Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey throws NullPointerException when parsing corrupt request

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)
like image 969
Francois Bourgeois Avatar asked Nov 19 '13 13:11

Francois Bourgeois


2 Answers

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.

like image 107
isnot2bad Avatar answered Oct 03 '22 13:10

isnot2bad


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.

like image 37
atomic_ice Avatar answered Oct 03 '22 12:10

atomic_ice