66

I google the error message getOutputStream() has already been called for this response and many people said it is because of the space or newline after <% or %>, but in my code , there is no a space or a newline. I am using tomcat6 on linux.

<%@
    page import="java.servlet.*,
    javax.servlet.http.*,
    java.io.*,
    java.util.*,
    com.lowagie.text.pdf.*,
    com.lowagie.text.*"
    %><%
    response.setContentType("application/pdf");
    Document document = new Document();
    try{
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, buffer);
        document.open();
        PdfPTable table = new PdfPTable(2);
        table.addCell("1");
        table.addCell("2");
        table.addCell("3");
        table.addCell("4");
        table.addCell("5");
        table.addCell("6");
        document.add(table);
        document.close();
        DataOutput dataOutput = new DataOutputStream(response.getOutputStream());
        byte[] bytes = buffer.toByteArray();
        response.setContentLength(bytes.length);
        for(int i = 0; i < bytes.length; i++)
        {
        dataOutput.writeByte(bytes[i]);
        }
    }catch(DocumentException e){
        e.printStackTrace();
    }

%>

~

org.apache.jasper.JasperException: java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:522)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:410)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.apache.catalina.connector.Response.getWriter(Response.java:610)
    org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:198)
    org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
    org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
    org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:188)
    org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:118)
    org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:77)
    org.apache.jsp.Account.Domain.testPDF_jsp._jspService(testPDF_jsp.java:94)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
giliev
  • 2,938
  • 4
  • 27
  • 47
Southsouth
  • 2,659
  • 6
  • 32
  • 39

16 Answers16

58

Ok, you should be using a servlet not a JSP but if you really need to... add this directive at the top of your page:

<%@ page trimDirectiveWhitespaces="true" %>

Or in the jsp-config section your web.xml

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <trim-directive-whitespaces>true</trim-directive-whitespaces>
  </jsp-property-group>
</jsp-config>

Also flush/close the OutputStream and return when done.

dataOutput.flush();
dataOutput.close();
return;
bluish
  • 26,356
  • 27
  • 122
  • 180
RealHowTo
  • 34,977
  • 11
  • 70
  • 85
  • 3
    Have you verified that this works? I doubt it'll make any difference, the container is still going to call `getWriter`, regardless of the page content. – skaffman Nov 21 '09 at 18:20
  • No it doesn't if there's absolutely no whitespace outside `<% %>`. This may however be implementation-specific behaviour which I wouldn't rely on after all. As far as I know it would work fine in Tomcat. But again, java code belongs in java classes, not in jsp files. Period. – BalusC Nov 21 '09 at 18:47
  • I forgot to mention that the trimDirectiveWhitespaces directive is for JSP 2.1 or better – RealHowTo Nov 21 '09 at 21:07
  • @BalusC: There was no whitespace outside `<% %>` in the original example, but that didn't make a difference. – skaffman Nov 21 '09 at 21:53
  • 2
    This did not fix the error for me but did fix my plethora of white space. – zmanc Nov 20 '12 at 19:31
  • The 'flush()' worked for me. had to place this call right after data has been written to 'response' or equivalent 'OutputStream'. – Rohit V Dec 02 '14 at 03:57
  • Adding return and creating Content-Length saved my Day. Thanks. – PriyaS Mar 26 '21 at 08:33
40

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.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 1
    the whole project is jsp based, I just need add functionality for PDF download – Southsouth Nov 21 '09 at 17:49
  • 4
    Well you can't, not like this. JSPs are for text, not binary. – skaffman Nov 21 '09 at 17:50
  • 4
    +1. Raw java code belongs in java classes. Use taglibs/EL in JSP only. If not possible with taglibs/EL, use a servlet. – BalusC Nov 21 '09 at 17:56
  • 3
    northTiger, there is nothing stopping you from adding a Servlet even if the project is otherwise all JSPs. JSPs wind up as servlets anyway once the compiler is done with them. For working with PDFs, you are MUCH better off with a plain servlet. – Kris Nov 21 '09 at 21:49
  • 3
    yes, I agree with you guys using servlet. but servket needs more configurations. – Southsouth Nov 21 '09 at 23:17
10

I had this problem only the second time I went to export. Once I added:

response.getOutputStream().flush();
response.getOutputStream().close();

after the export was done, my code started working all of the time.

michaelp
  • 353
  • 6
  • 24
9

Add the following inside the end of the try/catch to avoid the error that appears when the JSP engine flushes the response via getWriter()

out.clear(); // where out is a JspWriter
out = pageContext.pushBody();

As has been noted, this isn't best practice, but it avoids the errors in your logs.

pnairn
  • 1,737
  • 3
  • 17
  • 24
3

Here is what worked for me in similar case.

After you finish writing into the Servlet OutputStream just call response.sendRedirect("yourPage.jsp");. That would cause initiation of a new request from the browser, therefore avoid writing into the same output stream.

akash
  • 22,664
  • 11
  • 59
  • 87
Igor
  • 31
  • 1
3

I just experienced this problem.

The problem was caused by my controller method attempting return type of String (view name) when it exits. When the method would exit, a second response stream would be initiated.

Changing the controller method return type to void resolved the problem.

I hope this helps if anyone else experiences this problem.

Dan Torrey
  • 1,379
  • 15
  • 25
2

JSP is s presentation framework, and is generally not supposed to contain any program logic in it. As skaffman suggested, use pure servlets, or any MVC web framework in order to achieve what you want.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
0

This error was occuring in my program because the resultset was calling more columns to be displayed in the PDF Document than the database contained. For example, the table contains 30 fields but the program was calling 35 (resultset.getString(35))

0

I got the same error by using response.getWriter() before a request.getRequestDispatcher(path).forward(request, response);. So start works fine when I replace it by response.getOutputStream()

Daniel De León
  • 13,196
  • 5
  • 87
  • 72
0

I got the same problem, and I solved just adding "return;" at the end of the FileInputStream.

Here is my JSP

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<%@ page import="java.io.*"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%

 try {
  FileInputStream ficheroInput = new FileInputStream("C:\\export_x_web.pdf");
  int tamanoInput = ficheroInput.available();
  byte[] datosPDF = new byte[tamanoInput];
  ficheroInput.read(datosPDF, 0, tamanoInput);

  response.setHeader("Content-disposition", "inline; filename=export_sise_web.pdf");
  response.setContentType("application/pdf");
  response.setContentLength(tamanoInput);
  response.getOutputStream().write(datosPDF);

  response.getOutputStream().flush();
  response.getOutputStream().close();

  ficheroInput.close();
  return;

 } catch (Exception e) {

 }
%>

</body>
</html>
diego matos - keke
  • 2,099
  • 1
  • 20
  • 11
0

I didn't use JSP but I had similar error when I was setting response to return JSON object by calling PrintWriter's flush() method or return statement. Previous answer i.e wrapping return-statement into a try-block worked kind of: the error disappeared because return-statement makes method to ignore all code below try-catch, specifically in my case, line redirectStrategy.sendRedirect(request, response, destination_addr_string) which seem to modify the already committed response that causes the error. The simpler solution in my case was just to remove the line and let client app to take care of the redirection.

0

I faced the same issue, this issue occurs because Java gives an error if you use multiple writer/output stream using getWriter()/getOutputStream().

For me the issue was I was using @Logging and @RestLogging, avoid using extra annotation while calling the API.

CodingBee
  • 1,011
  • 11
  • 8
0

In my case I am using the out object for printing the code It shows the error like getOutputStream() has already called for the response. For resolving this error, I am initializing another PrintWriter object out1 and use that for printing the code That's working perfectly. Eg. Before: out.println("Error"); After: PrintWriter out1 = response.getWriter(); out1.println("Success");

Sherin
  • 9
  • 1
0

In my case I used to get ServletOutputStreamException() UTC010029 Stream is closed issue on Jboss 7.4.0. It got cleared when I called os.flush() i.e os = response.getOutputStream() before I write to the outputstream [response is an object of HttpServletOutputStream]. Some of the comments here were a life saver. +1 guys.

-1

In some cases this case occurs when you declare

Writer out=response.getWriter   

after declaring or using RequestDispatcher.

I encountered this similar problem while creating a simple LoginServlet, where I have defined Writer after declaring RequestDispatcher.

Try defining Writer class object before RequestDispatcher class.

Abdullah Khan
  • 12,010
  • 6
  • 65
  • 78
-3

Use Glassfish 4.0 instead. This turns out to be a problem only in Glassfish 4.1.1 release.

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Max
  • 1