Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassNotFoundException when scheduler calls static @Transactional PanacheEntity method #32990

Closed
neon-dev opened this issue Apr 28, 2023 · 12 comments · Fixed by #33084
Closed
Labels
area/devmode area/panache area/scheduler env/windows Impacts Windows machines kind/bug Something isn't working
Milestone

Comments

@neon-dev
Copy link
Contributor

Describe the bug

The following method cannot be called from a @Scheduled annotated method, if the entity class is imported from a lib and not part of the same source:

@Entity
public class ExternalEntity extends PanacheEntity {
    ...
    @Transactional
    public static long doStuff() { ... }
}

Expected behavior

This call should work without throwing an exception:

@Scheduled(every = "1h")
public void run() {
  ExternalEntity.doStuff();
}

Actual behavior

Class not found:

2023-04-28 15:31:41,012 ERROR [io.qua.sch.com.run.StatusEmitterInvoker] (vert.x-worker-thread-0) Error occurred while executing task for trigger IntervalTrigger [id=1_org.acme.Reproducer_ScheduledInvoker_run_72e66771a77415a7284d3ae42331659c186071de, interval=3600000]: java.util.concurrent.CompletionException: java.lang.NoClassDefFoundError: org/acme/entity/Entity_InterceptorInitializer
        at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:332)
        at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:347)
        at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:874)
        at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:887)
        at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2325)
        at java.base/java.util.concurrent.CompletableFuture$MinimalStage.whenComplete(CompletableFuture.java:2902)
        at io.quarkus.scheduler.common.runtime.DefaultInvoker.invoke(DefaultInvoker.java:24)
        at io.quarkus.scheduler.common.runtime.StatusEmitterInvoker.invoke(StatusEmitterInvoker.java:35)
        at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask.doInvoke(SimpleScheduler.java:333)
        at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask$1.handle(SimpleScheduler.java:314)
        at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask$1.handle(SimpleScheduler.java:310)
        at io.vertx.core.impl.ContextBase.lambda$null$0(ContextBase.java:137)
        at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
        at io.vertx.core.impl.ContextBase.lambda$executeBlocking$1(ContextBase.java:135)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoClassDefFoundError: org/acme/entity/Entity_InterceptorInitializer
        at org.acme.entity.Entity.deleteByField(Entity.java)
        at org.acme.Reproducer.run(Reproducer.java:13)
        at org.acme.Reproducer_ClientProxy.run(Unknown Source)
        at org.acme.Reproducer_ScheduledInvoker_run_72e66771a77415a7284d3ae42331659c186071de.invokeBean(Unknown Source)
        ... 15 more
Caused by: java.lang.ClassNotFoundException: org.acme.entity.Entity_InterceptorInitializer
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:516)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:466)
        ... 19 more

How to Reproduce?

  1. Download & unzip reproducer.zip
  2. mvn -f entity/pom.xml install
  3. mvn -f app/pom.xml quarkus:dev

Output of uname -a or ver

Microsoft Windows [Version 10.0.19045.2728]

Output of java -version

openjdk version "17.0.6" 2023-01-17

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.16.6.Final & 3.0.1.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Maven 3.8.1

Additional information

Tested with:
JDBC extension: quarkus-jdbc-h2 & quarkus-jdbc-mysql
Panache extension: quarkus-hibernate-orm-panache (reactive untested)
Scheduler extension: quarkus-scheduler

Possible workarounds:
Move the entity class or the @Transactional annotation into the main project.

@neon-dev neon-dev added the kind/bug Something isn't working label Apr 28, 2023
@quarkus-bot
Copy link

quarkus-bot bot commented Apr 28, 2023

/cc @FroMage (panache), @loicmathieu (panache), @mkouba (scheduler)

@mkouba
Copy link
Contributor

mkouba commented May 1, 2023

Hm, the generated org.acme.entity.Entity_InterceptorInitializer is a public class so I suspect there's something related to the fact that org.acme.entity.Entity is also transformed by Panache...

@mkouba
Copy link
Contributor

mkouba commented May 1, 2023

Hm, the generated org.acme.entity.Entity_InterceptorInitializer is a public class so I suspect there's something related to the fact that org.acme.entity.Entity is also transformed by Panache...

I've tried to extract the intercepted static method in a separate class and still can see the same NCDFE. So it's likely not related to the bytecode transformation...

@mkouba
Copy link
Contributor

mkouba commented May 1, 2023

And it fails with quarkus 3.0.1.Final too..

@mkouba
Copy link
Contributor

mkouba commented May 2, 2023

So the Base Runtime ClassLoader does not see the generated classes (which are hot deployable resources) by design. It only supports transformations, which are expected to be idempotent? I would argue that generated classes for external libraries should be idempotent as well but maybe I'm missing something 🤷.

CC @stuartwdouglas @gsmet @geoand @aloubyansky ...

@geoand
Copy link
Contributor

geoand commented May 2, 2023

There is a flag in the build item that allows you to make generated classes part of the application ClassLoader.

Have you tried it?

@mkouba
Copy link
Contributor

mkouba commented May 2, 2023

There is a flag in the build item that allows you to make generated classes part of the application ClassLoader.

Have you tried it?

I don't think that GeneratedClassBuildItem.applicationClass is being considered when ClassLoaders are created... in other words, a generated class is always loaded by the runtime ClassLoader; and the base runtime CL is the parent of this CL... so it would not help anyway because in this particular case a class from an external library attempts to load a generated class.

@stuartwdouglas
Copy link
Member

That is exactly that this flag does, if it is false it is loaded by the base runtime CL, not the runtime CL.

@mkouba
Copy link
Contributor

mkouba commented May 3, 2023

That is exactly that this flag does, if it is false it is loaded by the base runtime CL, not the runtime CL.

Ok, thanks. I think that I found the problem: https://github.com/quarkusio/quarkus/blob/main/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/staticmethods/InterceptedStaticMethodsProcessor.java#L157 and fix is on the way...

Out of curiosity, where's the place where the GeneratedClassBuildItem.applicationClass is used to affect the behavior of a ClassLoader?

@stuartwdouglas
Copy link
Member

if (i.isApplicationClass() == applicationClasses) {

@mkouba
Copy link
Contributor

mkouba commented May 3, 2023

if (i.isApplicationClass() == applicationClasses) {

👍 thanks!

mkouba added a commit to mkouba/quarkus that referenced this issue May 3, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990
mkouba added a commit to mkouba/quarkus that referenced this issue May 3, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990
mkouba added a commit to mkouba/quarkus that referenced this issue May 3, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990
@quarkus-bot quarkus-bot bot added this to the 3.1 - main milestone May 4, 2023
@neon-dev
Copy link
Contributor Author

neon-dev commented May 4, 2023

Thanks a lot! Keep up the great work.

holly-cummins pushed a commit to holly-cummins/quarkus that referenced this issue May 5, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990
@gsmet gsmet modified the milestones: 3.1 - main, 3.0.3.Final May 9, 2023
gsmet pushed a commit to gsmet/quarkus that referenced this issue May 9, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990

(cherry picked from commit fd48630)
manofthepeace pushed a commit to manofthepeace/quarkus that referenced this issue May 16, 2023
- fix the problem with dev mode and external libraries
- also make sure the generated method does not start with a number
- fixes quarkusio#32990
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/devmode area/panache area/scheduler env/windows Impacts Windows machines kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants