Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.IllegalStateException: getReader() has already been called for this request

I want to add logging to my Servlet, so I've created Filter which should display request and go to the Servlet. But unfortunately I've encoutered exception:

java.lang.IllegalStateException: getReader() has already been called for this request     at org.apache.catalina.connector.Request.getInputStream(Request.java:948)     at org.apache.catalina.connector.RequestFacade.getInputStream(RequestFacade.java:338)     at com.noelios.restlet.ext.servlet.ServletCall.getRequestEntityStream(ServletCall.java:190) 

So to fix this problem I've found solution with Wrapper, but it doesn't work. What else can I use/change in code? Any ideas?

[MyHttpServletRequestWrapper]

public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {     public MyHttpServletRequestWrapper(HttpServletRequest request)     {         super(request);     }      private String getBodyAsString()     {         StringBuffer buff = new StringBuffer();         buff.append(" BODY_DATA START [ ");         char[] charArr = new char[getContentLength()];         try         {             BufferedReader reader = new BufferedReader(getReader());             reader.read(charArr, 0, charArr.length);             reader.close();         }         catch (IOException e)         {             e.printStackTrace();         }         buff.append(charArr);         buff.append(" ] BODY_DATA END ");         return buff.toString();     }      public String toString()     {         return getBodyAsString();     } } 

[MyFilter]

public class MyFilterimplements Filter {     @Override     public void init(FilterConfig filterConfig) throws ServletException     {     }      @Override     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException     {         final HttpServletRequest httpServletRequest = (HttpServletRequest) request;         final HttpServletResponse httpServletResponse = (HttpServletResponse) response;          final HttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(httpServletRequest);         final String requestBody = requestWrapper.toString();          chain.doFilter(request, response);     } } 
like image 262
lukastymo Avatar asked Sep 06 '11 10:09

lukastymo


2 Answers

Looks like the restlet framework has called getRequestEntityStream() on the Request object which in turn calls getInputStream(), so calling getReader() on the request throws IllegalStateException. The Servlet API documentation for getReader() and getInputStream() says:

 public java.io.BufferedReader getReader()     ...     ... Throws:     java.lang.IllegalStateException - if getInputStream() method has been called on this request   public ServletInputStream getInputStream()     ...     ...     Throws:     java.lang.IllegalStateException - if the getReader() method has already been called for this request 

From the documentation it seems that we cannot call both getReader() and getInputStream() on the Request object. I suggest you use getInputStream() rather than getReader() in your wrapper.

like image 82
Suresh Kumar Avatar answered Sep 24 '22 15:09

Suresh Kumar


Use ContentCachingRequestWrapper class. Wrap HttpServletRequest in thi will resolve issue

Sample : if you want to convert your "HttpServletRequest servletRequest" you can do some thing like

import org.springframework.web.util.ContentCachingRequestWrapper;  ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest); 

Hope it helps!!!

like image 42
Swarit Agarwal Avatar answered Sep 23 '22 15:09

Swarit Agarwal