I am trying to get the request form parameters in the request filter:
@Override public ContainerRequest filter(final ContainerRequest request) { final Form formParameters = request.getFormParameters();
However, the form always seems empty. The HttpRequestContext.getFormParameters() documentation says:
Get the parameters of the form of the request object.
This method ensures that the request object is buffered so that it can be used by the application.
Return: form parameters, if there is a request object, and the content type is "application / x-www-form-urlencoded", otherwise an instance without parameters is returned.
My resource is annotated with @Consumes("application/x-www-form-urlencoded") , although it will not match until the request filter causes it to not work?
I tried to do some research, but could not find convincing evidence of whether this was possible. This is a 4 year discussion in which Paul Sandoz says:
If you work in Jersey filters or using the HttpRequestContext , you can get the form parameters as follows: [broken link to Jersey 1.1.1 HttpRequestContext.getFormParameters ]
I also found this 3-year discussion on how to get multipart / form-data form fields in a query filter. In it, Paul Sandoz uses the following code:
// Buffer InputStream in = request.getEntityInputStream(); if (in.getClass() != ByteArrayInputStream.class) { // Buffer input ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { ReaderWriter.writeTo(in, baos); } catch (IOException ex) { throw new ContainerException(ex); } in = new ByteArrayInputStream(baos.toByteArray()); request.setEntityInputStream(in); } // Read entity FormDataMultiPart multiPart = request.getEntity(FormDataMultiPart.class);
I tried to imitate this approach instead of Form , but the result of request.getEntityInputStream() always an empty stream. And looking at the source of getFormParameters , this method already does the same:
@Override public Form getFormParameters() { if (MediaTypes.typeEquals(MediaType.APPLICATION_FORM_URLENCODED_TYPE, getMediaType())) { InputStream in = getEntityInputStream(); if (in.getClass() != ByteArrayInputStream.class) { // Buffer input ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try { ReaderWriter.writeTo(in, byteArrayOutputStream); } catch (IOException e) { throw new IllegalArgumentException(e); } in = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); setEntityInputStream(in); } ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream) in; Form f = getEntity(Form.class); byteArrayInputStream.reset(); return f; } else { return new Form(); } }
I can’t understand what obscures the entity’s input stream before I get to it. Something in Jersey should consume it, because form parameters are later passed to the resource method. What am I doing wrong here, or is it impossible (and why)?
EDIT: Here is an example of a submitted request:
POST /test/post-stuff HTTP/1.1 Host: local.my.application.com:8443 Cache-Control: no-cache Content-Type: application/x-www-form-urlencoded form_param_1=foo&form_param_2=bar
Here (somewhat redundant) register requests :
INFO: 1 * Server in-bound request 1 > POST https://local.my.application.com:8443/test/post-stuff 1 > host: local.my.application.com:8443 1 > connection: keep-alive 1 > content-length: 33 1 > cache-control: no-cache 1 > origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm 1 > user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 1 > content-type: application/x-www-form-urlencoded 1 > accept: */* 1 > accept-encoding: gzip,deflate,sdch 1 > accept-language: en-US,en;q=0.8 1 > cookie: [omitted] 1 >
Here are the response headers for this request, including Jersey Trace :
Content-Type →application/json;charset=UTF-8 Date →Fri, 09 Aug 2013 18:00:17 GMT Location →https://local.my.application.com:8443/test/post-stuff/ Server →Apache-Coyote/1.1 Transfer-Encoding →chunked X-Jersey-Trace-000 →accept root resource classes: "/post-stuff" X-Jersey-Trace-001 →match path "/post-stuff" -> "/post\-stuff(/.*)?", [...], "(/.*)?" X-Jersey-Trace-002 →accept right hand path java.util.regex.Matcher[pattern=/post\-stuff(/.*)? region=0,11 lastmatch=/post-stuff]: "/post-stuff" -> "/post-stuff" : "" X-Jersey-Trace-003 →accept resource: "post-stuff" -> @Path("/post-stuff") com.application.my.jersey.resource.TestResource@7612e9d2 X-Jersey-Trace-004 →match path "" -> "" X-Jersey-Trace-005 →accept resource methods: "post-stuff", POST -> com.application.my.jersey.resource.TestResource@7612e9d2 X-Jersey-Trace-006 →matched resource method: public javax.ws.rs.core.Response com.application.my.jersey.resource.TestResource.execute(java.lang.String,java.lang.String) X-Jersey-Trace-007 →matched message body reader: class com.sun.jersey.api.representation.Form, "application/x-www-form-urlencoded" -> com.sun.jersey.core.impl.provider.entity.FormProvider@b98df1f X-Jersey-Trace-008 →matched message body writer: java.lang.String@f62, "application/json" -> com.sun.jersey.core.impl.provider.entity.StringProvider@1c5ddffa
Here is the (invisible) servlet configurator:
<servlet> <servlet-name>jersey</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.application.my.jersey</param-value> </init-param> <init-param> <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name> <param-value>com.application.my.jersey.MyFilterFactory</param-value> </init-param> <init-param> <param-name>com.sun.jersey.config.feature.Trace</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
Here is an example resource:
@Path("/post-stuff") @Produces(MediaType.APPLICATION_JSON) public final class TestResource { @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response execute( @FormParam("form_param_1") final String formParam1, @FormParam("form_param_2") final String formParam2 ) { return Response.created(URI.create("/")).entity("{}").build(); } }
I am using Jersey 1.17.
For those who are interested, I am trying to collapse my own necessary parameter check, as described in JERSEY-351 . My solution here worked on requests, cookies, and params parameters - the forms are pulling me.