web-dev-qa-db-ja.com

この応答に対してgetOutputStream()がすでに呼び出されています

エラーメッセージgetOutputStream() has already been called for this responseをグーグルで検索し、多くの人が<%または%>の後のスペースまたは改行のためだと言いましたが、私のコードではスペースも改行もありません。 LinuxでTomcat6を使用しています。

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

根本的な原因

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)
56
Southsouth

OK、JSPではなくservletを使用する必要がありますが、本当に必要な場合は、このディレクティブをページの上部に追加します。

<%@ page trimDirectiveWhitespaces="true" %>

または、jsp-configセクションでweb.xml

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

flush/close the OutputStreamも完了し、完了したら戻ります。

dataOutput.flush();
dataOutput.close();
return;
50
RealHowTo

ここでの問題は、JSPが応答OutputStreamと直接通信していることです。これは技術的に禁じられているわけではありませんが、あまり良い考えではありません。

具体的には、response.getOutputStream()を呼び出し、それにデータを書き込みます。後で、JSPエンジンが応答をフラッシュしようとすると、コードが既に応答を「要求」しているため失敗します。アプリケーションは、任意の応答でgetOutputStreamまたはgetWriterを呼び出すことができますが、両方を行うことはできません。 JSPエンジンはgetWriterを使用するため、getOutputStreamを呼び出すことはできません。

このコードは、JSPではなくサーブレットとして作成する必要があります。 JSPは、JSPに含まれているテキスト出力にのみ本当に適しています。 JSPには実際のテキスト出力はなく、Javaのみが含まれていることがわかります。

35
skaffman

JSPエンジンがgetWriter()を介して応答をフラッシュするときに表示されるエラーを回避するために、try/catchの末尾に次を追加します。

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

既に述べたように、これはベストプラクティスではありませんが、ログのエラーを回避します。

9
pnairn

この問題は、エクスポートに2回目に行ったときにのみ発生しました。追加したら:

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

エクスポートが完了した後、私のコードは常に機能し始めました。

4
michaelp

この問題が発生しました。

この問題は、コントローラーメソッドが終了時にString(view name)の戻り値のタイプを試みたために発生しました。メソッドが終了すると、2番目の応答ストリームが開始されます。

コントローラーメソッドの戻り値の型をvoidに変更すると、問題は解決しました。

他の誰かがこの問題を経験した場合にこれが役立つことを願っています。

3
Dan Torrey

同様のケースで私にとってうまくいったのは次のとおりです。

ServletOutputStreamへの書き込みが完了したら、response.sendRedirect("yourPage.jsp");を呼び出します。これにより、ブラウザからの新しいリクエストが開始されるため、同じ出力ストリームへの書き込みは避けてください。

3
Igor

JSPはプレゼンテーションフレームワークであり、通常、プログラムロジックを含むことは想定されていません。スカッフマンが示唆したように、純粋なサーブレットまたは任意のMVC Webフレームワークを使用して、目的を達成します。

2
Bozho

response.getWriter()の前にrequest.getRequestDispatcher(path).forward(request, response);を使用すると、同じエラーが発生しました。したがって、response.getOutputStream()に置き換えると、startは正常に機能します。

0
Daniel De León

同じ問題が発生し、「リターン」を追加するだけで解決しました。 FileInputStreamの最後。

ここに私の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>
0

このエラーは、結果セットがPDF Documentに含まれるデータベースよりも多くの列を呼び出しているため、プログラムで発生していました。たとえば、テーブルには30のフィールドが含まれていますが、プログラムは35を呼び出していました(resultset.getString(35))

0
Wandile Nxumalo