How to Generate PDF Files in Java: A Complete Step‑by‑Step Tutorial

This guide walks through the need for PDF generation in business scenarios, introduces the iText library (both iText5 and iText7), shows how to add Maven dependencies, provides a minimal “Hello World” PDF example, then details converting HTML (with CSS, images, and Freemarker variables) into PDF, and discusses when custom adaptation is required.

Pan Zhi's Tech Notes
Pan Zhi's Tech Notes
Pan Zhi's Tech Notes
How to Generate PDF Files in Java: A Complete Step‑by‑Step Tutorial

Background

In many business applications developers need to provide electronic documents such as e‑invoices, order printouts, or signed contracts for users to view, download or print.

iText Library Overview

iText is an open‑source Java library for creating PDF (and RTF) files. It is hosted on SourceForge and currently has two major branches: iText5, which is widely used but has some design shortcomings, and iText7, a newer refactor with many improvements. For simple use cases either version works.

Adding iText Dependencies

<dependencies>
    <!-- pdf:start -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.11</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf.tool</groupId>
        <artifactId>xmlworker</artifactId>
        <version>5.5.11</version>
    </dependency>
    <!-- support Chinese characters -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>
    <!-- CSS rendering support -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf-itext5</artifactId>
        <version>9.1.16</version>
    </dependency>
    <!-- HTML → XHTML conversion -->
    <dependency>
        <groupId>net.sf.jtidy</groupId>
        <artifactId>jtidy</artifactId>
        <version>r938</version>
    </dependency>
    <!-- pdf:end -->
</dependencies>

Simple "Hello World" PDF

public class CreatePDFMainTest {
    public static void main(String[] args) throws Exception {
        Document document = new Document(PageSize.A4);
        // Step 2: create Writer instance
        PdfWriter.getInstance(document, new FileOutputStream("hello.pdf"));
        // Create Chinese font
        BaseFont bfchinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfchinese, 12, Font.NORMAL);
        // Step 3: open document
        document.open();
        // Step 4: write content
        Paragraph paragraph = new Paragraph("hello world", fontChinese);
        document.add(paragraph);
        // Step 5: close document
        document.close();
    }
}

Running the program produces hello.pdf containing the text "hello world" rendered with a Chinese‑compatible font.

Complex Implementation – Converting HTML to PDF

When the business scenario requires rendering a full HTML page (including CSS, images and tables) as a PDF, the article shows how to use iText5 together with the XML‑Worker pipeline.

private static void writeToOutputStreamAsPDF(String htmlStr) throws Exception {
    String targetFile = "pdfDemo.pdf";
    File targeFile = new File(targetFile);
    if (targeFile.exists()) { targeFile.delete(); }
    Document document = new Document(PageSize.A4, 25, 25, 15, 40);
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(targetFile));
    PdfReportHeaderFooter header = new PdfReportHeaderFooter("", 8, PageSize.A4);
    writer.setPageEvent(header);
    writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);
    document.open();
    // CSS resolver
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    // Font provider for Chinese characters
    CssAppliers cssAppliers = new CssAppliersImpl(new XMLWorkerFontProvider(){
        @Override
        public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {
            try {
                BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                return new Font(bfChinese, size, style);
            } catch (Exception e) {
                return super.getFont(fontname, encoding, size, style);
            }
        }
    });
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    htmlContext.setImageProvider(new AbstractImageProvider(){
        @Override
        public Image retrieve(String src) {
            int pos = src.indexOf("base64,");
            try {
                if (src.startsWith("data") && pos > 0) {
                    byte[] img = Base64.decode(src.substring(pos + 7));
                    return Image.getInstance(img);
                } else if (src.startsWith("http")) {
                    return Image.getInstance(src);
                }
            } catch (BadElementException | IOException ex) { return null; }
            return null;
        }
        @Override
        public String getImageRootPath() { return null; }
    });
    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new ByteArrayInputStream(htmlStr.getBytes()));
    document.close();
}

private static String readHtmlFile() {
    StringBuffer textHtml = new StringBuffer();
    try {
        File file = new File("printDemo.html");
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String tempString;
        while ((tempString = reader.readLine()) != null) {
            textHtml.append(tempString);
        }
        reader.close();
    } catch (IOException e) { return null; }
    return textHtml.toString();
}

public static void main(String[] args) throws Exception {
    String htmlStr = readHtmlFile();
    writeToOutputStreamAsPDF(htmlStr);
}

The HTML file printDemo.html contains a table that represents an inbound‑stock order. After running the program, pdfDemo.pdf shows the rendered table with proper borders, fonts and embedded images.

Variable Substitution with Freemarker

For fully dynamic content the article recommends using a template engine such as Freemarker. By defining placeholders like ${name} in the HTML template and replacing them before the conversion step, any business data (e.g., order numbers, QR codes) can be injected.

<html>
    <head><meta charset="utf-8"><title></title></head>
    <body>
        <div>您好:${name}</div>
        <div>欢迎,登录博客网站</div>
    </body>
</html>

After the placeholder is replaced with the actual value, the same HTML‑to‑PDF pipeline described above produces the final document.

Conclusion

The iText framework is a very practical third‑party library for generating PDF files in Java. For simple static PDFs it satisfies most requirements out‑of‑the‑box. Complex PDFs that involve rich HTML, CSS, images or dynamic data may require additional adaptation or custom development, for which the official iText API documentation should be consulted.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaMaveniTextPDFFreemarkerHTML to PDFiText5iText7
Pan Zhi's Tech Notes
Written by

Pan Zhi's Tech Notes

Sharing frontline internet R&D technology, dedicated to premium original content.

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.