0

サーブレットは、最初に生成された iframe 内にプレビュー ページが生成された後、PDF ドキュメントを生成します。これは通常、次のように機能します。

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if ("directPrintDocumentDoIt".equals(request.getParameter("method")))  {
            generatePDF(request, response);
        }
        if ("directPrintDocumentWaiting".equals(request.getParameter("method")))  {
            String queryString = request.getQueryString().replace("directPrintDocumentWaiting", "directPrintDocumentDoIt");
            renderWaiting(request, response, queryString);
        }
        if ("directPrintDocument".equals(request.getParameter("method")))  {
            String queryString = request.getQueryString().replace("directPrintDocument", "directPrintDocumentWaiting");
            renderIFrameWaiting(request, response, queryString);
        }
    }

最初に、「directPrintDocument」とメソッド「renderIFrameWaiting」が呼び出され、iframe ページが生成され、コンテンツがサーブレット応答に書き込まれます (iframe src は doPost の次の部分を呼び出します。これでエラーが発生しないと確信しているので、これは省略します)コードフラグメント)。次に、「directPrintDocumentWaiting」メソッドと「renderWaiting」メソッドが呼び出され、前に生成された iframe ページ内にプレビュー ページが生成され、生成された JavaScript が「directPrintDocumentDoIt」を呼び出して最終的に PDF が生成されます。

private void renderWaiting(HttpServletRequest request, HttpServletResponse response, String queryString) throws IOException  {
    StringBuffer output = new StringBuffer();
    response.setContentType("text/html; charset=ISO-8859-1");
    response.setHeader("Cache-Control", "no-cache");
    output.append("<html>\n");
    output.append("<head>\n");
    output.append("<meta http-equiv='Content-Type' content='text/html;charset=iso-8859-1'>\n");
    output.append("<meta http-equiv='expires' content='0'>\n");
    output.append("<meta http-equiv='cache-control' content='no-cache'>\n");
    output.append("<meta http-equiv='pragma' content='no-cache'>\n");
    output.append("</head>\n");
    output.append("<script type=\"text/javascript\">\n");
    output.append("function formSubmit() {\n");
    output.append("document.forms[0].target=\'_self\';\n");
    output.append("document.body.style.cursor = \"wait\";\n");
    output.append("var formAction = document.forms[0].action;\n");
    output.append("document.forms[0].submit();\n");
    output.append("}\n");
    output.append("</script>\n");
    output.append("<body onload=\"self.focus(); formSubmit();\">\n");
    output.append("<form name=\"druckenForm\" method=\"post\" action=\"" + request.getRequestURI() + "?" + queryString + "\" onsubmit=\"return false;\">\n");
    output.append("<p align=\"center\" valign=\"center\">Druck wird erzeugt...\n</p>\n");
    output.append("<p align=\"center\" valign=\"center\">Der erstmalige Start kann etwas l&auml;nger dauern.</p>\n");
    output.append("</form>\n");
    output.append("</body>\n");
    output.append("</html>");
    response.setContentLength(output.length());
    response.getOutputStream().write(output.toString().getBytes());
    response.getOutputStream().flush();
    response.getOutputStream().close();
}

これは通常は機能しますが、時々奇妙なことが起こります。どういうわけか、最後の呼び出し「directPrintDocumentDoIt」が 2 回呼び出されるように見えるため、generatePDF も 2 回呼び出され、印刷出力全体が行き詰まります (ほとんどの場合、PDF は白いページで上書きされます)。これは 50 回に 1 回の確率で発生するため、再現性はほとんどありません。まず、いくつかのスレッドの問題について考えたので、呼び出しごとにスレッド ID を記録しました。

log.info("> current thread:" + Thread.currentThread().getId());

スレッド ID は常に同じなので、本当にスレッドの問題であるとは思えません。私を困惑させているのは、このエラーが発生すると、javascript POST 呼び出しが実行された後に fiddler が 4 回目の呼び出しを記録するという事実です。通常、3 つの呼び出し (「directPrintDocument」、「directPrintDocumentWaiting」、および「directPrintDocumentDoIt」) があります。呼び出しが 4 回ある場合、常に同じ方法で発生します。「directPrintDocumentDoIt」は 2 回 (POST 要求と同じ URL) 呼び出されますが、突然 GET 要求として呼び出されます。この GET リクエストがどこから来たのかわかりません (「generatePDF」では、他のリクエスト呼び出しはありません)。そのため、javascript が何らかの奇妙な動作を生成するか (しかし、なぜそれが非常にまれなのか)、または Web コンテナー (Websphere) が私が理解できない奇妙な動作を生成するかのいずれかです。興味深いことに、fiddler は 3 回目と 4 回目の呼び出しで異なるエンティティ サイズを示します。正しい POST 呼び出しのエンティティ サイズは 84.138 バイトです。4 回目の呼び出し (間違った呼び出し) には 83.883 バイトがあります。これが何を意味するのかわかりませんが、おそらくこの情報は役に立ちます。このエラーは、Websphere を再起動または公開した後に頻繁に発生するように感じます。この場合、最初の試行で発生します (常にではありません)。これは偶然ではありません。ここで何が起こっているのですか?このエラーは、Websphere を再起動または公開した後に頻繁に発生するように感じます。この場合、最初の試行で発生します (常にではありません)。これは偶然ではありません。ここで何が起こっているのですか?このエラーは、Websphere を再起動または公開した後に頻繁に発生するように感じます。この場合、最初の試行で発生します (常にではありません)。これは偶然ではありません。ここで何が起こっているのですか?

4

1 に答える 1

0

明らかに、エラーはpdfwriterが原因でした。エラーが発生しやすいコードは次のようになりました。

        response.reset();
        response.setContentType("application/pdf");
        response.setContentLength(pdfContent.length);
        response.setHeader("Content-Disposition", "inline; filename=RANDOMFILE.pdf");
        response.addHeader("Accept-Ranges", "bytes");
        response.getOutputStream().write(pdfContent);
        response.getOutputStream().flush();
        response.getOutputStream().close(); 

理由はわかりませんが、このヘッダーによって2番目のリクエストが発生することがあります。次のように変更すると、PDF生成後にホワイトページが表示されなくなります。したがって、これが解決策のようです。

response.setContentType("application/pdf");
response.setContentLength(pdfContent.length);
response.getOutputStream().write(pdfContent);
response.getOutputStream().flush();
response.getOutputStream().close(); 
于 2011-09-22T12:57:36.227 に答える