Spring Boot Generate PDF File from HTML Template
Tags: Flying Saucer PDF pdf generate pdf ClassLoaderTemplateResolver TemplateEngine ITextRenderer Thymeleaf
In this Spring Boot tutorial we will show you the step by step guide how to implement a Spring Boot console application to generate .pdf files from HTML template files. In order to create the .pdf file we will use Thymeleaf template library to process the HTML template file then from the processed HTML file we use the Flying Saucer PDF library to generate the .pdf file.
Table of contents
- Create New Spring Boot Project
- Add Flying Saucer PDF library to the project
- Configure Thymeleaf
- Implement PDF Generate Service
- Add HTML template file
- Implement Entity classes
- Implement Testing Code to Generate .pdf File
- Complete Source Code and Run The Application
- Download Source Code
Create New Spring Boot Project
Open IntelliJ IDEA, select the menu File > New > Project.
On the New Project dialog, select Spring Initializr and click Next button.
On the Spring initializr Project Settings dialog input the new project information as below and click Next button.
- Group: dev.simplesolution
- Artifact: spring-boot-generate-pdf
- Version: 1.0.0
- Name: spring-boot-generate-pdf
- Description: Spring Boot Generate PDF File
- Package: dev.simplesolution.pdf
On the Dependencies dialog, select Thymeleaf as the screenshot below and click Next button.
Select the location for your project and click Finish button.
You can also create new Spring Boot project using Spring Initializr online tool at start.spring.io as below screenshot.
Add Flying Saucer PDF library to the Spring Boot project
To use the Flying Saucer PDF library into the Maven project, add the following dependency to the pom.xml file.
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
</dependency>
If you are using Gradle, add the following dependency to the build.gradle file.
implementation group: 'org.xhtmlrenderer', name: 'flying-saucer-pdf', version: '9.1.22'
Implement Thymeleaf Configuration bean
In this step we add a new configuration to configure the Thymeleaf template engine.
Add a new Java packaged named dev.simplesolution.pdf.config, in the created package implement a new Java class named ThymeleafConfiguration as below.
src/main/java/dev/simplesolution/pdf/config/ThymeleafConfiguration.java
package dev.simplesolution.pdf.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
@Configuration
public class ThymeleafConfiguration {
@Bean
public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver pdfTemplateResolver = new ClassLoaderTemplateResolver();
pdfTemplateResolver.setPrefix("pdf-templates/");
pdfTemplateResolver.setSuffix(".html");
pdfTemplateResolver.setTemplateMode("HTML5");
pdfTemplateResolver.setCharacterEncoding("UTF-8");
pdfTemplateResolver.setOrder(1);
return pdfTemplateResolver;
}
}
Implement PDF Generate Service
In this step we implement a new service class to generate .pdf file with a given template file name, the data to populate HTML template and provided output .pdf file name.
Firstly add the following properties to configure the directory to write .pdf files. For example we will write .pdf file to D:\SimpleSolution\ directory.
src/main/resources/application.properties
pdf.directory=D:\\SimpleSolution\\
Add a new Java package named dev.simplesolution.pdf.service, in this new package create a new interface named PdfGenerateService as below.
src/main/java/dev/simplesolution/pdf/service/PdfGenerateService.java
package dev.simplesolution.pdf.service;
import java.util.Map;
public interface PdfGenerateService {
void generatePdfFile(String templateName, Map<String, Object> data, String pdfFileName);
}
Add a new Java package named dev.simplesolution.pdf.service.impl, in the new package implement a new Java class named PdfGenerateServiceImpl, in this class we implement method generatePdfFile() to generate the .pdf file.
src/main/java/dev/simplesolution/pdf/service/impl/PdfGenerateServiceImpl.java
package dev.simplesolution.pdf.service.impl;
import com.lowagie.text.DocumentException;
import dev.simplesolution.pdf.service.PdfGenerateService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Map;
@Service
public class PdfGenerateServiceImpl implements PdfGenerateService {
private Logger logger = LoggerFactory.getLogger(PdfGenerateServiceImpl.class);
@Autowired
private TemplateEngine templateEngine;
@Value("${pdf.directory}")
private String pdfDirectory;
@Override
public void generatePdfFile(String templateName, Map<String, Object> data, String pdfFileName) {
Context context = new Context();
context.setVariables(data);
String htmlContent = templateEngine.process(templateName, context);
try {
FileOutputStream fileOutputStream = new FileOutputStream(pdfDirectory + pdfFileName);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(fileOutputStream, false);
renderer.finishPDF();
} catch (FileNotFoundException e) {
logger.error(e.getMessage(), e);
} catch (DocumentException e) {
logger.error(e.getMessage(), e);
}
}
}
Add HTML template file
At this step we add the HTML template file in Thymeleaf format as below.
src/main/resources/pdf-templates/quotation.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<style>
h1{
color: brown;
}
.quotation {
width: 100%;
}
.quotation, .quotation th, .quotation td {
border: 1px solid brown;
border-collapse: collapse;
}
.quotation th {
background-color: brown;
color: white;
}
</style>
</head>
<body>
<h1>Quotation</h1>
<table>
<tr>
<th>Customer</th>
</tr>
<tr>
<td th:text="'Company Name: ' + ${customer.companyName}"></td>
</tr>
<tr>
<td th:text="'Contact Name: ' + ${customer.contactName}"></td>
</tr>
<tr>
<td th:text="'Address: ' + ${customer.address}"></td>
</tr>
<tr>
<td th:text="'Email: ' + ${customer.email}"></td>
</tr>
<tr>
<td th:text="'Phone: ' + ${customer.phone}"></td>
</tr>
</table>
<br />
<table class="quotation">
<tr>
<th>Item #</th>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
<tr th:each="item, iterStat: ${quoteItems}">
<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>
</table>
</body>
</html>
Implement Entity classes
In this step we implement the entity classes for the project, these classes will be used to instantiate objects as variables in order to process HTML template. For example we have Customer information and a list of quotation items need pass to the HTML template.
Add a new Java package named dev.simplesolution.pdf.entity, the implement the Customer class as below.
src/main/java/dev/simplesolution/pdf/entity/Customer.java
package dev.simplesolution.pdf.entity;
public class Customer {
private String companyName;
private String contactName;
private String address;
private String email;
private String phone;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Add new class named QuoteItem as below.
src/main/java/dev/simplesolution/pdf/entity/QuoteItem.java
package dev.simplesolution.pdf.entity;
public class QuoteItem {
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 Testing Code to Generate .pdf File
At this step we implement a new class named PdfGeneratorRunner and implements CommandLineRunner interface in order to run the code when the Spring Boot application start.
In this class we call the generatePdfFile() method from PDF generate service to generate the .pdf file with provided customer information and a list of QuoteItem objects.
src/main/java/dev/simplesolution/pdf/PdfGeneratorRunner.java
package dev.simplesolution.pdf;
import dev.simplesolution.pdf.entity.Customer;
import dev.simplesolution.pdf.entity.QuoteItem;
import dev.simplesolution.pdf.service.PdfGenerateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class PdfGeneratorRunner implements CommandLineRunner {
@Autowired
private PdfGenerateService pdfGenerateService;
@Override
public void run(String... args) throws Exception {
Map<String, Object> data = new HashMap<>();
Customer customer = new Customer();
customer.setCompanyName("Simple Solution");
customer.setContactName("John Doe");
customer.setAddress("123, Simple Street");
customer.setEmail("john@simplesolution.dev");
customer.setPhone("123 456 789");
data.put("customer", customer);
List<QuoteItem> quoteItems = new ArrayList<>();
QuoteItem quoteItem1 = new QuoteItem();
quoteItem1.setDescription("Test Quote Item 1");
quoteItem1.setQuantity(1);
quoteItem1.setUnitPrice(100.0);
quoteItem1.setTotal(100.0);
quoteItems.add(quoteItem1);
QuoteItem quoteItem2 = new QuoteItem();
quoteItem2.setDescription("Test Quote Item 2");
quoteItem2.setQuantity(4);
quoteItem2.setUnitPrice(500.0);
quoteItem2.setTotal(2000.0);
quoteItems.add(quoteItem2);
QuoteItem quoteItem3 = new QuoteItem();
quoteItem3.setDescription("Test Quote Item 3");
quoteItem3.setQuantity(2);
quoteItem3.setUnitPrice(200.0);
quoteItem3.setTotal(400.0);
quoteItems.add(quoteItem3);
data.put("quoteItems", quoteItems);
pdfGenerateService.generatePdfFile("quotation", data, "quotation.pdf");
}
}
Complete Source Code and Run The Application
At this step we have finished the implementation of Spring Boot console application to generate .pdf file. Your project source code should be structured as below screenshot.
Run the application and open D:\SimpleSolution directory you can see the quotation.pdf file be generated with the content as below.
Download The Source Code
The source code in this article can be found at: github.com/simplesolutiondev/spring-boot-generate-pdf
or clone at:
git clone https://github.com/simplesolutiondev/spring-boot-generate-pdf.git
or download at:
Happy Coding 😊
Related Articles
Spring Boot Web Download PDF File from HTML Template
Java Export PDF File from HTML Template