Tag Archives: java.lang.IllegalStateException: getInputStream() can’t be called after getReader()

How to Read Post Request data twice in Spring

Hi Readers,

i got requirement to read to HTTP Post Request data twice in spring MVC interceptor but the problem is when am trying read it,am getting this exception in spring controller “java.lang.IllegalStateException: getReader() has already been called for this request

We are getting this exception because request.getInputStream() called twice, once in MVC interceptor and once spring controller.To fix this we need write wrapper on HTTP request but it will not solve our problem because after wrapping request there is no way to hand over same wrapper request to spring controller,to do that we need to write traditional filter.

follow the below steps

Step 1)Write simple wrapper on HTTP request so that it can be used in filter we are going write in Step 2.

package com.myjavarecipes.web;
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
 private String _body;
 
public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
 super(request);
 _body = "";
 BufferedReader bufferedReader = request.getReader();
 String line;
 while ((line = bufferedReader.readLine()) != null){
 _body += line;
 }
 }

@Override
public ServletInputStream getInputStream() throws       IOException {
 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
 return new ServletInputStream() {
 public int read() throws IOException {
 return byteArrayInputStream.read();
 }
 };
 }

@Override
public BufferedReader getReader() throws IOException {
 return new BufferedReader(new InputStreamReader(this.getInputStream()));
 }
 }

2)Write Traditional J2EE filer,in Filter doFilter method we wrap HTTP request with custom wrapper MultiReadHttpServletRequest and pass it back to filter chain,so that now onward when ever request.getInputStream() get called it will call the overrided method in MultiReadHttpServletRequest class and it returns same ServletInputStream which is already read by wrapper.

 package com.myjavarecipes.web;
 import java.io.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 import java.util.*;

 public class RequestWrapperFilter implements Filter {
 public void init(FilterConfig config)
      throws ServletException{
 // nothing goes here
 }
 
public void doFilter(ServletRequest request,ServletResponse           response, FilterChain chain)
     throws java.io.IOException, ServletException {
MultiReadHttpServletRequest requestWrapper=new      MultiReadHttpServletRequest(request);
 // Pass request back down the filter chain
  chain.doFilter(requestWrapper,response);
   }

 public void destroy( ){
 /* Called before the Filter instance is removed
 from service by the web container*/
 }
 }

3)Configure filter in web.xml so that container will call our filter for each HTTP request.

<filter>
   <filter-name>RequestWrapperFilter</filter-name>
   <filter-class>com.myjavarecipes.web.RequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>RequestWrapperFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

4)Now onward HTTP request object can be read more than once it means we can read it in Spring MVC interceptor and as well as in Spring controller.