quarkus: Reactive Client ResponseExceptionMapper throws BlockingNotAllowedException when consuming an InputStream
Describe the bug
When trying to read the response entity in an ResponseExceptionMapper
, a BlockingNotAllowedException
is thrown IF the return type of the call is an InputStream
. It works fine with String
.
My Application subclass is annotated @Blocking
and I can also do blocking operations like a Thread.sleep
in the ExceptionMapper
Expected behavior
InputStreams can be handled
Actual behavior
Using response.readEntity(JsonNode.class)
in a ResponseExceptionMapper
throws a BlockingNotAllowedException
when the response type is InputStream
How to Reproduce?
see https://github.com/ssaip/quarkus-reactive-client-inputstream-blocking
org.jboss.resteasy.reactive.common.core.BlockingNotAllowedException: Attempting a blocking read on io thread
at org.jboss.resteasy.reactive.client.handlers.VertxClientInputStream$VertxBlockingInput.readBlocking(VertxClientInputStream.java:199)
at org.jboss.resteasy.reactive.client.handlers.VertxClientInputStream.readIntoBuffer(VertxClientInputStream.java:81)
at org.jboss.resteasy.reactive.client.handlers.VertxClientInputStream.read(VertxClientInputStream.java:62)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:539)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:133)
at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:256)
at com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1685)
at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1084)
at com.fasterxml.jackson.databind.ObjectReader.createParser(ObjectReader.java:1103)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1481)
at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.ServerJacksonMessageBodyReader.doReadFrom(ServerJacksonMessageBodyReader.java:87)
at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.ServerJacksonMessageBodyReader.readFrom(ServerJacksonMessageBodyReader.java:38)
at org.jboss.resteasy.reactive.client.impl.ClientReaderInterceptorContextImpl.proceed(ClientReaderInterceptorContextImpl.java:67)
at org.jboss.resteasy.reactive.client.impl.ClientSerialisers.invokeClientReader(ClientSerialisers.java:160)
at org.jboss.resteasy.reactive.client.impl.ClientResponseImpl.readEntity(ClientResponseImpl.java:59)
at org.jboss.resteasy.reactive.common.jaxrs.ResponseImpl.readEntity(ResponseImpl.java:129)
at com.example.BlockingResponseExceptionMapper.toThrowable(BlockingResponseExceptionMapper.java:24)
at com.example.BlockingResponseExceptionMapper.toThrowable(BlockingResponseExceptionMapper.java:10)
at com.example.BlockingResponseExceptionMapper_ClientProxy.toThrowable(Unknown Source)
at io.quarkus.rest.client.reactive.runtime.MicroProfileRestClientResponseFilter.filter(MicroProfileRestClientResponseFilter.java:36)
at org.jboss.resteasy.reactive.client.handlers.ClientResponseFilterRestHandler.handle(ClientResponseFilterRestHandler.java:21)
at org.jboss.resteasy.reactive.client.handlers.ClientResponseFilterRestHandler.handle(ClientResponseFilterRestHandler.java:10)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.invokeHandler(AbstractResteasyReactiveContext.java:229)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
at org.jboss.resteasy.reactive.client.impl.RestClientRequestContext$1.lambda$execute$0(RestClientRequestContext.java:279)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:246)
at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:43)
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:566)
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:829)
Output of uname -a
or ver
No response
Output of java -version
Java version: 11.0.17, vendor: Azul Systems, Inc.
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.15.3.Final
Build tool (ie. output of mvnw --version
or gradlew --version
)
apache-maven-3.8.6
Additional information
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 29 (18 by maintainers)
Commits related to this issue
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 Do not run if it's suspended asd — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 Do not run if it's suspended asd — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to Sgitario/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 — committed to rpelisse/quarkus by Sgitario a year ago
- Support blocking exception mappers in REST Client Reactive Fix https://github.com/quarkusio/quarkus/issues/30312 (cherry picked from commit 97e101b526ab82db414e6180e6bd3c20d3d27c85) — committed to gsmet/quarkus by Sgitario a year ago
- chore(deps): update all non-major dependencies (mulk/quarkus-googlecloud-jsonlogging!15) This MR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [io.quarkus:... — committed to benkard/quarkus-googlecloud-jsonlogging by deleted user a year ago
While this was working in my sample project, I still couldn’t get it to work in the real project. I’ll keep this here and maybe it saves someone else some hours in the future.
I figured out that my
ResponseExceptionMapper
always got_subclass
’d because I was usingjakarta.validation
annotations there and had theio.quarkus:quarkus-hibernate-validator
dependency on the classpath, therefore this class was always getting proxied to intercept for validations.And because of that, the
@Blocking
annotation was no longer present and the ResponseExceptionMapper was run on the io thread. Unfortunately, there is no way to fix the annotations for sub/proxied classes (a topic that I originally came across when investigating the cause of this issue 😄 see https://github.com/quarkusio/quarkus/issues/30327)Anyway, removing annotations like
@NotNull
, will prevent subclassing and the@Blocking
ResponseExceptionMapper
will run on a worker-thread as expected.This is caused because the exception mapper is a bean (it’s using the
@ApplicationScoped
annotation). This can be easily fixed. Tho, @ssaip if you replace@ApplicationScoped
with@Provider
as noted in the guide, it will work fine.Okay. Asking because this issue is specific to the client.
Please open a new issue and attach a sample application that exhibits the problem you are seeing in the server which although looks similar, has a different root cause and is likely easy to fix).
We didn’t change anything, so, for sure, the bug is still there.
Unfortunately, I don’t see a good approach to fix it, except requiring an
@Blocking
annotation (or a blocking mapper interface) and delegating the invocation of this mapper on a worker thread.@Sgitario @geoand WDYT?