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

Excluding exception mappers in the Arc results in NoSuchMethodException #29403

Closed
ivansenic opened this issue Nov 22, 2022 · 22 comments
Closed
Assignees
Labels
area/rest kind/bug Something isn't working

Comments

@ivansenic
Copy link
Contributor

ivansenic commented Nov 22, 2022

Describe the bug

When a dependency defines exception mappers, the exclusion using the -Dquarkus.arc.exclude-types does not work. Even worse, it's ending up in the NoSuchMethodException.

The exception mapper is defined as:

package io.stargate.sgv2.api.common.exception;

import ...

public class WebApplicationExceptionMapper {

  @ServerExceptionMapper
  public Response webApplicationException(WebApplicationException exception) {
     ...
  }
}

Exclusions that we tried:

  • -Dquarkus.arc.exclude-types=io.stargate.sgv2.api.common.exception.*
  • -Dquarkus.arc.exclude-types=io.stargate.sgv2.api.common.exception.**

Stack trace below:

ERROR [vert.x-eventloop-thread-1] 2022-11-22 11:35:40,293 ResteasyReactiveRequestContext.java:636 - Request failed: java.lang.IllegalArgumentException: Unable to create class 'io.stargate.sgv2.api.common.exception.WebApplicationExceptionMapper$GeneratedExceptionHandlerFor$WebApplicationException$OfMethod$webApplicationException'. To fix the problem, make sure this class is a CDI bean.
	at io.quarkus.resteasy.reactive.common.runtime.ArcBeanFactory.createInstance(ArcBeanFactory.java:41)
	at org.jboss.resteasy.reactive.server.core.RuntimeExceptionMapper.doGetExceptionMapper(RuntimeExceptionMapper.java:238)
	at org.jboss.resteasy.reactive.server.core.RuntimeExceptionMapper.getExceptionMapper(RuntimeExceptionMapper.java:217)
	at org.jboss.resteasy.reactive.server.core.RuntimeExceptionMapper.mapException(RuntimeExceptionMapper.java:79)
	at org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext.mapExceptionIfPresent(ResteasyReactiveRequestContext.java:343)
	at org.jboss.resteasy.reactive.server.handlers.ExceptionHandler.handle(ExceptionHandler.java:15)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:124)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:142)
	at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:51)
	at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:18)
	at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:8)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:136)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:173)
	at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:73)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$1.handle(StaticResourcesRecorder.java:58)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$1.handle(StaticResourcesRecorder.java:53)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:136)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:173)
	at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:73)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$1.handle(StaticResourcesRecorder.java:58)
	at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$1.handle(StaticResourcesRecorder.java:53)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.doPermissionCheck(HttpAuthorizer.java:117)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer$2.accept(HttpAuthorizer.java:134)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer$2.accept(HttpAuthorizer.java:123)
	at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
	at io.smallrye.mutiny.helpers.UniCallbackSubscriber.onItem(UniCallbackSubscriber.java:77)
	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.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.drain(UniMemoizeOp.java:160)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.onItem(UniMemoizeOp.java:180)
	at io.smallrye.mutiny.operators.uni.UniOnTermination$UniOnTerminationProcessor.onItem(UniOnTermination.java:39)
	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.UniMemoizeOp.drain(UniMemoizeOp.java:160)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.onItem(UniMemoizeOp.java:180)
	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.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.access$100(UniCreanownItem.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.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:84)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnTermination.subscribe(UniOnTermination.java:21)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:84)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:52)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:112)
	at io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:89)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.doPermissionCheck(HttpAuthorizer.java:123)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer.checkPermission(HttpAuthorizer.java:100)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer_Subclass.checkPermission$$superforward1(Unknown Source)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer_Subclass$$function$$1.apply(Unknown Source)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:51)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(Unknown Source)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:33)
	at io.quarkus.vertx.http.runtime.security.HttpAuthorizer_Subclass.checkPermission(Unknown Source)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$3.handle(HttpSecurityRecorder.java:233)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$3.handle(HttpSecurityRecorder.java:225)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:206)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:60)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.handle(VertxHttpHotReplacementSetup.java:196)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.handle(VertxHttpHotReplacementSetup.java:185)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.RuntimeException: java.lang.NoSuchMethodException: io.stargate.sgv2.api.common.exception.WebApplicationExceptionMapper$GeneratedExceptionHandlerFor$WebApplicationException$OfMethod$webApplicationException.<init>()
	at io.quarkus.arc.runtime.BeanContainerImpl$DefaultInstanceFactory.create(BeanContainerImpl.java:76)
	at io.quarkus.resteasy.reactive.common.runtime.ArcBeanFactory.createInstance(ArcBeanFactory.java:27)
	... 124 more
Caused by: java.lang.NoSuchMethodException: io.stargate.sgv2.api.common.exception.WebApplicationExceptionMapper$GeneratedExceptionHandlerFor$WebApplicationException$OfMethod$webApplicationException.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3585)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
	at io.quarkus.arc.runtime.BeanContainerImpl$DefaultInstanceFactory.create(BeanContainerImpl.java:68)
	... 125 more

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.13.4.Final

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

No response

Additional information

No response

@ivansenic ivansenic added the kind/bug Something isn't working label Nov 22, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Nov 22, 2022

/cc @manovotn, @mkouba

@quarkus-bot quarkus-bot bot added the area/arc Issue related to ARC (dependency injection) label Nov 22, 2022
@smrtyvz
Copy link

smrtyvz commented Nov 22, 2022

Hi Ivan,

Have you tried to exclude it with class path in application.properties as it is described here

Like :
quarkus.arc.exclude-types=io.stargate.sgv2.api.common.exception.WebApplicationExceptionMapper

@mkouba
Copy link
Contributor

mkouba commented Nov 22, 2022

If you exclude the exception mapper class via quarkus.arc.exclude-types then resteasy-reactive attempts to use the no-args constructor to create a mapper instance but fails with java.lang.NoSuchMethodException: io.stargate.sgv2.api.common.exception.WebApplicationExceptionMapper$GeneratedExceptionHandlerFor$WebApplicationException$OfMethod$webApplicationException.<init>().

To be honest, I'm not quite sure this is a supported use case.

@mkouba mkouba added area/rest and removed area/arc Issue related to ARC (dependency injection) labels Nov 22, 2022
@mkouba
Copy link
Contributor

mkouba commented Nov 22, 2022

CC @geoand @FroMage

@geoand
Copy link
Contributor

geoand commented Nov 22, 2022

Yeah, I wouldn't say this is really supported.
What exactly are you trying to accomplish?

@ivansenic
Copy link
Contributor Author

I want to have the generic mappers in a common-project. But then let anybody use that commons project and avoid having predefined mappers and create their own.

Can I can control mapper inclusion with a property, for example:

@LookupIfProperty(name = "stargate.exception-mappers.enabled", stringValue = "true", lookupIfMissing = true)
@ServerExceptionMapper
...

Or is there any other way to conditionally register an exception mapper?

@geoand
Copy link
Contributor

geoand commented Nov 23, 2022

That's what I thought. In that case, this looks like a duplicate of #29115, do you agree?

With Quarkus 2.14.1.Final, annotations @IfBuildProfile, @UnlessBuildProfile, @IfBuildProperty and @UnlessBuildProperty are taken into account when added to a class (but I think it won't work when added on a method, I will look into fixing that).

@geoand
Copy link
Contributor

geoand commented Nov 23, 2022

It looks like adding support for @IfBuildProfile, @UnlessBuildProfile, @IfBuildProperty and @UnlessBuildProperty on methods annotated with @ServerRequestFilter is going to be very messy, so for now, I'll just make it a build time error.
It's definitely not ideal, but it will at least make it clear to users what is supported and what's not.

geoand added a commit to geoand/quarkus that referenced this issue Nov 23, 2022
…n methods

Although we can make this work in the future, it involves a fair amount of work
for a very small gain, so let's make it explicit for now that this combination
is not allowed.

Follows up on: quarkusio#29118
Relates to: quarkusio#29403
@ivansenic
Copy link
Contributor Author

It looks like adding support for @IfBuildProfile, @UnlessBuildProfile, @IfBuildProperty and @UnlessBuildProperty on methods annotated with @ServerRequestFilter is going to be very messy, so for now, I'll just make it a build time error.
It's definitely not ideal, but it will at least make it clear to users what is supported and what's not.

What about @LookupIfProperty, would this be easier?

@geoand
Copy link
Contributor

geoand commented Nov 23, 2022

I have actually never used @LookupIfProperty (and even forgot it existed)...

Unfortunately no, it would not make things any easier

@ivansenic
Copy link
Contributor Author

OK, but I still assume that if I move the exception mappers to JAX-RS style with ExceptionMapper<T> and then conditionally have the producer method for it. Right? This has to work?

@geoand
Copy link
Contributor

geoand commented Nov 23, 2022

Ah damn it... I thought we were talking about filters here, 🤦🏼 .

It does seem like we'll need to do the same thing for exception mappers as the combination of annotation is currently not supported.

You can't have a producer method for JAX-RS style exception mappers, they aren't registered like that.

@geoand
Copy link
Contributor

geoand commented Nov 23, 2022

After looking at this, I have concluded that we will need a smarter way of handling both the filters and exception mappers case.

I need to sleep on how that can be done

@geoand geoand self-assigned this Nov 23, 2022
@geoand
Copy link
Contributor

geoand commented Nov 24, 2022

#29459 takes care of the issue

@ivansenic
Copy link
Contributor Author

Any idea when #29459 will be merged and in what version can we expect the fix?

@geoand
Copy link
Contributor

geoand commented Dec 5, 2022

It will be part of 2.15.0.Final

geoand added a commit that referenced this issue Dec 5, 2022
Take conditional annotation into account for @ServerExceptionMapper
@ivansenic
Copy link
Contributor Author

But wait this now only throws the build exception if the annotations are combined? There is still no support for this?

[error]: Build step io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#handleCustomAnnotatedMethods threw an exception: java.lang.RuntimeException: The combination of '@IfBuildProperty' and '@ServerExceptionMapper' is not allowed. Offending method is 'statusRuntimeException' of class 'io.stargate.sgv2.api.common.exception.StatusRuntimeExceptionMapper'

@geoand
Copy link
Contributor

geoand commented Dec 15, 2022

You can't use @IfBuildProperty on the method, you can only use it on the class

@ivansenic
Copy link
Contributor Author

Ahh, OK let me try this :)

@geoand
Copy link
Contributor

geoand commented Jan 10, 2023

Are we good to close this now?

@ivansenic
Copy link
Contributor Author

Are we good to close this now?

Definitely

@geoand
Copy link
Contributor

geoand commented Jan 10, 2023

Great, thanks

@geoand geoand closed this as completed Jan 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants