eclipse-ee4j/jersey

jersey 3.1 default exception mapper message interferes with setStatusOverSendError=true

sford opened this issue · 5 comments

We are currently using Jersey 2 and have jersey.config.server.response.setStatusOverSendError set to true so that we can post-process the response in a servlet filter when exceptions make their way out of Jersey and to a servlet filter.

Here is snippet from setStatusOverSendError docs explaining the behavior we are relying on:

However if you want to post-process response (e.g. by servlet filter) the only way to do it is calling setStatus(...) on container Response object.

This is necessary because sendError will cause the servlet container to close the response. Using setStatus by setting jersey.config.server.response.setStatusOverSendError=true avoids this and allows post-processing the response.

Jersey 3.1 introduces a default exception mapper that adds the following error message to the response for unmapped exceptions:

An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper.

The fact that this message exists makes post-processing of the response when setStatusOverSendError=true impossible because servlet container will close the response when Content-Length is set and the full response entity has been written. While sendError is one way that will trigger the servlet container to close the response (which is what setStatusOverSendError is trying to account for), setting Content-Length and writing this much data will also trigger the servlet container to close the response.

Expected Outcome

When jersey.config.server.response.setStatusOverSendError=true, exceptions that make their way to servlet filter do not trigger response closure so that post-processing of the response is possible.

Fixed by #5612.

Thanks @jansupol ! setStatusOverSendError=true is working for us now in 3.1.7 👍

@jansupol is there a way to suppress this new behavior of adding error message to the response for unmapped exceptions??

@Subrhamanya What would you prefer to be the behavior for the thrown exception?

I mean I want to go back to jetty 2.x behavior where we didn't get this message logged.

Specifically this one An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper

@jansupol anything you can suggest here?

Like I uplifted my code from jersey 2.x to 3.x along with spring and now when I throw runtime exception, in the response, previously I used to get the error message but after the uplift, I am getting Request failed

ie jersey 2.x response:

{ "timestamp": "2024-09-03T05:13:38.457+00:00", "status": 500, "error": "Internal Server Error", "message": "This Operation is unsupported by the underlying implementation. blah blah", "path": "path" }

jersey 3.x response

{ "timestamp": "2024-09-03T05:14:37.956+00:00", "status": 500, "error": "Internal Server Error", "message": "Request failed.", "path": "path" }

I expected jersey 3.x message to be same as that of jersey 2.x..

Here is how we are creating/ throwing error

throw new UnsupportedOperationException( "This Operation is unsupported by the underlying implementation. Error code= {0}", new Object[] {status.getErrorCode()}); }