Alex Alex - 9 months ago 127
reST (reStructuredText) Question

Jersey throws NPE for each call after using ContainerRequestContext.abortWith()

I have a RESTful endpoint which I secured with a simple authorization check via a custom ContainerRequestFilter. The filter checks if all the information contained in the HTTP session is correct and if not it executes this:

requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
.entity("Forbidden").build());


This is all fine and dandy. The strange thing is that when I make the same GET request again the Jersey server reports an NPE and does not return anything.

The NPE stacktrace:

Jul 20, 2016 5:27:53 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
java.lang.IllegalStateException: The output stream has already been closed.
at org.glassfish.jersey.message.internal.CommittingOutputStream.setStreamProvider(CommittingOutputStream.java:147)
at org.glassfish.jersey.message.internal.OutboundMessageContext.setStreamProvider(OutboundMessageContext.java:803)
at org.glassfish.jersey.server.ContainerResponse.setStreamProvider(ContainerResponse.java:372)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:694)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)


What is happening? I dont want to close the output stream. I only need a method to return a http return code + message to the requester.

Answer Source

In case anyone would ever face the same issue I had here's the answer: you cannot re-use Responses! The output stream writer's instance is bound to the Request and as soon as you use it in abortWith() the stream will be committed forever. As such it can no longer be used to send responses.

You need to initialize a new Request from within the filter() method.

in simple terms, do not use such constructs:

 private static final Response ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN)
            .entity("Access blocked for all users !!").build();

btw, I've picken up this broken piece of code here: http://howtodoinjava.com/jersey/jersey-rest-security/ So be wary when implementing this RequestFilter.