You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Kari Scott <Ka...@cdw.com> on 2011/10/04 00:36:36 UTC

IllegalStateException using CompressionFilter with Tomcat 7.0.21/22


Hi,

We are running Tomcat 6. 0.32 with jdk1.6.0_26 on Solaris 10, mod_ajp and Apache 2.2.21 in our production environment and are looking to upgrade to Tomcat 7 but have run into a problem with the CompressionFilter (an older version of the Amy Roh one) causing this exception:



SEVERE: Servlet.service() for servlet [jsp] in context with path [] threw exception [java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause
java.lang.IllegalStateException: getWriter() has already been called for this response
        at org.apache.catalina.connector.Response.getOutputStream(Response.java:594)
        at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:199)
        at com.tirerack.filters.CompressionResponseStream.<init>(CompressionResponseStream.java:47)
        at com.tirerack.filters.CompressionServletResponseWrapper.createOutputStream(CompressionServletResponseWrapper.java:172)
        at com.tirerack.filters.CompressionServletResponseWrapper.getWriter(CompressionServletResponseWrapper.java:250)
        at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
        at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
        at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:190)
        at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:123)
        at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
        at org.apache.jsp.upgrade_005fgarage.SetCurrentVehicle_jsp._jspService(SetCurrentVehicle_jsp.java:278)



These appear to occur when the "response.sendRedirect("/page.jsp")" is used on a JSP. The error is caught and handled so the customer doesn't notice it and is still redirected, but it sure generates a ton of log entries and I'd like to get it fixed before proceeding with our upgrade.


I saw that another user had trouble (copied post snippet below for reference) with the new flushBuffer() call that was added to the Response.java for sendRedirect() in 7.0.21 and I'm guessing that's the issue here, too, but I'm not sure how to get around it.


>From what I've read, you can only use a getWriter or a getOutputStream on a single response object, not both, and I think this error is happening because the flushBuffer() method that was added is invoking the getWriter on line 118 (http://www.docjar.com/html/api/org/apache/jasper/runtime/JspWriterImpl.java.html) when an output stream was already being used:


 111       protected final void flushBuffer() throws IOException {
  112           if (bufferSize == 0)
  113               return;
  114           flushed = true;
  115           ensureOpen();
  116           if (nextChar == 0)
  117               return;
 --> 118           initOut();
  119           out.write(cb, 0, nextChar);
  120           nextChar = 0;
  121       }
  122
  123       private void initOut() throws IOException {
  124           if (out == null) {
  -->125               out = response.getWriter();
  126           }
  127       }



We have several other filters in place and the error goes away by removing just the CompressionFilter, so the issue is definitely in that one filter.


Since this is a pretty common filter, I'm hoping someone else has run into this and has found a fix. Anyone?


-Kari








Begin forwarded message:

From: Jacob Champlin <ja...@rentec.com>>
Date: September 27, 2011 1:55:39 PM CDT
To: <us...@tomcat.apache.org>>
Subject: Re: 7.0.21 Redirects failing randomly
Reply-To: Tomcat Users List <us...@tomcat.apache.org>>

Konstantin,

Ok, so I see now why you added the flushBuffer() from spec:

http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpServletResponse.html#sendRedirect%28java.lang.String%29

"Sends a temporary redirect response to the client using the specified redirect location URL and clears the buffer."

Its just we have been running Tomcat, for 5 years and we have lots of code that relied on the fact that sendRedirect did not flush the buffer.

I will drop it, but going to be a while before we can go to 7.0.21.

Jacob

On 09/27/2011 02:32 PM, Jacob Champlin wrote:
Konstantin,

I believe the new flushBuffer() call you added to Response.java
sendRedirect() line #1340. Is breaking all ServletFilters but sending
buy flushing the response before filters have a chance to modify the
response.

Jacob










_________________________________
Kari Scott
Senior Programmer
kari.scott@cdw.com<ma...@cdw.com>

CDW
5520 Research Park Drive
Madison, WI 53711
Office: 608 298 1223
Fax: 608 288 3007







Re: IllegalStateException using CompressionFilter with Tomcat 7.0.21/22

Posted by Konstantin Kolinko <kn...@gmail.com>.
2011/10/4 Kari Scott <Ka...@cdw.com>:
> SEVERE: Servlet.service() for servlet [jsp] in context with path [] threw exception [java.lang.IllegalStateException: getWriter() has already been called for this response] with root cause
> java.lang.IllegalStateException: getWriter() has already been called for this response
>        at org.apache.catalina.connector.Response.getOutputStream(Response.java:594)
>        at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:199)
>        at com.tirerack.filters.CompressionResponseStream.<init>(CompressionResponseStream.java:47)
>        at com.tirerack.filters.CompressionServletResponseWrapper.createOutputStream(CompressionServletResponseWrapper.java:172)
>        at com.tirerack.filters.CompressionServletResponseWrapper.getWriter(CompressionServletResponseWrapper.java:250)
>        at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
>        at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
>        at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:190)
>        at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:123)
>        at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
>        at org.apache.jsp.upgrade_005fgarage.SetCurrentVehicle_jsp._jspService(SetCurrentVehicle_jsp.java:278)
>
>

The above stack trace is quite odd.
JspWriterImpl calls getWriter(), but CompressionServletResponseWrapper
implements it as a call to createOutputStream(), but that fails
because, well, you have already called getWriter().


It feels like there is some bug there, but I would like a more simple example.

I think it is OK to open an issue in Bugzilla, but please attach an
example (with source code) that reproduces this. I think a lot depends
on the state of JspWriterImpl when PageContextImpl.release() is
called.  I think it should be empty at that point, but it is not.

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org