サーブレットは、最初に生成された 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ä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 を再起動または公開した後に頻繁に発生するように感じます。この場合、最初の試行で発生します (常にではありません)。これは偶然ではありません。ここで何が起こっているのですか?