users@jersey.java.net

MIMEParsingException (IOException: Stream closed) when accessing a multipart form from a filter

From: Igor Minar <iiminar_at_gmail.com>
Date: Sat, 11 Jul 2009 18:09:36 -0700

Hi there,

I have a application that needs to process a multipart-form request.
Everything works great, until I try to access my form fields both in a
jersey filter as well as in my resource.

In my filter I have:

     private Credentials attemptBrowserBasedToken(HttpRequestContext
context) {
             FormDataMultiPart form =
context.getEntity(FormDataMultiPart.class);
             String key = form.getField("AccessKey").getValue(); //
TODO NPEs!!!
             String signature =
Base64Coder.decode(form.getField("signature").getValue());
             ...
}

In my resource I have:

     @POST
     @Consumes(MediaType.MULTIPART_FORM_DATA)
     public Response processForm(@PathParam("bucketName") final String
bucketName,
                                     @FormDataParam("policy") final
String policyEncoded,
                                     @FormDataParam("key") String key,
                                      
@FormDataParam("success_action_redirect") final String successRedirect,
                                     @FormDataParam("acl") final
String acl,
                                     final FormDataMultiPart formData,
                                     @Context final SecurityContext
securityContext,
                                     @Context final HttpHeaders
headers) {
     ...
     }

When I run a request against this resource method, I get the exception
below some time after the filter returns and before processForm in the
resource is called.

It looks like when the filter reads the form, it doesn't cache the
result, but closes the request stream when it reads it. As a result,
when jersey tries to initialize resource method arguments, it can't do
it any more.

If I remove all FromData* stuff from the resource method signature,
the exceptions is not thrown.

Is this a known limitation or a result of a design decision?

Do you know if there is some workaround for this? Maybe a way to store
the data retrieved in the filter somewhere in the request context and
then retrieve it somehow in the resource? I suppose I could do this
via a thread local hack, but I'd rather avoid that if possible.

thanks,
Igor




Jul 11, 2009 4:19:55 PM
com.sun.jersey.server.impl.application.WebApplicationImpl onException
SEVERE: Internal server error
javax.ws.rs.WebApplicationException:
org.jvnet.mimepull.MIMEParsingException: java.io.IOException: Stream
closed
         at
com
.sun
.jersey.multipart.impl.MultiPartReader.readFrom(MultiPartReader.java:
203)
         at
com
.sun
.jersey.multipart.impl.MultiPartReader.readFrom(MultiPartReader.java:74)
         at
com
.sun
.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:
393)
         at
com
.sun
.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:
402)
         at
com.sun.jersey.multipart.impl.FormDataMultiPartDispatchProvider
$
FormDataInjectableValuesProvider
.getInjectableValues(FormDataMultiPartDispatchProvider.java:112)
         at
com
.sun
.jersey
.server
.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
$
EntityParamInInvoker
.getParams(AbstractResourceMethodDispatchProvider.java:126)
         at
com
.sun
.jersey
.server
.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
$
ResponseOutInvoker
._dispatch(AbstractResourceMethodDispatchProvider.java:173)
         at
com
.sun
.jersey
.server
.impl
.model
.method
.dispatch
.ResourceJavaMethodDispatcher
.dispatch(ResourceJavaMethodDispatcher.java:67)
         at
com
.sun
.jersey
.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:163)
         at
com
.sun
.jersey
.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:
71)
         at
com
.sun
.jersey
.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:
111)
         at
com
.sun
.jersey
.server
.impl
.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:
63)
         at
com
.sun
.jersey
.server
.impl
.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:
654)
         at
com
.sun
.jersey
.server
.impl
.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:
612)
         at
com
.sun
.jersey
.server
.impl
.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:
603)
         at
com
.sun
.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:
309)
         at
com
.sun
.jersey
.spi.container.servlet.ServletContainer.service(ServletContainer.java:
425)
         at
com
.sun
.jersey
.spi.container.servlet.ServletContainer.service(ServletContainer.java:
590)
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
         at
com
.google
.inject.servlet.ServletDefinition.doService(ServletDefinition.java:216)
         at
com
.google
.inject.servlet.ServletDefinition.service(ServletDefinition.java:141)
         at
com
.google
.inject
.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:93)
         at
com
.google
.inject
.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:63)
         at
com
.google
.inject
.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:122)
         at
com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:110)
         at
com
.sun
.grizzly.http.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:172)
         at
com
.sun
.grizzly
.http.servlet.FilterChainImpl.invokeFilterChain(FilterChainImpl.java:
137)
         at
com
.sun.grizzly.http.servlet.ServletAdapter.service(ServletAdapter.java:
322)
         at
com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:
165)
         at
com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:746)
         at
com
.igorminar.grizzlysendfile.SendfileFilter.doFilter(SendfileFilter.java:
128)
         at
com
.sun
.grizzly
.arp.DefaultAsyncExecutor.invokeFilters(DefaultAsyncExecutor.java:147)
         at
com
.sun
.grizzly.arp.DefaultAsyncExecutor.interrupt(DefaultAsyncExecutor.java:
126)
         at
com.sun.grizzly.arp.AsyncProcessorTask.doTask(AsyncProcessorTask.java:
88)
         at com.sun.grizzly.http.TaskBase.run(TaskBase.java:189)
         at java.util.concurrent.ThreadPoolExecutor
$Worker.runTask(ThreadPoolExecutor.java:886)
         at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:908)
         at java.lang.Thread.run(Thread.java:637)
Caused by: org.jvnet.mimepull.MIMEParsingException:
java.io.IOException: Stream closed
         at org.jvnet.mimepull.MIMEParser.fillBuf(MIMEParser.java:436)
         at org.jvnet.mimepull.MIMEParser.skipPreamble(MIMEParser.java:
302)
         at org.jvnet.mimepull.MIMEParser.access$300(MIMEParser.java:62)
         at org.jvnet.mimepull.MIMEParser
$MIMEEventIterator.next(MIMEParser.java:138)
         at org.jvnet.mimepull.MIMEParser
$MIMEEventIterator.next(MIMEParser.java:123)
         at
org.jvnet.mimepull.MIMEMessage.makeProgress(MIMEMessage.java:193)
         at org.jvnet.mimepull.MIMEMessage.parseAll(MIMEMessage.java:
176)
         at
org.jvnet.mimepull.MIMEMessage.getAttachments(MIMEMessage.java:101)
         at
com
.sun
.jersey.multipart.impl.MultiPartReader.readFrom(MultiPartReader.java:
166)
         ... 37 more
Caused by: java.io.IOException: Stream closed
         at
com
.sun
.grizzly.tcp.http11.GrizzlyInputBuffer.read(GrizzlyInputBuffer.java:343)
         at
com
.sun
.grizzly.tcp.http11.GrizzlyInputStream.read(GrizzlyInputStream.java:234)
         at
com
.sun
.grizzly
.http.servlet.ServletInputStreamImpl.read(ServletInputStreamImpl.java:
91)
         at org.jvnet.mimepull.MIMEParser.fillBuf(MIMEParser.java:434)
         ... 45 more