Generating PDF Reports in Java with iText and Apache PDFBox

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Generating PDF Reports in Java: Overview of iText and Apache PDFBox Libraries

\n

Creating PDF documents is one of the common tasks in enterprise Java applications. Reports, invoices, waybills, certificates — all of these are convenient to generate programmatically. In the Java ecosystem, there are two main libraries for working with PDF: iText (an industry standard, but with a commercial license for new versions) and Apache PDFBox (completely free and open-source). In this article, we will cover both, show code examples, and help you choose the right tool for your project.

\n\n

1. Apache PDFBox — a free alternative with extensive capabilities

\n

Apache PDFBox is an open-source library (Apache 2.0 license). It allows you to create PDFs from scratch, edit existing ones, and extract text and metadata. PDFBox does not require a commercial license, making it an ideal choice for startups and open-source projects.

\n

Key features:

\n
    \n
  • Creating documents with text, images, and tables.
  • \n
  • Working with fonts (including Cyrillic).
  • \n
  • Adding bookmarks, hyperlinks, and watermarks.
  • \n
  • Encryption and password protection.
  • \n
  • Extracting text and images from existing PDFs.
  • \n
\n\n

Example: creating a simple PDF report with a table

\n
import org.apache.pdfbox.pdmodel.PDDocument;\nimport org.apache.pdfbox.pdmodel.PDPage;\nimport org.apache.pdfbox.pdmodel.PDPageContentStream;\nimport org.apache.pdfbox.pdmodel.font.PDType0Font;\nimport org.apache.pdfbox.pdmodel.common.PDRectangle;\nimport java.io.File;\nimport java.io.IOException;\n\npublic class PdfBoxReport {\n    public static void main(String[] args) throws IOException {\n        try (PDDocument document = new PDDocument()) {\n            PDPage page = new PDPage(PDRectangle.A4);\n            document.addPage(page);\n\n            // Load a font with Cyrillic support\n            PDType0Font font = PDType0Font.load(document, new File("fonts/arial.ttf"));\n\n            try (PDPageContentStream cs = new PDPageContentStream(document, page)) {\n                // Title\n                cs.beginText();\n                cs.setFont(font, 18);\n                cs.newLineAtOffset(50, 750);\n                cs.showText("Sales Report for Q1 2025");\n                cs.endText();\n\n                // Table (simple implementation via lines and text)\n                cs.setFont(font, 12);\n                // Draw column headers\n                float margin = 50;\n                float yStart = 700;\n                float tableWidth = 500;\n                float rowHeight = 25;\n                String[] headers = {"Product", "Quantity", "Price, RUB"};\n                String[][] data = {{"Laptop", "10", "85000"}, {"Mouse", "50", "1500"}, {"Keyboard", "30", "3500"}};\n\n                // Table header\n                cs.setLineWidth(1f);\n                for (int i = 0; i < headers.length; i++) {\n                    cs.addRect(margin + i * (tableWidth / 3), yStart - rowHeight, tableWidth / 3, rowHeight);\n                    cs.stroke();\n                    cs.beginText();\n                    cs.newLineAtOffset(margin + i * (tableWidth / 3) + 5, yStart - rowHeight + 5);\n                    cs.showText(headers[i]);\n                    cs.endText();\n                }\n\n                // Data\n                float yPos = yStart - rowHeight;\n                for (String[] row : data) {\n                    yPos -= rowHeight;\n                    for (int i = 0; i < row.length; i++) {\n                        cs.addRect(margin + i * (tableWidth / 3), yPos, tableWidth / 3, rowHeight);\n                        cs.stroke();\n                        cs.beginText();\n                        cs.newLineAtOffset(margin + i * (tableWidth / 3) + 5, yPos + 5);\n                        cs.showText(row[i]);\n                        cs.endText();\n                    

Recommendations