DEV Community

Miguel Ortega
Miguel Ortega

Posted on • Originally published at mortega.dev

Generate PDF Documents in your Spring Boot App with AsciidoctorJ

In a recent project I worked there was a need to generate PDF documents.

The document itself required to display information about a complex domain hierarchical object, containing ~100+ attributes and other child objects.
Before the existing application came to place, most users were manually creating Word documents to handle this requirement (with all the copy-pasting and human errors that one can imagine).

Existing solutions

The JVM ecosystem offers many possibilities to generate printable documents, to name a few:

While these libraries certainly offer battle-tested solutions and many features (some have been around for ~20 years !) for small or even medium project I find them a bit excessive.
(Disclaimer: I only have experience with the first two, that you won't find in my CV 😀)

I also have found that either the documentation is outdated, the learning curve is steep, the code is very low-level, only commercial licence is available or a combination of all the above.

Why Asciidoc can be good choice

Asciidoc is a lightweight markup language, where you only focus on content rather than layout.
It's offer a mature ecosystem to writing articles, documentation, books, and so on, with output formats ranging from HTML to ePub (and of course PDF).
It can easily integrate images, diagrams, code.

I have been using it for years for the technical documentation of personal and non-personal projects.

Show me the code


If you are in a hurry you can check the code directly on Github


Integrating Asciidoctor into your app is as simple as adding a maven (or gradle) dependency

<dependency>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctorj</artifactId>
    <version>${asciidoctorj.version}</version>
</dependency>

<dependency>
    <groupId>org.asciidoctor</groupId>
    <artifactId>asciidoctorj-pdf</artifactId>
    <version>${asciidoctorj.pdf.version}</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Now let's see how you can generate a document :

try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { //<1>

    Attributes attributes = Attributes.builder()//<2>
          .attribute("pdf-theme", theme) // optional theme
          .attribute("doctype", "book")
          .attribute("icons", "font")
          .build();

    Options options = Options.builder()
          .backend("pdf")//<3>
          .attributes(attributes)
          .toFile(outputLocation.toFile()).build();

    asciidoctor.convert(asciidocContent, options);//<4>
}
Enter fullscreen mode Exit fullscreen mode
  1. Create Asciidoctor factory
  2. Define common attributes (you can even define a theme, more on that later)
  3. Set PDF backend
  4. Do the actual conversion, where asciidocContent is a string containing a ASCIIDOC template

That's pretty much it !

The asciidocContent can come from a "static" file on your classpath (or anywhere really).
For more dynamic document, it is possible to use any templating engine (in our project we used mustache).

It is possible to provide customization to the default theme, while it is not as powerful as other solutions, it can be good enough for most needs.
Several examples can be found on github.

Themes can also be packaged as jar for easier distribution.
The documentation is quite detailed.

Caveats

While this solution has served me well, it does come with some limitations:

  • Customization can be quite limited depending on your needs.
  • While diagrams as text is very practical, it does currently need an external dependency (graphviz, mermaid) present on your PATH.
  • Last but not least, the dependency that wraps a JRuby runtime does not work well in UBER jars (nested jars)
    • For Spring Boot apps, this can be solved via requiresUnpack option of spring-boot-maven-plugin. ➡️Documentation
    • For Quarkus, this is not possible yet #issue

a quick demo project demonstrating the possibilities of this solution, with a custom theme,
is available on github.

Further reading

Top comments (0)