4

I'm trying to read APPLICATION_FORM_URLENCODED in a MessageBodyReader in Jersey. The stream is returning null data when I try to read it using a BufferedReader

Here is my code:

@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public class EmployeeReader implements MessageBodyReader<Employee> {

    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, 
        MediaType mediaType) {
        return true;
    }

    @Override
    public Employee readFrom(Class<Employee> type, Type genericType, Annotation[] annotations, 
        MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
        throws IOException, WebApplicationException {
        System.out.println(entityStream.available());  //Prints 0
        BufferedReader br = new BufferedReader(new InputStreamReader(entityStream));
        String data = br.readLine();
        System.out.println("Stream Read:"+data);
        //data is null here
        .....
    }
}

I can see that the data is being sent from my form in the POST request as application/x-www-form-urlencoded, however I am unable to read it in my MessageBodyReader.

While debugging I can see that the ByteChunk is holding the below data:

POST /Employees/employee HTTP/1.1
host:localhost:80800
connection:keep-alivee
content-length:144
postman-token:cf873d98-3208-292c-8fc1-6da8138a31faa
cache-control:no-cachee
origin:chrome-extension://fhbjgbiflinjbdggehcddcbncdddomopp
user-agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.366
content-type:application/x-www-form-urlencodedd
accept:*/**
accept-encoding:gzip, deflate, brr
accept-language:en-US,en;q=0.88

id=3&name=Test

UPDATE

I just found out that it is some sort of side effect of SpringBootServletInitializer. Disabling this results in the above code working fine.

Can anybody help?

Manish Kothari
  • 1,702
  • 1
  • 24
  • 34
  • POST parameters arrive in a servlet as request parameters, not as a message body. – user207421 Nov 29 '16 at 17:35
  • @EJP I have seen the same code work for Jersey 2.5 in a standalone Jersey application, this code is not working in Jersey 2.23 with spring boot, Moreover as I have mentioned in the question, I can see the data (Posted in the question) in the ByteChunk of the InputStream in the debug console (`id=3&name=Test`) – Manish Kothari Nov 29 '16 at 17:39

1 Answers1

4

Apparently there is a HiddenHttpMethodFilter that does getParameter before a request reaches the code for form data and a POST request. So the InputStream was already read and br.readLine(); was returning null.

I found a way to override this in one of the other posts here

@Configuration
public class FilterConfig  {
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                    FilterChain filterChain) throws ServletException, IOException {
                if ("POST".equals(request.getMethod())
                        && request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED)) {
                    //Skip this filter and call the next filter in the chain.
                    filterChain.doFilter(request, response);
                } else {
                    //Continue with processing this filter.
                    super.doFilterInternal(request, response, filterChain);
                }
            }
        };
    }
}

So what this does is it simply checks if the request is of POST type and if the MediaType is of APPLICATION_FORM_URLENCODED, if so then we skip this part of the filter chain otherwise for all other requests we process this filter as well.

This way the InputStream will not be read when it reaches the MessageBodyReader

Community
  • 1
  • 1
Manish Kothari
  • 1,702
  • 1
  • 24
  • 34