users@jersey.java.net

Re: [Jersey] MIMEParsingException (IOException: Stream closed) when accessing a multipart form from a filter

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 13 Jul 2009 09:11:24 +0200

H Igor,

Your filter is consuming the request entity, and unless you buffer the
entity it can only be consumed once.

For now you will have to get the entity stream read it into a byte
array input stream, set that as the stream, read the entity in the
filter, then, most importantly, reset the byte array input stream so
the entity can be re-read.

In general when using Jersey filters one should not assume that the
Java type the filter wants for an entity is the same as the Java type
for the resource method. But there is probably some way i could
optimize this, for the case of when it is. Could you log an
enhancement issue?

Thanks,
Paul.

On Jul 12, 2009, at 3:09 AM, Igor Minar wrote:

> 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
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>