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 injecting REST client in native #20896

Closed
andlinger opened this issue Oct 20, 2021 · 16 comments · Fixed by #21148
Closed

ClassNotFoundException when injecting REST client in native #20896

andlinger opened this issue Oct 20, 2021 · 16 comments · Fixed by #21148
Assignees
Labels
Milestone

Comments

@andlinger
Copy link
Contributor

andlinger commented Oct 20, 2021

Describe the bug

When I inject the Resteasy REST client a ClassNotFoundException occurs. But this only happens in a native app.

Expected behavior

No response

Actual behavior

The injection fails with the following exception:

org.jboss.resteasy.spi.UnhandledException: java.lang.RuntimeException: Error injecting me.package.backend.clients.ChVatClient me.package.backend.services.VatService.chVatClient
        at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
        at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
        at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:218)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:519)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
        at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:135)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:81)
        at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:41)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
        at io.quarkus.vertx.http.runtime.StaticResourcesRecorder.lambda$start$1(StaticResourcesRecorder.java:67)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:351)
        at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:329)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
        at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.doPermissionCheck(HttpAuthorizer.java:121)
        at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.checkPermission(HttpAuthorizer.java:104)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$3.handle(HttpSecurityRecorder.java:218)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$3.handle(HttpSecurityRecorder.java:210)
        at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
        at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
        at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2$2$1.onItem(HttpSecurityRecorder.java:128)
        at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2$2$1.onItem(HttpSecurityRecorder.java:118)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:60)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:60)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.access$100(UniCreateFromKnownItem.java:26)
        at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)
        at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:81)
        at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
        at io.smallrye.mutiny.operators.uni.builders.DefaultUniEmitter.complete(DefaultUniEmitter.java:36)
        at io.quarkus.security.runtime.QuarkusIdentityProviderManagerImpl$1$1$1$1.run(QuarkusIdentityProviderManagerImpl.java:58)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
        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.lang.Thread.run(Thread.java:833)
        at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:596)
        at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: java.lang.RuntimeException: Error injecting me.package.backend.clients.ChVatClient me.package.backend.services.VatService.chVatClient
        at me.package.backend.services.VatService_Bean.create(VatService_Bean.zig:423)
        at me.package.backend.services.VatService_Bean.create(VatService_Bean.zig:618)
        at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
        at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
        at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
        at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:17)
        at me.package.backend.services.VatService_ClientProxy.arc$delegate(VatService_ClientProxy.zig:67)
        at me.package.backend.services.VatService_ClientProxy.get(VatService_ClientProxy.zig:188)
        at me.package.backend.resources.VatResource.verify(VatResource.java:36)
        at me.package.backend.resources.VatResource_Subclass.verify$$superforward1(VatResource_Subclass.zig:148)
        at me.package.backend.resources.VatResource_Subclass$$function$$1.apply(VatResource_Subclass$$function$$1.zig:33)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
        at io.quarkus.security.runtime.interceptor.SecurityHandler.handle(SecurityHandler.java:21)
        at io.quarkus.security.runtime.interceptor.DenyAllInterceptor.intercept(DenyAllInterceptor.java:30)
        at io.quarkus.security.runtime.interceptor.DenyAllInterceptor_Bean.intercept(DenyAllInterceptor_Bean.zig:378)
        at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:50)
        at io.quarkus.security.runtime.interceptor.SecurityHandler.handle(SecurityHandler.java:24)
        at io.quarkus.security.runtime.interceptor.PermitAllInterceptor.intercept(PermitAllInterceptor.java:23)
        at io.quarkus.security.runtime.interceptor.PermitAllInterceptor_Bean.intercept(PermitAllInterceptor_Bean.zig:327)
        at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
        at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
        at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
        at me.package.backend.resources.VatResource_Subclass.verify(VatResource_Subclass.zig:212)
        at me.package.backend.resources.VatResource_ClientProxy.verify(VatResource_ClientProxy.zig:103)
        at java.lang.reflect.Method.invoke(Method.java:568)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
        at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
        at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
        ... 49 more
Caused by: org.apache.commons.logging.LogConfigurationException: java.lang.ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl (Caused by java.lang.ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl)
        at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1158)
        at org.apache.commons.logging.LogFactory$2.run(LogFactory.java:960)
        at java.security.AccessController.doPrivileged(AccessController.java:87)
        at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:957)
        at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:624)
        at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:655)
        at org.apache.http.conn.ssl.DefaultHostnameVerifier.<init>(DefaultHostnameVerifier.java:82)
        at org.apache.http.conn.ssl.DefaultHostnameVerifier.<init>(DefaultHostnameVerifier.java:91)
        at org.jboss.resteasy.client.jaxrs.engines.ClientHttpEngineBuilder43.build(ClientHttpEngineBuilder43.java:74)
        at org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl.build(ResteasyClientBuilderImpl.java:415)
        at io.quarkus.restclient.runtime.QuarkusRestClientBuilder.build(QuarkusRestClientBuilder.java:332)
        at io.quarkus.restclient.runtime.RestClientBase.create(RestClientBase.java:69)
        at me.package.backend.clients.ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.create(ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.zig:189)
        at me.package.backend.clients.ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.create(ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.zig:205)
        at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
        at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
        at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
        at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
        at me.package.backend.clients.ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.get(ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.zig:237)
        at me.package.backend.clients.ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.get(ChVatClient_0a8d71f9d2df9a04b0757deaf2ed6aa0a03a5ff1_Synthetic_Bean.zig:253)
        at me.package.backend.services.VatService_Bean.create(VatService_Bean.zig:406)
        ... 88 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl
        at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:53)
        at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:139)
        at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1020)
        ... 110 more

How to Reproduce?

No response

Output of uname -a or ver

Darwin Kernel Version 20.6.0

Output of java -version

openjdk version "17.0.1" 2021-10-19 OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05) OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

21.3

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

------------------------------------------------------------ Gradle 7.2 ------------------------------------------------------------ Build time: 2021-08-17 09:59:03 UTC Revision: a773786b58bb28710e3dc96c4d1a7063628952ad Kotlin: 1.5.21 Groovy: 3.0.8 Ant: Apache Ant(TM) version 1.10.9 compiled on September 27 2020 JVM: 17.0.1 (GraalVM Community 17.0.1+12-jvmci-21.3-b05) OS: Mac OS X 11.6 x86_64

Additional information

The error occurs since Quarkus 2.3.0.Final.
I can also reproduce the error with Java 11 and GraalVM 21.2.

@andlinger andlinger added the kind/bug Something isn't working label Oct 20, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Oct 20, 2021

/cc @evanchooly, @michalszynkiewicz

@andlinger
Copy link
Contributor Author

I can fix the problem by ignoring the 'commons-logging' dependency in the REST client dependency manually:

implementation ('io.quarkus:quarkus-rest-client') {
  exclude group: 'commons-logging', module: 'commons-logging'
}

@michalszynkiewicz
Copy link
Member

@andlinger please attach a simple reproducer

@andlinger
Copy link
Contributor Author

@edufolly
Copy link

Same problem since Quarkus 2.3.0.

@michalszynkiewicz michalszynkiewicz self-assigned this Nov 2, 2021
@michalszynkiewicz
Copy link
Member

when I use java 11 and graal 21.2 with a docker image (the default build option if you do the build without graal installed locally) with maven, the native binary works for me.

How do you run with graalvm 21.3, is there a way to do it with docker/podman instead of a local graalvm installation?

@michalszynkiewicz
Copy link
Member

It looks like gradle for some reason doesn't honor the exclusion of commons-logging.

For gradle the relevant part of the dependency tree is:

\--- io.quarkus:quarkus-rest-client -> 2.3.1.Final
     +--- io.quarkus:quarkus-core:2.3.1.Final (*)
     +--- io.quarkus:quarkus-arc:2.3.1.Final (*)
     +--- io.quarkus:quarkus-resteasy-common:2.3.1.Final (*)
     +--- io.quarkus:quarkus-apache-httpclient:2.3.1.Final
     |    +--- io.quarkus:quarkus-arc:2.3.1.Final (*)
     |    +--- org.apache.httpcomponents:httpclient:4.5.13
     |    |    +--- org.apache.httpcomponents:httpcore:4.4.13 -> 4.4.14
     |    |    +--- commons-logging:commons-logging:1.2
     |    |    \--- commons-codec:commons-codec:1.11 -> 1.15

The dependency is excluded in Quarkus: https://github.com/quarkusio/quarkus/blob/2.3.1.Final/extensions/apache-httpclient/runtime/pom.xml#L20-L29 (and Maven honors this if we do a Maven project).

@michalszynkiewicz
Copy link
Member

@aloubyansky @gsmet do you maybe know why this happens?

@aloubyansky
Copy link
Member

@glefloch is this expected that the exclusion configured in the BOM is ignored in this case?

@glefloch
Copy link
Member

glefloch commented Nov 2, 2021

Yes, dependency exclusion does not work in the same way on gradle. If you want to know which module imports commons-logging, you can run ./gradlew dependencyInsights --dependency commons-logging. This result in:

commons-logging:commons-logging:1.2
\--- org.apache.httpcomponents:httpclient:4.5.13
     +--- io.quarkus:quarkus-bom:2.3.1.Final
     |    \--- compileClasspath
     +--- org.jboss.resteasy:resteasy-client:4.7.0.Final
     |    +--- io.quarkus:quarkus-bom:2.3.1.Final (*)
     |    \--- org.jboss.resteasy:resteasy-client-microprofile-base:4.7.0.Final
     |         \--- org.jboss.resteasy:resteasy-client-microprofile:4.7.0.Final
     |              +--- io.quarkus:quarkus-bom:2.3.1.Final (*)
     |              \--- io.quarkus:quarkus-rest-client:2.3.1.Final
     |                   +--- compileClasspath (requested io.quarkus:quarkus-rest-client)
     |                   \--- io.quarkus:quarkus-bom:2.3.1.Final (*)
     +--- io.quarkus:quarkus-apache-httpclient:2.3.1.Final
     |    +--- io.quarkus:quarkus-bom:2.3.1.Final (*)
     |    \--- io.quarkus:quarkus-rest-client:2.3.1.Final (*)
     \--- org.apache.httpcomponents:httpasyncclient:4.1.4 (requested org.apache.httpcomponents:httpclient:4.5.6)
          +--- io.quarkus:quarkus-bom:2.3.1.Final (*)
          \--- io.quarkus:quarkus-rest-client:2.3.1.Final (*)

It looks like we have something like:

quarkus-apache-httpclient --> httpclient (with exclude from pom) --> commons-logging
httpasyncclient --> httpclient (with exclude from pom).         --/
resteasy-client-microprofile --> ... --> resteasy-client       --/

As one module (resteasy-client-microprofile) requires commons logging, even though it has been excluded by quarkus-apache-httpclient and httpasyncclient, gradle will import it.
Excluding commons-logging from resteasy-client-microprofile in quarkus-restclient should fix the issue.
I will test that.

@vhmolinar
Copy link

I noticed that commons-logging (apache) dependecy was already in classpath since 1.x versions.
So, despite the need of excluding it, the problem actually started being perceived by us after something else got changed by 2.x versions.
Am I right?

ps: This sad issue is preventing a whole app upgrade to quarkus 2.x.

@jumolinaro
Copy link

Hi @vhmolinar, this issue didn't occur with Quarkus 2.1.4.Final.
Now I am trying to upgrade to Quarkus 2.4.1.Final and this ClassNotFoundException with commons logging is thrown in native mode only

@jumolinaro
Copy link

A workaround to "fix" this issue is exclusion of commons-logging in build.gradle for :

  • quarkus-rest-client
  • quarkus-rest-client-jackson
  • quarkus-oidc-token-propagation
  • quarkus-elasticsearch-rest-high-level-client

@quarkus-bot quarkus-bot bot added this to the 2.5 - main milestone Nov 4, 2021
@gsmet gsmet modified the milestones: 2.5.0.CR1, 2.4.2.Final Nov 11, 2021
@vhmolinar
Copy link

Hello @gsmet @glefloch ;

The fix had solved the issue until I added a new quarkus extension (quarkus-keycloak-admin-client) which brought back commons-logging dependencies.

So it seems that it is not okay yet. Should this be reopened?

@michalszynkiewicz
Copy link
Member

@vhmolinar Even though the fix is similar, it should be a different issue, not this one reopened, IMO.
Could you create a pull request for it?

@vhmolinar
Copy link

@michalszynkiewicz thanks for asking me. I managed to do my first direct contribution #21627

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants