Generate PDFs with Spring Boot 3, iText, and Thymeleaf – 170 Real‑World Cases

This article presents a comprehensive guide to generating PDF documents in Spring Boot 3 applications using iTextpdf and Thymeleaf, covering environment setup, Maven dependencies, data model, HTML template design, controller implementation, and a test case that produces a correctly rendered PDF with external CSS and images.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Generate PDFs with Spring Boot 3, iText, and Thymeleaf – 170 Real‑World Cases

1. Introduction

In enterprise applications, generating PDF files is a common requirement for invoices, receipts, contracts, and reports. PDFs provide cross‑platform consistency, tamper‑resistance, and fixed layout, making them suitable for finance, e‑commerce, and government scenarios.

2. Practical Cases

2.1 Environment Preparation

Add the following Maven dependencies:

<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>kernel</artifactId>
  <version>9.3.0</version>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>html2pdf</artifactId>
  <version>6.2.1</version>
</dependency>
<dependency>
  <groupId>ognl</groupId>
  <artifactId>ognl</artifactId>
  <version>3.4.7</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2.2 Data Model and Thymeleaf Template

Define a Java data class representing a receipt:

public class Receipt {
    // Acquirer information
    private String scope;
    // Merchant information
    private String merchantName;
    private String merchantId;
    private String terminalId;
    private String merchantCity;
    // Transaction basics
    private String stan;               // system trace number
    private String transactionDate;
    private String transactionType;
    private BigDecimal requestAmount;
    // Transaction details
    private String mcc;                // merchant category code
    private String scheme;             // card scheme
    private String maskedPan;          // masked card number
    private String acquirer;           // acquiring BIN
    // System information
    private String approvalNumber;
    private String processingCode;
    private String responseCode;
    private String retrievalNumber;
    private String displayMessage;
    // getters and setters omitted
}

The corresponding Thymeleaf HTML template (receipt.html) uses expressions such as

to fill the fields and includes external CSS and an image.</p>
<h3>2.3 Controller Definition</h3>
<p>Expose an endpoint that renders the template and converts it to PDF:</p>
<pre><code>@RestController
@RequestMapping("/html2pdf")
public class Html2PdfController {

    private final ITemplateEngine templateEngine;

    public Html2PdfController(ITemplateEngine templateEngine) {
        this.templateEngine = templateEngine;
    }

    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadEJournalFile(HttpServletRequest request,
                                                      HttpServletResponse response) throws Exception {
        // 1. Prepare data
        Map<String, Object> variables = Map.of("receipt", getData());

        // 2. Create Thymeleaf context
        Context context = new Context();
        context.setVariables(variables);
        String receiptTemplate = templateEngine.process("receipt", context);

        // 3. Configure converter properties (base URI, fonts)
        ConverterProperties converterProperties = new ConverterProperties();
        converterProperties.setBaseUri("http://localhost:8080");
        FontProvider fontProvider = new FontProvider();
        fontProvider.addSystemFonts();
        converterProperties.setFontProvider(fontProvider);

        // 4. Convert HTML to PDF
        ByteArrayOutputStream target = new ByteArrayOutputStream();
        HtmlConverter.convertToPdf(receiptTemplate, target, converterProperties);

        // 5. Set download headers
        String fileName = URLEncoder.encode("receipt_detail.pdf", "UTF-8");
        HttpHeaders header = new HttpHeaders();
        header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
        header.add("Cache-Control", "no-cache, no-store, must-revalidate");
        header.add("Pragma", "no-cache");
        header.add("Expires", "0");

        return ResponseEntity.ok()
                .headers(header)
                .contentType(MediaType.APPLICATION_PDF)
                .body(target.toByteArray());
    }

    public Receipt getData() {
        // return a populated Receipt instance
        return ...;
    }
}

2.4 Test Result

Calling the endpoint returns a PDF that correctly displays all receipt fields, loads external CSS and images, and matches the layout shown below.

Javabackend developmentSpring BootThymeleafiTextPDFpdf-generation
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.