Link to home
Start Free TrialLog in
Avatar of xiaoyunwu
xiaoyunwuFlag for United States of America

asked on

getCompressingOutputStream() has already been called

I'm using Broadvision to write code, it's using Struts framework.

I have the following code to create pdf using iText.

HttpServletResponse response = (HttpServletResponse) this.getInputs()
                        .get("javax.servlet.http.HttpServletResponse");

            response.setContentType("application/pdf");
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, response
                        .getOutputStream());


In my web.xml, I have the following filter:
  <filter>
  <!-- File compression -->
  <filter-name>CompressingFilter</filter-name>
  <filter-class>com.planetj.servlet.filter.compression.CompressingFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>CompressingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


When I call the program to generate pdf, I got the following error in the log file. Even though the pdf generated correctly. How can I get rid of the log?

2011-10-18 13:39:50,142 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/tec].[jsp]] Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getCompressingOutputStream() has already been called
        at com.planetj.servlet.filter.compression.CompressingHttpServletResponse.getWriter(CompressingHttpServletResponse.java:96)
        at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:112)


I think it's casued by:
http://grepcode.com/file/repo1.maven.org/maven2/net.sourceforge.pjl-comp-filter/pjl-comp-filter/1.6.4/com/planetj/servlet/filter/compression/CompressingHttpServletResponse.java

public PrintWriter  [More ...] getWriter() throws IOException {

95

             if (isGetOutputStreamCalled) {

96

                   throw new IllegalStateException("getCompressingOutputStream() has already been called");

97

             }

98

             isGetWriterCalled = true;

99

             if (printWriter == null) {

100

                  printWriter = new PrintWriter(new OutputStreamWriter(getCompressingServletOutputStream(),

101

                                                                       getCharacterEncoding()),

102

                                                true);

103

            }

104

            return printWriter;

105

      }
ASKER CERTIFIED SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of xiaoyunwu

ASKER

>>If you just want to get rid of log record - you can catch this exception and not throw it further abut rather rwite something less dramatic
Since the code is in lib/pjl-comp-filter-1.6.jar, and I didn't write it. I guess I need to learn how to get it compiled and put it back. Before I do that, I need to know if it will have negative effect.


>> So you say, it still returns you the writer - maybe you happen to call this method getWriter() twice - it first returns the writer,
and copmplains second time ?

No. I think not. It's working fine while I call response.getOutputStream().
And if I change response.getOutputStream() to write the file on server, the error disappears.

Here is the quote from the following link:
http://stackoverflow.com/questions/1776142/getoutputstream-has-already-been-called-for-this-response

The issue here is that your JSP is talking directly to the response OutputStream. This technically isn't forbidden, but it's very much not a good idea.

Specifically, you call response.getOutputStream() and write data to that. Later, when the JSP engine tries to flush the response, it fails because your code has already "claimed" the response. An application can either call getOutputStream or getWriter on any given response, it's not allowed to do both. JSP engines use getWriter, and so you cannot call getOutputStream.

You should be writing this code as a Servlet, not a JSP. JSPs are only really suitable for textual output as contained in the JSP. You can see that there's no actual text output in your JSP, it only contains java.
I'm not sure I understand this:

>No. I think not. It's working fine while I call response.getOutputStream().
>And if I change response.getOutputStream() to write the file on server, the error disappears

If you just make it itn two steps:



OutputStream os = response.getOutputStream();

and then

PdfWriter writer = PdfWriter.getInstance(document, out);

on which step it would produce the error?

probably  on the first step ?



OutputStream os = response.getOutputStream();

PdfWriter writer = PdfWriter.getInstance(document, out);

on which step it would produce the error?

probably  on the first step ?


>> None of the steps produce error. The error generated from the filter.
com.planetj.servlet.filter.compression.CompressingFilter
And the filter really makes it all working faster?
Perhpas this remark below from here
http://download.oracle.com/docs/cd/E13222_01/wls/docs81/jsp/reference.html
may have some connection with this sitaution, as I guess one channel to communicate with
the reponse.out stream was already opened implicitly
----------------------------
    out is an instance of javax.jsp.JspWriter that has several methods you can use to send output back to the browser.

    If you are using a method that requires an output stream, then JspWriter does not work. You can work around this limitation by supplying a buffered stream and then writing this stream to out. For example, the following code shows how to write an exception stack trace to out:

      ByteArrayOutputStream ostr = new ByteArrayOutputStream();
      exception.printStackTrace(new PrintWriter(ostr));
      out.print(ostr);
------------------------
if you use some byte buffer  in this command

   PdfWriter writer = PdfWriter.getInstance(document, response
                        .getOutputStream());

instead of "response.getOutputStream();" as shown above
and then use something similar to
out.print() to ultimately send your PDF
maybe that will not generate the error

I think in this example they disconnect these two steps:
http://www.mail-archive.com/itext-questions@lists.sourceforge.net/msg09964.html

Don't know iif you want to go through all pains and
experiments just because of the warning in the log.



Thank you, for_yan.

Since there's no performance penality, so I caught the exception and not throw it further.