Creating PDFs with iText in Java

Introduction

PDF generation is a common requirement in many Java applications, especially for creating reports, invoices, or structured documents. In this tutorial, we’ll take a deep dive into creating a more sophisticated PDF using iText with Java Spring Boot. We’ll cover how to add headers, footers, dynamic tables, custom fonts, and more, to create professional-looking documents.

Prerequisites

  • Familiarity with Java and Spring Boot
  • iText library (Version 7 or 8)
  • Maven or Gradle for dependency management

Setting Up the Project

Begin by setting up your Spring Boot project and adding the iText dependencies to your pom.xml or build.gradle file:

Creating the PDF Service

Let’s create a PdfService that handles various aspects of PDF creation, including headers, footers, dynamic tables, and custom styling.

import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.util.List;

@Service
public class PdfService {

    public byte[] createPdf(List tableData) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {
            PdfWriter writer = new PdfWriter(baos);
            PdfDocument pdfDoc = new PdfDocument(writer);
            Document document = new Document(pdfDoc);

            // Custom font
            PdfFont font = PdfFontFactory.createFont("fonts/arial.ttf", "Identity-H", true);
            document.setFont(font);

            // Adding header
            addHeader(document, "Advanced PDF Report");

            // Adding dynamic table
            addTable(document, tableData);

            // Adding footer
            addFooter(document);

            document.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return baos.toByteArray();
    }

    private void addHeader(Document document, String headerText) {
        Paragraph header = new Paragraph(headerText)
                .setTextAlignment(TextAlignment.CENTER)
                .setFontSize(16)
                .setBold();
        document.add(header);
    }

    private void addFooter(Document document) {
        Paragraph footer = new Paragraph("+250791446610 KN 78 St, Kigali, Rwanda\ninfo@edencaremedical.com")
                .setTextAlignment(TextAlignment.CENTER)
                .setFontSize(10)
                .setFixedPosition(30, 30, UnitValue.createPercentValue(100));
        document.add(footer);
    }

    private void addTable(Document document, List tableData) {
        float[] columnWidths = {1, 5};
        Table table = new Table(columnWidths);

        // Adding table headers
        table.addHeaderCell(createStyledCell("ID"));
        table.addHeaderCell(createStyledCell("Description"));

        // Adding table rows
        for (String[] rowData : tableData) {
            table.addCell(createStyledCell(rowData[0]));
            table.addCell(createStyledCell(rowData[1]));
        }

        document.add(table);
    }

    private Cell createStyledCell(String content) {
        return new Cell().add(new Paragraph(content))
                .setBackgroundColor(ColorConstants.LIGHT_GRAY)
                .setTextAlignment(TextAlignment.CENTER);
    }
    }

Creating a REST Controller

Next, create a REST controller to expose an endpoint for generating the PDF:

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/api/pdf")
public class PdfController {

    private final PdfService pdfService;

    public PdfController(PdfService pdfService) {
        this.pdfService = pdfService;
    }

    @GetMapping("/generate")
    public ResponseEntity generatePdf() {
        // Sample data
        List tableData = Arrays.asList(
                new String[]{"1", "First row data"},
                new String[]{"2", "Second row data"},
                new String[]{"3", "Third row data"},
                new String[]{"4", "Fourth row data"}
        );

        byte[] pdfBytes = pdfService.createPdf(tableData);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        headers.setContentDispositionFormData("filename", "advanced_report.pdf");

        return ResponseEntity.ok()
                .headers(headers)
                .body(pdfBytes);
    }
    }

Explaining Key Features

  1. Custom Fonts: We used a custom font (arial.ttf) to give our PDF a polished look. You can use any font that suits your needs.
  2. Header and Footer: The header and footer are added to enhance the document’s professionalism. The footer is fixed at the bottom of each page.
  3. Dynamic Table: The table can dynamically grow with data, and we’ve applied a simple style to make it visually appealing.
  4. Cell Styling: The table cells are styled with background colors and center-aligned text for better readability.

Handling Large Tables

If your table has many rows, it might span multiple pages. iText handles this automatically, ensuring that the table headers appear on each page:

table.setKeepTogether(true);

Running the Application

Run your Spring Boot application and access http://localhost:8080/api/pdf/generate to generate and download the PDF. You’ll see the header, dynamic table, and footer neatly organized

Conclusion

This advanced guide showed you how to create a sophisticated PDF document in a Java Spring Boot application using iText. By adding headers, footers, dynamic tables, and custom fonts, you can generate professional documents tailored to your application’s needs. This foundation can be further expanded with additional features like images, page numbers, and more complex table structures.