Unpredictable reactive controller behavior.
See original GitHub issueDescribe the bug
I decided to refactor one of my service written in quarkus from blocking io to reactive manner.
I have many mock controller which works perfectly before refactor but now some of them throws errors:
java.lang.NullPointerException: Cannot invoke "org.jboss.resteasy.reactive.server.mapping.RuntimeResource.getResourceClass()" because the return value of "org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext.getTarget()" is null
at org.jboss.resteasy.reactive.server.core.ExceptionMapping.logBlockingErrorIfRequired(ExceptionMapping.java:103)
at org.jboss.resteasy.reactive.server.core.ExceptionMapping.mapException(ExceptionMapping.java:95)
at org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext.mapExceptionIfPresent(ResteasyReactiveRequestContext.java:340)
at org.jboss.resteasy.reactive.server.handlers.ExceptionHandler.handle(ExceptionHandler.java:15)
at org.jboss.resteasy.reactive.server.handlers.ExceptionHandler.handle(ExceptionHandler.java:9)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141)
at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:47)
at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:17)
at org.jboss.resteasy.reactive.server.vertx.ResteasyReactiveVertxHandler.handle(ResteasyReactiveVertxHandler.java:7)
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.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:55)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:37)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$10.handle(VertxHttpRecorder.java:443)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$10.handle(VertxHttpRecorder.java:440)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:151)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$1.handle(VertxHttpRecorder.java:133)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:50)
at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:168)
at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:143)
at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:155)
at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:154)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
at io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xUpgradeToH2CHandler.channelRead(Http1xUpgradeToH2CHandler.java:116)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)
at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795)
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
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:831)
For example this controller doesn’t work:
package pl.test.rest.recaptcha;
import io.smallrye.mutiny.Uni;
import pl.test.rest.recaptcha.model.SiteVerifyResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Date;
@Path("/recaptcha/api/siteverify")
public class MockResource {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Uni<SiteVerifyResponse> siteVerify(@FormParam("response") String response
, @FormParam("secret") String secret, @FormParam("remoteip") String remoteip) {
return Uni.createFrom().item(SiteVerifyResponse.builder()
.success(true)
.score((float) 1.0)
.action("ACTION")
.hostname("localhost")
.challengeTs(new Date())
.build());
}
}
But this work’s:
package pl.test.rest.dotpay;
import io.smallrye.mutiny.Uni;
import lombok.val;
import pl.test.rest.dotpay.model.PaymentEntry;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.List;
@Path("/s2/login/api/purchase_history/")
public class MockResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<PaymentEntry>> api(@QueryParam("email") String email) {
return Uni.createFrom().item(Collections.singletonList(createPaymentEntry()));
}
private PaymentEntry createPaymentEntry() {
val entry = new PaymentEntry();
entry.setDate("2018-06-09T16:54:15.855823");
entry.setAmount("8.29");
entry.setCurrency("PLN");
entry.setStatus("completed");
entry.setRequestIp("188.146.162.128");
entry.setMcc("4112");
entry.setChannel("73");
entry.setMerchantId("5d51e2dc7bc76cf9841d82ba404d134646bdbd97");
return entry;
}
}
The one thing what I’am done in refactor is change the return type to new one with wrapper Uni.
I found on network similar error: https://github.com/quarkusio/quarkus/runs/3204982867
Expected behavior
No response
Actual behavior
No response
How to Reproduce?
No response
Output of uname -a
or ver
Linux 5.13.0-20-generic #20-Ubuntu SMP Fri Oct 15 14:21:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Output of java -version
16.0.2
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.4.0.Final
Build tool (ie. output of mvnw --version
or gradlew --version
)
Apache Maven 3.6.2
Additional information
No response
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (3 by maintainers)
Top Results From Across the Web
Reactive Behaviors in Dogs - Symptoms, Causes, Diagnosis ...
Dogs that overreact in response to certain stimuli are known as reactive. Most reactive dogs can become somewhat calmer and happier animals with...
Read more >How to turn your child's reactive, inflexible behavior around
Parenting a child who gets reactive, constantly disagrees, and pushes back gets exhausting. This strategy shows you how to meet them calmly.
Read more >Reforming a Reactive Dog - Whole Dog Journal
Dogs are called leash-reactive when the frustration caused by a restrictive leash overwhelms them (see Feisty Fido by Patricia McConnell).
Read more >6 Ways to Calm Your Reactive Dog - Wags & Wiggles
Reactivity is when a dog over reacts to things in their environment. These reactions can include: barking, lunging, and growling.
Read more >A Beginner's Guide to Helping Your Reactive Dog Get Better
Aversives work to suppress behavior, but do nothing to change the underlying problem that caused the behavior. In fact, the dog may become...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Ok I’am closing this issue.
If you are trying to read the entire body of the request on the event loop thread, then yes, that is still not allowed