When an exception happens in the writers, we've already set the response HTTP status code and headers, but we switch to the exception handler which tries to send the exception and doesn't notice the reponse is already committed, so we get an exception on the server side and the client gets nothing:
class FroMage {
// private is what's causing the exception
private String name;
public FroMage(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cheese: " + name;
}
}
@Path("negotiated")
public class Endpoint {
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
@GET
public FroMage get(){
return new FroMage("Morbier");
}
}
2020-12-10 09:24:20,580 ERROR [org.jbo.res.rea.com.cor.AbstractResteasyReactiveContext] (vert.x-eventloop-thread-8) Request failed: java.lang.IllegalStateException: Response head already sent
at io.vertx.core.http.impl.HttpServerResponseImpl.checkHeadWritten(HttpServerResponseImpl.java:638)
at io.vertx.core.http.impl.HttpServerResponseImpl.setStatusCode(HttpServerResponseImpl.java:132)
at org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext.setStatusCode(VertxResteasyReactiveRequestContext.java:220)
at org.jboss.resteasy.reactive.server.core.ServerSerialisers.encodeResponseHeaders(ServerSerialisers.java:445)
at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:35)
at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:15)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:108)
at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:47)
at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$5.handle(ResteasyReactiveRecorder.java:121)
at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$5.handle(ResteasyReactiveRecorder.java:118)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:326)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:304)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:86)
at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:75)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:327)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
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:834)
Note that the jackson exception that complains about FroMage not being registered, or not in fact having fields, is lost and not visible, but it's:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.acme.rest.FroMage and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4409)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:3621)
at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.JacksonMessageBodyWriter.writeResponse(JacksonMessageBodyWriter.java:67)
at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:175)
at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:157)
at org.jboss.resteasy.reactive.server.core.serialization.FixedEntityWriterArray.write(FixedEntityWriterArray.java:28)
at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:32)
at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:15)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:108)
at org.jboss.resteasy.reactive.server.handlers.RestInitialHandler.beginProcessing(RestInitialHandler.java:47)
at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$5.handle(ResteasyReactiveRecorder.java:121)
at io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveRecorder$5.handle(ResteasyReactiveRecorder.java:118)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:326)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$4.handle(VertxHttpRecorder.java:304)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1036)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:131)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:132)
at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:86)
at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:75)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:327)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
...
When an exception happens in the writers, we've already set the response HTTP status code and headers, but we switch to the exception handler which tries to send the exception and doesn't notice the reponse is already committed, so we get an exception on the server side and the client gets nothing:
Note that the jackson exception that complains about
FroMage
not being registered, or not in fact having fields, is lost and not visible, but it's:https://github.com/quarkusio/quarkus/issues/13797
$upstream:13797$