OpenHtmlToPdf results in Error when using PDF/A conformance

3.1k Views Asked by At

I am facing an issue, while creating a PDF using OpenHtmlToPdf. Creating a normal PDF works fine, but once PDF/A conformance is enabled, the application exits with a NullPointerException.

The PDF i am trying to create has to be PDF/A conform. However, without the conformance, the resulting pdf does not contain the fonts.

The process of creating a PDF starts with an HTML template, i process using Thymeleaf in Spring Boot. The rendered PDF is at last returned as a ByteArray and return by a controller as a Blob-Download. This part is working fine. The code generating the PDF looks something like this:

val model: Model = modelFactory.buildModel(id)
val context = Context(model.locale)
val outputStream = ByteArrayOutputStream()
val builder = PdfRendererBuilder()
val conformance = PdfRendererBuilder.PdfAConformance.NONE

context.setVariable("model", model)
// Other variables

val htmlContent: String = templateEngine.process("content", context)

builder.useFastMode().usePdfAConformance(conformance)
         .withHtmlContent(htmlContent, "")
         .usePdfVersion(if (conformance.part == 1) 1.4f else 1.5f)
         .toStream(outputStream)
         .useFont({ ClassPathResource("fonts/first-font.ttf").inputStream }, "first-font")
         .useFont({ ClassPathResource("fonts/second-font.ttf").inputStream }, "second-font")
         .useFont({ ClassPathResource("fonts/third-font.ttf").inputStream }, "third-font")
         .useFont({ ClassPathResource("fonts/fourth-font.ttf").inputStream }, "fourth-font")
         .run()

return outputStream.toByteArray()

The code has been slightly altered, but the logic is kept the same.

The html contains css, which includes the fonts like this:

@page {
    size: a4;

    @bottom-center {
        font-size: 8pt;
        border-top: 1px solid black;
        content: 'Generated on [[${formatters.formatDateTime(model.generatedAt)}]]';
        font-family: "first-font"; /* Font provided in code */
    }

    // ...
}
html {
    font-size: 9pt;
    font-family: "second-font"; /* Font provided in code */
}

// ...

With PdfAConformance.NONE, everything works fine and the PDF is rendered as expected.

However, once i change it to any PDF/A conformance, it no longer works. There is a very long list of logs to System.err, containing the following two lines. Repeated over and over again.

com.openhtmltopdf.exception WARNING:: Font metrics not available. Probably a bug.
com.openhtmltopdf.render WARNING:: Font is null.

And finally, the process ends with the following three info logs and NullPointerException

com.openhtmltopdf.general INFO:: Using fast-mode renderer. Prepare to fly.
com.openhtmltopdf.general INFO:: Specified fonts don't contain a space character!
com.openhtmltopdf.general INFO:: Specified fonts don't contain a space character!


java.lang.NullPointerException
    at org.apache.pdfbox.pdmodel.PDPageContentStream.setFont(PDPageContentStream.java:409)
    at com.openhtmltopdf.pdfboxout.PdfContentStreamAdapter.setFont(PdfContentStreamAdapter.java:262)
    at com.openhtmltopdf.pdfboxout.PdfBoxFastOutputDevice.drawStringFast(PdfBoxFastOutputDevice.java:462)
    at com.openhtmltopdf.pdfboxout.PdfBoxFastOutputDevice.drawString(PdfBoxFastOutputDevice.java:408)
    at com.openhtmltopdf.pdfboxout.PdfBoxTextRenderer.drawString(PdfBoxTextRenderer.java:51)
    at com.openhtmltopdf.render.AbstractOutputDevice.drawText(AbstractOutputDevice.java:107)
    at com.openhtmltopdf.render.InlineText.paint(InlineText.java:171)
    at com.openhtmltopdf.render.InlineLayoutBox.paintInline(InlineLayoutBox.java:279)
    at com.openhtmltopdf.render.simplepainter.SimplePainter.paintInlineContent(SimplePainter.java:170)
    at com.openhtmltopdf.render.simplepainter.SimplePainter.paintLayer(SimplePainter.java:72)
    at com.openhtmltopdf.render.PageBox.paintMarginAreas(PageBox.java:430)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.paintPageFast(PdfBoxRenderer.java:886)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.writePDFFast(PdfBoxRenderer.java:619)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPdfFast(PdfBoxRenderer.java:554)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:472)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:409)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:391)
    at com.openhtmltopdf.pdfboxout.PdfRendererBuilder.run(PdfRendererBuilder.java:42)
    ....

This Exception is thrown within Apache PdfBox and i cannot control the input values, hence this appears to be an issue within OpenHtmlToPdf and not another duplicate of "What is a NullPointerException, and how do I fix it?". This is also the case, because nothing is allowed to be null in this Kotlin code.

This Exception is thrown after calling run on the Builder.

I have tried a lot of possible combinations using the conformance. All 3 PDF/A conformance settings, in combination with and without the fast mode, because this post suggested it might be an issue. I made sure to [...] [use] a name that is not sans-serif, serif or monospace as this question might have suggested. Also, adding the "-fs-font-subset: complete-font", as well as the url additionally in the css entries did not help, as it apparently did in this question. If possible, i want to include the fonts in code not in css, since resolving those urls was tricky and finicky in the past. I also made sure that the fonts are not broken, by trying out different ttfs and all i tried resulted in said NullPointerException.

However, those answers and all other answers to issues on Github as well as here did not help me in my case. I am lost.

Is there anything i am missing? Do i have to do something different to get PDF/A conformance?

0

There are 0 best solutions below