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(ListtableData) { 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 ResponseEntitygeneratePdf() { // 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
- 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. - 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.
- Dynamic Table: The table can dynamically grow with data, and we’ve applied a simple style to make it visually appealing.
- 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.