When sending a request with content type multipart/mixed but corrupt body (one that is no multipart), Jersey throws a NullPointerException
while parsing the request.
@POST
@Consumes("multipart/mixed")
public Response someResource(MultiPart multiPart) { ... }
This results in a status code 500, while 4xx would be correct. How can I handle this exception without catching all NullPointerExceptions
?
Attachment A: stacktrace:
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.NullPointerException
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.unquoteMediaTypeParameters(MultiPartReaderClientSide.java:227)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readMultiPart(MultiPartReaderClientSide.java:154)
at com.sun.jersey.multipart.impl.MultiPartReaderServerSide.readMultiPart(MultiPartReaderServerSide.java:80)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:144)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:82)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:488)
at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123)
at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:46)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:203)
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
at com.yammer.metrics.jersey.InstrumentedResourceMethodDispatchProvider$TimedRequestDispatcher.dispatch(InstrumentedResourceMethodDispatchProvider.java:32)
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302)
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1480)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1411)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.togglz.servlet.TogglzFilter.doFilter(TogglzFilter.java:58)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
This seems to be a bug in Jersey. They don't check the "boundary" parameter value for null
, before dereferencing it. You will have to find a workaround until it is fixed.
Workaround 1: Provide an ExceptionMapper
Maybe you can register an ExceptionMapper
for NullPointerException
and inspect the stack trace to test, if it is that bug or any other NPE. In case of this bug, return 4xx
, otherwise as usual 500 - internal server error
. (It's a bad hack, but I think that's ok for a temporary workaround).
Workaround 2: Provide a JAX-RS ContainerRequestFilter
Since JAX-RS 2.0, it is possible to provide a ContainerRequestFilter
that is invoked before the resource method is called. Check the boundary parameter in the Content-Type
request header. If it is absent, abort the request by calling ContainerRequestContext#abortWith(Reponse)
.
Workaround 3: Write a servlet filter
Similar to workaround 2, but with good-old javax.servlet.Filter
. Make sure, the filter is called before Jersey processes the request.
The NPE occurs because the boundary parameter is missing in your call. I ran into the same problem and needed to fix the issue for my service. I ended up manually adding the boundary parameter to the Content-Type header that Jersey is expecting
https://servicesunavailable.wordpress.com/2015/03/04/using-apache-httpclient-4-x-for-multipart-uploads-with-jersey-1-x-server/
The fix is not pretty since the class MultipartFormEntity is package private however it works well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With