2009-11-21 68 views
49

I Google el mensaje de error getOutputStream() has already been called for this response y muchas personas dijeron que es debido al espacio o nueva línea después de <% o %>, pero en mi código, no hay un espacio o un salto de línea . Estoy usando tomcat6 en Linux.getOutputStream() ya ha sido llamado para esta respuesta

<%@ 
    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) 

causa raíz

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) 

Respuesta

43

Ok, usted debe utilizar un servlet no es un JSP, pero si realmente necesita ... agregar esta directiva en la parte superior de la página:

<%@ page trimDirectiveWhitespaces="true" %> 

o en la sección jsp-config su web.xml

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

también flush/close la OutputStream y volver cuando haya terminado.

dataOutput.flush(); 
dataOutput.close(); 
return; 
+3

¿Has verificado que esto funciona? Dudo que vaya a hacer ninguna diferencia, el contenedor seguirá llamando a 'getWriter', independientemente del contenido de la página. – skaffman

+0

No, no lo hace si no hay absolutamente espacios en blanco fuera '<% %>'. Sin embargo, esto puede ser un comportamiento específico de implementación en el que no confiaría después de todo. Por lo que sé, funcionaría bien en Tomcat. Pero, de nuevo, el código de Java pertenece a las clases de Java, no a los archivos jsp. Período. – BalusC

+0

Olvidé mencionar que la directiva trimDirectiveWhitespaces es para JSP 2.1 o mejor – RealHowTo

31

La cuestión aquí es que su JSP está hablando directamente a la respuesta OutputStream. Esto técnicamente no está prohibido, pero no es una buena idea.

Específicamente, llama al response.getOutputStream() y escribe datos para eso. Más tarde, cuando el motor JSP intenta descargar la respuesta, falla porque su código ya ha "reclamado" la respuesta. Una aplicación puede llamar al getOutputStream o al getWriter en cualquier respuesta dada, no está permitido hacer ambas cosas. Los motores JSP usan getWriter, por lo que no puede llamar al getOutputStream.

Debe escribir este código como un servlet, no como un JSP. Los JSP solo son realmente adecuados para la salida textual tal como figura en el JSP. Puede ver que no hay salida de texto real en su JSP, solo contiene java.

+0

todo el proyecto está basado en jsp, solo necesito agregar funcionalidad para descargar en PDF – Southsouth

+4

Bueno, no se puede, no así. Las JSP son para texto, no binarias. – skaffman

+4

+1. El código Java sin procesar pertenece a las clases de Java. Use taglibs/EL solo en JSP. Si no es posible con taglibs/EL, use un servlet. – BalusC

2

JSP es el marco de presentación, y generalmente no se supone que contenga ninguna lógica de programa. Como sugirió skaffman, use servlets puros o cualquier framework web MVC para lograr lo que quiere.

3

Aquí es lo que funcionó para mí en caso similar.

Después de que termine de escribir en ServletOutputStream simplemente llame al response.sendRedirect("yourPage.jsp");. Eso provocaría el inicio de una nueva solicitud desde el navegador, por lo tanto, evite escribir en la misma secuencia de salida.

6

Añadir el siguiente en el interior del extremo de la try/catch para evitar el error que aparece cuando el motor JSP vacía la respuesta a través de getWriter()

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

Como se ha señalado, esta no es la mejor práctica , pero evita los errores en tus registros.

0

Este error estaba ocurriendo en mi programa porque el conjunto de resultados llamaba a más columnas para mostrarse en el documento PDF que la base de datos contenida. Por ejemplo, la tabla contiene 30 campos pero el programa llamaba a 35 (resultset.getString (35))

3

Acabo de experimentar este problema.

El problema fue causado por el método de mi controlador al intentar devolver el tipo de String (nombre de la vista) cuando sale. Cuando el método salga, se iniciará un segundo flujo de respuesta.

Cambiando el tipo de retorno del método del controlador a void resolvió el problema.

Espero que esto ayude si alguien más experimenta este problema.

3

Tuve este problema solo la segunda vez que fui a exportar. Una vez añadí:

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

después de la exportación se ha realizado mi código comenzó a trabajar todo el tiempo.

+0

JSP quiere abrirlo para imprimir cosas HTML, por lo que se abre después de su último%> – ern0

0

Recibí el mismo error al usar response.getWriter() antes de request.getRequestDispatcher(path).forward(request, response);. Así que empezar funciona bien cuando lo reemplazo por response.getOutputStream()

0

Use Glassfish 4.0 en su lugar. Esto resulta ser un problema solo en la versión de Glassfish 4.1.1.

PT-BR: Utilice o Glasfish 4.0. Este parece ser un problema no meramente Glassfish 4.1.1.

+0

¿Tiene un enlace de informe de error para esto? – Robert

-1

En algunos casos este caso se produce cuando se declara

Writer out=response.getWriter 

después de declarar o usar RequestDispatcher.

Me encontré con este problema similar al crear un simple LoginServlet, donde he definido Writer después de declarar RequestDispatcher.

Intente definir el objeto de clase Writer antes de la clase RequestDispatcher.

Cuestiones relacionadas