?
Solved

getCompressingOutputStream() has already been called

Posted on 2011-10-18
7
Medium Priority
?
1,706 Views
Last Modified: 2012-05-12
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

      }
0
Comment
Question by:xiaoyunwu
  • 4
  • 3
7 Comments
 
LVL 47

Accepted Solution

by:
for_yan earned 2000 total points
ID: 36989071
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

If you want to get to the root cause of the problem, that's another story

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 ?
0
 

Author Comment

by:xiaoyunwu
ID: 36989145
>>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.
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36989330
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 ?


0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:xiaoyunwu
ID: 36989370

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
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36989437
And the filter really makes it all working faster?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36989587
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.



0
 

Author Closing Comment

by:xiaoyunwu
ID: 36994614
Thank you, for_yan.

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

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Suggested Courses
Course of the Month16 days, 10 hours left to enroll

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question