users@jersey.java.net

Re: Inconsistent behavior with POST

From: Tim McCune <tim_at_qless.com>
Date: Thu, 20 Mar 2008 10:19:25 -0700

Thanks for the reply Paul, I appreciate it. That sounds about like what
I expected. As a simple workaround right now, I stuck another filter in
the chain that just calls request.getParameterMap() on POSTs, similar to
your #2.

Regards,
Tim

On Thu, 2008-03-20 at 11:52 +0100, Paul Sandoz wrote:
> Hi Tim,
>
> Tim McCune wrote:
> > I'll preface this with the fact that I'm still using version 0.4, so if
> > a good answer is "already fixed in a newer version", then awesome.
> >
>
> I can reproduce it in the trunk.
>
>
> > I'm running into problems using POST with my resources. I just want to
> > get at application/x-www-form-urlencoded name/value pairs. If I pass a
> > FormURLEncodedProperties parameter to my resource method, that seems to
> > work, until I introduce a filter or a Tomcat valve (e.g. request dumper)
> > somewhere in the processing chain before it, that reads from the input
> > stream. Jersey doesn't seem to reset the stream (not sure if that's
> > even possible), and so I end up with an empty FormURLEncodedProperties.
> >
>
> For the most part Jersey is container independent and tries to make as
> minimal assumptions as possible on the container used to get the HTTP
> meta-data and request entity. Which is why it always uses the input
> stream for processing a request entity.
>
> The problem is the Tomcat Request Dumper Valve has side effects that
> result in the processing of the input stream. In general if any
> filter/valve has side effects that affect the input stream then it can
> potentially break many types of servlet or another type of filter. For
> example, if a logging filter was configured to occur after the Tomcat
> Request Dumper Valve and that filter wants to dump the request entity as
> bytes, or a filter that needs to verify the signature of the request entity.
>
>
> > Another approach that I've tried is adding a
> > @Resource private HttpServletRequest _request;
> > field to my resource, and then just reading the request parameters
> > directly from that inside my resource method. That one's a bit more
> > interesting, as it seems to work exactly backwards of the other
> > approach. :) Jersey looks to be wrapping the servlet request and
> > causing some problems. If I don't touch the servlet request before it
> > gets to Jersey, I get an empty set of parameters from the request.
> > Then, to try to debug it, I added this line:
> > System.out.println("------------JERSEY SERVLET: " +
> > req.getParameterMap());
> > to the beginning of the Jersey servlet's service() method, and after
> > that I was always able to get my parameters from the request.
> >
> > I didn't dig too deeply into the code, but the overall problem seems to
> > be around the way that Jersey wants to read the parameters directly from
> > the servlet input stream, instead of reading them from the actual
> > servlet request. It's making too many assumptions about the
> > environment.
> >
>
> The reason is because Jersey reads the input stream and this means
> ServletRequest.getParameter* will not function, from the JavaDoc:
>
> "If the parameter data was sent in the request body, such as occurs
> with an HTTP POST request, then reading the body directly via
> getInputStream() or getReader() can interfere with the execution of
> this method."
>
> But of course if set up the valve it will work because the valve gets
> the parameters.
>
>
> > Is there a good recommended, reliable way to read posted,
> > form-urlencoded parameters in a Jersey resource?
> >
>
> Two possible immediate solutions:
>
> 1) Use a filter/valve that does not have side-effects; or
>
> 2) Try the following if you need to use a filter/valve that has
> side-effects:
>
> @Path("/") public class FormResource {
> @Resource HttpServletRequest request;
>
> @POST public String formPost() {
> return request.getParameterMap();
> }
> }
>
> I recommend the former if possible. The latter works because the
> "formPost" method does not have any request entity parameter does does
> not consume the input stream.
>
> I might be able to develop a special form processing message body reader
> that is used with servlet that works around potential side-effects of
> filters but i need to think more about it...
>
> Paul.
>