I work with openPDF using flying-saucer-pdf-openpdf to generate pdf, following issue occurs randomly . the input data is the same, but sometimes it works well, sometimes it goes wrong, no idea what happened.
2019-03-25 01:11:58,191 ERROR [sanhao-Executor-1] SimpleAsyncUncaughtExceptionHandler: Unexpected error occurred invoking async method: public void com.zykj.sanhao.service.PdfService.generatePdfAndSendMail(com.zykj.sanhao.business.work_order.dto.WorkOrderDTO,boolean)
java.lang.RuntimeException: The page 2 was requested but the document has only 1 pages.
at com.lowagie.text.pdf.PdfWriter.close(PdfWriter.java:1153)
at com.lowagie.text.pdf.PdfDocument.close(PdfDocument.java:813)
at com.lowagie.text.Document.close(Document.java:451)
at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:337)
at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:265)
at com.zykj.sanhao.service.PdfService.generatePdf(PdfService.java:401)
at com.zykj.sanhao.service.PdfService.generatePdfAndSendMail(PdfService.java:116)
at com.zykj.sanhao.service.PdfService$$FastClassBySpringCGLIB$$3b40b191.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor.lambda$createWrappedRunnable$1(ExceptionHandlingAsyncTaskExecutor.java:68)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
2019-03-25 01:12:00,825 INFO [hz.sanhao.cached.thread-4] TcpIpConnectionManager: [172.16.0.3]:5701 [dev] [3.9.4] Established socket connection between /172.16.0.3:41156 and /129.204.175.132:5701
2019-03-25 01:12:00,826 INFO [hz.sanhao.IO.thread-Acceptor] TcpIpAcceptor: [172.16.0.3]:5701 [dev] [3.9.4] Accepting socket connection from /129.204.175.132:41156
2019-03-25 01:12:00,826 INFO [hz.sanhao.cached.thread-4] TcpIpConnectionManager: [172.16.0.3]:5701 [dev] [3.9.4] Established socket connection between /172.16.0.3:5701 and /129.204.175.132:41156
private String generatePdf(String reportTemplateName, Context context, String filePath) throws IOException {
String reportContent = templateService.processThymeleafTemplateIntoString(reportTemplateName, context);
renderer.setDocumentFromString(reportContent);
renderer.layout();
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(filePath);
renderer.createPDF(outputStream);
} catch (IOException e) {
log.error("[generatePdf]", e);
} catch (DocumentException e) {
log.error("[generatePdf]", e);
} finally {
if (null != outputStream) {
outputStream.close();
}
}
return filePath;
}
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.1.16</version>
<exclusions>
<exclusion>
<!--Since openpdf 1.2.0 loading Image with path/URL is not working , 1.2.9 fixed this issue-->
<!--https://github.com/LibrePDF/OpenPDF/issues/133-->
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.librepdf/openpdf -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.2.10</version>
</dependency>
@TonyLuo Can you please provide enough code and example input documents to reproduce this problem?
If you want, you can e-mail me the code, if you don't want it public.
sure. this problem doesn't happen always, it just sometimes happens.
String reportContent = templateService.processThymeleafTemplateIntoString(reportTemplateName, context);
the reportContent string has been printed as reportContent.html in attachment
source.zip
this is the font used in the pdfService.java
FangSong.ttf.zip
@TonyLuo Did u resolved this problem? I'm facing it right now..
not yet...
this issue happens randomly, very difficult to trace the cause
If you are able to reproduce, please post more information here. A pull-request to fix this would be awesome.
ITextRenderer is not thread safe, are you sure that you are not reusing the same instance across different threads (e.g. via Async annotated method calls) ?
I use Async annotated method calls, but generate pdf inside synchronized block.
private final Object generatePdfLock = new Object();
@Async
public void generatePdfAndSendMail(WorkOrderDTO workOrder, boolean sendMailFlag) {
// WorkOrderDTO workOrder = workOrderService.get(workOrderId);
if (null == workOrder) {
return;
}
String workOrderId = workOrder.getId();
synchronized (generatePdfLock) {
String filePath = buildFilePath(workOrder);
if (!generatingFileList.contains(filePath)) {
log.info("[generatePdfAndSendMail] generate file is starting... ---------------------- workOrderId = " + workOrderId + " , filePath =" + filePath);
generatingFileList.add(filePath); // record the file which is generating
try {
Context context = buildContext(workOrder);
generatePdf(PDF_TEMPLATE_NAME, context, filePath);
if (sendMailFlag) {
handleSendMail(workOrder, context, filePath);
}
log.info("[generatePdfAndSendMail] generate file is done! ---------------------- workOrderId = " + workOrderId + " . filePath =" + filePath);
} catch (IOException e) {
log.error("[generatePdfAndSendMail] error", e);
} finally {
generatingFileList.remove(filePath);// remove the file record which is generated
}
} else {
log.info("[generatePdfAndSendMail] workOrderId =" + workOrderId + " file is generating....., filePath =" + filePath);
}
}
}
one more thing: when this issue happens, I restart the server, it will become normal .....
I replace openPDF with itext5, everything goes well...
@pbrant Can you help us with this?
After running for days, itext5 also has such issue.
I fixed it temporarily by creating new ITextRenderer when catch RuntimeException and try to generate pdf again .
try {
context = buildContext(workOrder);
generatePdf(PDF_TEMPLATE_NAME, context, filePath);
} catch (IOException e) {
log.error("[generatePdfAndSendMail] error", e);
}
catch (RuntimeException e){
log.error("[generatePdfAndSendMail] error", e);
// where error happens, try to create new textrender.
this.renderer = new ITextRenderer();
try {
generatePdf(PDF_TEMPLATE_NAME, context, filePath);
} catch (IOException e1) {
log.error("[generatePdfAndSendMail] error", e1);
}
}
It might be the same problem as
https://github.com/flyingsaucerproject/flyingsaucer/pull/159
Generally speaking, it's probably safest to only use a particular instance
of ITextRenderer only once. It does maintain a certain amount of internal
state. It should work to re-use though too (barring bugs like in PR 159
above).
On Wed, Apr 24, 2019 at 3:16 AM Tony notifications@github.com wrote:
after running for days, itext5 also has such issue...
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/LibrePDF/OpenPDF/issues/164#issuecomment-486030090,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAF42HYXBWYNV2DG3ET2XDPR6YHFANCNFSM4HAX5MTA
.
I added a comment to the code about this issue here:
https://github.com/LibrePDF/OpenPDF/commit/c579d91857718e878e0a3820dda7dd164449dbf9
Most helpful comment
It might be the same problem as
https://github.com/flyingsaucerproject/flyingsaucer/pull/159
Generally speaking, it's probably safest to only use a particular instance
of ITextRenderer only once. It does maintain a certain amount of internal
state. It should work to re-use though too (barring bugs like in PR 159
above).
On Wed, Apr 24, 2019 at 3:16 AM Tony notifications@github.com wrote: