Java Export PDF File from HTML Template

Tags: ClassLoaderTemplateResolver TemplateEngine ITextRenderer pdf export pdf Thymeleaf

In this Java tutorial we learn how to export .pdf files from HTML template files using the Thymeleaf and Flying Saucer PDF libraries.

Table of contents

  1. Add Thymeleaf and Flying Saucer PDF libraries
  2. Implement Exporter Class to Generate PDF File
  3. Add HTML Template File to resources directory
  4. Implement DTO classes
  5. Implement Main Class to Generate PDF File
  6. Download Source Code

Add Thymeleaf and Flying Saucer PDF libraries

To use the Thymeleaf and Flying Saucer PDF libraries in the Gradle build project, add the following dependency into the build.gradle file.

implementation group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.13.RELEASE'

implementation group: 'org.xhtmlrenderer', name: 'flying-saucer-pdf', version: '9.1.22'

To use the Thymeleaf and Flying Saucer PDF libraries in the Maven build project, add the following dependency into the pom.xml file.

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.13.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.22</version>
</dependency>

Implement Exporter Class to Generate PDF File

Create a new Java class named PdfFileExporter, in this class we use Thymeleaf template engine to populate the HTML content from a given template file name and data in method generateHtml(). And then we implement the exportPdfFile() method to write the .pdf file from HTML content.

PdfFileExporter.java

import com.lowagie.text.DocumentException;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Map;

public class PdfFileExporter {

    public void exportPdfFile(String templateFileName, Map<String, Object> data, String pdfFileName) {
        String htmlContent = generateHtml(templateFileName, data);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(pdfFileName);
            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocumentFromString(htmlContent);
            renderer.layout();
            renderer.createPDF(fileOutputStream, false);
            renderer.finishPDF();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    private String generateHtml(String templateFileName, Map<String, Object> data) {
        TemplateEngine templateEngine = createTemplateEngine();
        Context context = new Context();
        context.setVariables(data);
        String htmlContent = templateEngine.process(templateFileName, context);
        return htmlContent;
    }

    private TemplateEngine createTemplateEngine() {
        ClassLoaderTemplateResolver pdfTemplateResolver = new ClassLoaderTemplateResolver();
        pdfTemplateResolver.setPrefix("pdf-templates/");
        pdfTemplateResolver.setSuffix(".html");
        pdfTemplateResolver.setTemplateMode("HTML5");
        pdfTemplateResolver.setCharacterEncoding("UTF-8");
        pdfTemplateResolver.setOrder(1);

        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(pdfTemplateResolver);
        return templateEngine;
    }

}

Add HTML Template File to resources directory

For example, we need to implement a program to export the supply order form to PDF file.

At this step we create new HTML template file in Thymeleaf format under resources/pdf-templates directory with file named order-template.html as below.

resources/pdf-templates/order-template.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <style>
        h1 {
            color: #25a7e7;
            text-align: center;
        }
        .order {
            width: 100%;
        }
        .order, .order th, .order td {
            border: 1px solid #25a7e7;
            border-collapse: collapse;
        }
        .order th {
            background-color: #25a7e7;
            color: white;
        }
        .total {
            text-align: right;
        }
    </style>
</head>
<body>
<table>
    <tr>
        <td>
            <img width="80" src="https://simplesolution.dev/images/Logo_S_v1.png" />
        </td>
        <td>
            <h1>Supply Order Form</h1>
        </td>
    </tr>
</table>
<div>
    <table>
        <tr>
            <td th:text="'Date: ' + ${#dates.format(order.date, 'dd/MM/yyyy')}"></td>
        </tr>
        <tr>
            <td th:text="'Order #: ' + ${order.orderNo}"></td>
        </tr>
        <tr>
            <td th:text="'Request Date: ' + ${#dates.format(order.requestDate, 'dd/MM/yyyy')}"></td>
        </tr>
        <tr>
            <td th:text="'Order Date: ' + ${#dates.format(order.orderDate, 'dd/MM/yyyy')}"></td>
        </tr>
    </table>
</div>
<br />
<table class="order">
    <tr>
        <th>Item #</th>
        <th>Description</th>
        <th>Quantity</th>
        <th>Unit Price</th>
        <th>Total</th>
    </tr>
    <tr th:each="item, iterStat: ${orderItems}">
        <td th:text="${iterStat.index + 1}"></td>
        <td th:text="${item.description}"></td>
        <td th:text="${item.quantity}"></td>
        <td th:text="${item.unitPrice}"></td>
        <td th:text="${item.total}"></td>
    </tr>
    <tr>
        <td class="total" colspan="4"><b>Total</b></td>
        <td><b th:text="${#aggregates.sum(orderItems.{total})}"></b></td>
    </tr>
</table>
</body>
</html>

Implement DTO classes

In order to process the HTML template file above we add DTO classed named Order and OrderItem as below.

Order.java

import java.util.Date;

public class Order {
    private String orderNo;
    private Date date;
    private Date requestDate;
    private Date orderDate;

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Date getRequestDate() {
        return requestDate;
    }

    public void setRequestDate(Date requestDate) {
        this.requestDate = requestDate;
    }

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }
}

OrderItem.java

public class OrderItem {
    private String description;
    private Integer quantity;
    private Double unitPrice;
    private Double total;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Double getUnitPrice() {
        return unitPrice;
    }

    public void setUnitPrice(Double unitPrice) {
        this.unitPrice = unitPrice;
    }

    public Double getTotal() {
        return total;
    }

    public void setTotal(Double total) {
        this.total = total;
    }
}

Implement Main Class to Generate PDF File

At this step we implement a Main class with create some test data and use PdfFileExporter class to export PDF file.

Main.java

import java.util.*;

public class Main {

    public static void main(String... args) {
        PdfFileExporter pdfFileExporter = new PdfFileExporter();

        Map<String, Object> data = createTestData();

        String pdfFileName = "D:\\SimpleSolution\\order.pdf";
        pdfFileExporter.exportPdfFile("order-template", data, pdfFileName);
    }

    private static Map<String, Object> createTestData() {
        Map<String, Object> data = new HashMap<>();

        Order order = new Order();
        order.setOrderNo("ABC-12345");
        order.setDate(new Date());
        order.setOrderDate(new Date());
        order.setRequestDate(new Date());
        data.put("order", order);

        List<OrderItem> orderItems = new ArrayList<>();
        OrderItem orderItem1 = new OrderItem();
        orderItem1.setDescription("Test Order Item 1");
        orderItem1.setQuantity(1);
        orderItem1.setUnitPrice(100.0);
        orderItem1.setTotal(100.0);
        orderItems.add(orderItem1);

        OrderItem orderItem2 = new OrderItem();
        orderItem2.setDescription("Test Order 2");
        orderItem2.setQuantity(5);
        orderItem2.setUnitPrice(50.0);
        orderItem2.setTotal(250.0);
        orderItems.add(orderItem2);

        OrderItem orderItem3 = new OrderItem();
        orderItem3.setDescription("Test Order 3");
        orderItem3.setQuantity(2);
        orderItem3.setUnitPrice(200.0);
        orderItem3.setTotal(400.0);
        orderItems.add(orderItem3);

        data.put("orderItems", orderItems);

        return data;
    }
}

Execute the above Java program the PDF file will be exported at D:\SimpleSolution\order.pdf, then open the file with an PDF reader you can see the PDF file content as below.

Java Export PDF File from HTML Template

Download The Source Code

The source code in this article can be found at: github.com/simplesolutiondev/java-export-pdf

or clone at:

git clone https://github.com/simplesolutiondev/java-export-pdf.git

or download at:

Download Source Code

Happy Coding 😊

Spring Boot Generate PDF File from HTML Template

Spring Boot Web Download PDF File from HTML Template

Java Convert HTML to PDF

Spring Boot Web Convert HTML String to PDF File

Java Convert HTML to Image