Сервлет генерирует документ PDF после того, как страница предварительного просмотра была сгенерирована в iframe, который генерируется сначала. Обычно это работает и выглядит так:
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" будет вызван дважды, поэтому также будет вызван generatePDF дважды, и вся распечатка будет сорвана (в большинстве случаев PDF будет переопределен белой страницей). Это случается с вероятностью 1 из 50 раз, поэтому вряд ли когда-либо будет воспроизводимым. Прежде всего, я подумал о некоторых проблемах с потоками, поэтому регистрировал идентификатор потока при каждом вызове:
log.info("> current thread:" + Thread.currentThread().getId());
Идентификатор потока всегда одинаков, поэтому я сомневаюсь, что это действительно проблема потока. Меня сбивает с толку тот факт, что когда эта ошибка происходит, Fiddler записывает 4-й вызов после выполнения вызова POST javascript. Обычно существует 3 вызова («directPrintDocument», «directPrintDocumentWaiting» и «directPrintDocumentDoIt»). Когда есть 4 вызова, это всегда происходит одинаково: «directPrintDocumentDoIt» будет вызываться дважды (один и тот же URL-адрес с запросом POST), но внезапно, как запрос GET. Я понятия не имею, откуда приходит этот запрос GET (в "generatePDF" нет других вызовов запроса). Так что либо javascript выдает какое-то странное поведение (но почему то очень редко), либо веб-контейнер (Websphere) создает странные вещи, которые я не понимаю. Интересно, что Fiddler показывает разные размеры сущностей при 3-м и 4-м вызовах. Правильный вызов POST имеет размер объекта 84,138 байт. 4-й вызов (неправильный) имеет 83,883 байта. Я не знаю, что это значит, но, возможно, эта информация полезна. У меня такое ощущение, что эти ошибки происходят чаще после перезапуска или публикации в Websphere. В этом случае это происходит с первой попытки (но не всегда). Это не может быть совпадением. Есть идеи, что здесь происходит?