DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Practical Use of Weak Symbols
  • Python and Open-Source Libraries for Efficient PDF Management
  • Improving Java Code Security
  • Reading an HTML File, Parsing It and Converting It to a PDF File With the Pdfbox Library

Trending

  • How AI Agents Are Transforming Enterprise Automation Architecture
  • AI’s Role in Everyday Development
  • Medallion Architecture: Why You Need It and How To Implement It With ClickHouse
  • How to Practice TDD With Kotlin
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Introduction to iText 7

Introduction to iText 7

Getting started with the latest version of iText 7, with instructions on generating PDF content and then stylizing it to suit your needs.

By 
Arnošt Havelka user avatar
Arnošt Havelka
DZone Core CORE ·
Dec. 12, 20 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
18.2K Views

Join the DZone community and get the full member experience.

Join For Free

Overview

In this article, I will introduce the latest version of the iText 7 library. I will provide an example of how to generate a PDF using the library and some methods for testing PDF content. This will be followed by examples of styling texts or paragraphs. To start, I'll begin with a short overview of the library to provide readers with a better understanding of the concept.

Purpose of iText Library

The iText library can be used to manipulate almost any PDF. It can be used to create static or dynamic PDFs and manipulate already existing PDFs with minimum concern for the PDF standards. The library is a collection of several components, but the primary concern of this article is the IText Core component. See some definitions from the iText site.

Key features:

iText 7 Core is a straightforward, performant and extensible library that is ready to handle the challenges of today's digital document workflows.

Main benefits:

With iText 7 Core you don't have to worry about PDF technologies and standards, you can just focus on your business needs and document content. At the same time your development team has full access to all internal PDF structures, offering them the possibility to read, insert, update and delete any PDF object they want. In addition to this, they can benefit from our rich and up-to-date technical documentation in the Resource Center.

License

The library has been using the AGPL license model since iText 5. That means the library is free to use in open source projects. However, a commercial license is needed for usage in any commercial project.

Note: I have to admit their support is excellent and they never let me down.

History

The iText 7 is quite a matured library in its 4th edition (see versions 1, 2, 5, and 7). Besides that, the library is constantly adding new features. You can see the evolution of the library (the collection of components) in the image below.

iText release dates flowchart

The progress of iText evolution in time (20th Birthday Release: iText 7.1.1)

Maven Dependencies

To get started with the library we need to add itext7-core Maven dependency to your pom.xml as defined in the code below. We can find the latest available version of iText 7 in the Maven Central repository.

XML
 




x
7


 
1
<dependency>
2
    <groupId>com.itextpdf</groupId>
3
    <artifactId>itext7-core</artifactId>
4
    <version>7.1.13</version>
5
    <type>pom</type>
6
</dependency>



Additionally, our code depends on the JUnit framework (for unit testing purposes) delivered by the SpringBoot Test Starter.

XML
 




x
6


 
1
<dependency>
2
    <groupId>org.springframework.boot</groupId>
3
    <artifactId>spring-boot-starter-test</artifactId>
4
    <version>2.4.0</version>
5
    <scope>test</scope>
6
</dependency>



Simple Text

The library in version 7 is not so different from the previous versions. Therefore, the code has changed only minimally, although there are some notable differences. 

To start with the iText 7 library, we should learn first how to generate a PDF containing simple text.

Note: this example uses JDK15, but it's not a hard constraint. The code should work fine with JDK8 as well.

Generate PDF Content

To generate our first PDF with the library we need to prepare several instances to be able to add the content. Our goal is to prepare an instance of com.itextpdf.layout.Document class and add some content there. 

The library uses a concept quite similar to DOM where the root element is represented by the instance of Document class. We can add any block element there (e.g. paragraph, list, or table). The block elements can contain more specific objects (e.g. text or image).

To start, we need to follow these steps:

  1. Create an instance of PdfWriter class (line 13) to specify the target file name and path and optionally (as is our case) create an instance of WritterProperties class to specify the desired PDF version (the version is 2.0 in our case) for the generated PDF (lines 11-12). The generated PDF will be saved into the file specified in the variable file simplePdf (line 10).
  2. Create an instance of PdfDocument class to handle the writing of the added content according to the PDF specification (line 14).
  3. Create an instance of Document class as the main point to work with the PDF. It serves as the root element where we can add all the desired elements representing our content (line 15).
  4. Define the text to be added into the PDF and add it wrapped as a Paragraph element into the Document instance (line 17). Of course, we can add more content, but it's sufficient for now.
Java
 




x


 
1
@Slf4j
2
class DzoneTests {
3
  
4
    final static Logger log = LoggerFactory.getLogger(DzoneTests.class);
5

          
6
    @Test
7
    void simpleText() throws Exception {
8
        var textContent = "Sapiensplendide noluisse ... mollis verterem alia regione quidam.";
9

          
10
        String simplePdf = "target/dzone-simple-text.pdf";
11
        WriterProperties wp = new WriterProperties();
12
        wp.setPdfVersion(PdfVersion.PDF_2_0);
13
        try (PdfWriter writer = new PdfWriter(simplePdf, wp);
14
                PdfDocument pdfDocument = new PdfDocument(writer);
15
                Document document = new Document(pdfDocument)) {
16

          
17
            document.add(new Paragraph(textContent));
18

          
19
        } catch (FileNotFoundException e) {
20
            log.error("Creating PDF failed", e);
21
            throw new ITextException(e.getMessage());
22
        }
23

          
24
        // to be tested later 
25
    }
26

          
27
}



Note: you can find a similar example using iText 5. Be aware that the text in the code above (the literal assigned to variable textContent) is not complete in order to make the example readable. The value itself is not important. You may need the whole code.

Now, we can check the output of the generated code from the code above (see the next screenshot):

The result of generated simple PDF

The result of generated simple PDF.


In thedzone-simple-text.pdffile, we can also find the desired values of PDF properties as highlighted in the screenshot below with red. You can see thePDF Producervalue added by iText Library and PDF Version specified earlier in WritterProperties by us (line 12).

Simple PDF properties

The properties of generated simple PDF.


Test Generated PDF Content

The generated PDF should also be tested to verify that the content has appeared as intended. There are several ways to test such content, but the simplest way is to check the PDF content as text since no formatting of the content has been added yet.

To test the PDF, we need to know the file path we used for PDF generation (the variable simplePdf) and follow these steps:

  1. Create an instance of PdfReaderclass to specify the filename we want to load (line 11).
  2. Create an instance of PdfDocumentclass as the main point to work with the document, which is the same as before (line 11).
  3. Read the first page from the PDF as a text with the help of LocationTextExtractionStrategy class (lines 12-14) from the iText library.
  4. Verify the first 10 characters to be the same as they were generated (line 11). Note: such a test is not perfect, but for our purposes it is appropriate.
Java
 




x


 
1
@Slf4j
2
class DzoneTests {
3

          
4
    private static Lorem lorem = LoremIpsum.getInstance();
5

          
6
    @Test
7
    void simpleText() throws Exception {
8
        String simplePdf = "target/dzone-simple-text.pdf";
9
        // generate PDF as in previous example
10
      
11
        try (PdfDocument pdfDocument = new PdfDocument(new PdfReader(simplePdf))) {
12
            String firstPageContent = PdfTextExtractor.getTextFromPage(
13
              pdfDocument.getFirstPage(), 
14
              new LocationTextExtractionStrategy());
15
            assertThat(firstPageContent).startsWith(textContent.substring(0, 10));
16
        }
17
    }
18

          
19
}



When thegenerateSimplePdftest is triggered (e.g. within the preferred IDE, Eclipse in our case), then the new file dzone-simple.pdf can be found under the target folder in your project. Moreover, we verified that the PDF contains the expected content when the test passed successfully (see screenshot below).

JUnit interface test complete

IDE result from executing generateSimplePdf test

Styled Text

Since we know how to generate a PDF, we can move on to investigate the possibilities of styling a text (more "advanced" objects like tables or QR codes are not within this scope). This part is focused on these areas:

  1. Styling of text: block elements inside a single paragraph.
  2. Styling of paragraph: paragraphs inside the document (on the page).

Styling of Text

When we want to style some text, we need to add an instance of Textclass into the instance ofParagraphclass (to use the overloadedaddmethod). With that, we can define the specific features of every defined Text instance. To achieve this, we need to follow these steps:

  1. Create an instance of Document (lines 7-10). It's the same as it was demonstrated in our first example.
  2. Create an instance of Paragraphclass where all the styled Text elements will be added later (line 12).
  3. Create an instance of Textclass with the desired features (lines 13, 15, and 17).
  4. Any line break can be achieved by adding a new line break character into the paragraphinstance (lines 14 and 16).
  5. The styling itself is realized by the methodstyledTextwith the set of passed arguments to be set on Text instance (lines 35-62). The only tricky part is the creation ofPdfFontclass from the passed family name as aString(lines 63-70). We just translate the checkedIOExceptioninto our runtimeITextExceptionto make our code easier.
Java
 




x
70


 
1
@Test
2
void styledText() throws Exception {
3
    var label1 = "big blue Courier font";
4
    var label2 = "underlined bold default font with yellow background";
5
    var label3 = "crossed italic";
6

          
7
    String simplePdf = "target/dzone-styled-text.pdf";
8
    try (PdfWriter writer = new PdfWriter(simplePdf);
9
            PdfDocument pdfDocument = new PdfDocument(writer);
10
            Document document = new Document(pdfDocument)) {
11

          
12
        Paragraph paragraph = new Paragraph();
13
        paragraph.add(styledText(label1, BLUE, null, COURIER, 30f, false, false, false, false));
14
        paragraph.add("\n");
15
        paragraph.add(styledText(label2, RED, YELLOW, null, null, true, false, true, false));
16
        paragraph.add("\n");
17
        paragraph.add(styledText(label3, null, null, null, null, false, true, false, true));
18
        document.add(paragraph);
19

          
20
    } catch (FileNotFoundException e) {
21
        log.error("Creating PDF failed", e);
22
        throw new ITextException(e.getMessage());
23
    }
24

          
25
    try (PdfDocument pdfDocument = new PdfDocument(new PdfReader(simplePdf))) {
26
        String firstPageContent = PdfTextExtractor.getTextFromPage(
27
          pdfDocument.getFirstPage(), 
28
          new LocationTextExtractionStrategy());
29
        assertThat(firstPageContent).startsWith(label1);
30
        assertThat(firstPageContent).contains(label2);
31
        assertThat(firstPageContent).endsWith(label3);
32
    }
33
}
34

          
35
public Text styledText(String label, Color color,   Color backgroundColor, String fontFamily, Float fontSize, boolean isBold, boolean isItalic, boolean isUnderline, boolean isLineThrough) {
36
    Text text = new Text(label);
37
    if (nonNull(color)) {
38
        text.setFontColor(color);
39
    }
40
    if (nonNull(backgroundColor)) {
41
        text.setBackgroundColor(backgroundColor);
42
    }
43
    if (nonNull(fontFamily)) {
44
        text.setFont(createFont(fontFamily));
45
    }
46
    if (nonNull(fontSize)) {
47
        text.setFontSize(fontSize);
48
    }
49
    if (isBold) {
50
        text.setBold();
51
    }
52
    if (isItalic) {
53
        text.setItalic();
54
    }
55
    if (isUnderline) {
56
        text.setUnderline();
57
    }
58
    if (isLineThrough) {
59
        text.setLineThrough();
60
    }
61
    return text;
62
}
63

          
64
PdfFont createFont(String fontFamily) {
65
    try {
66
        return PdfFontFactory.createFont(fontFamily);
67
    } catch (IOException e) {
68
        throw new ITextException("Font creation failed", e);
69
    }
70
}



The generated PDF contains a single paragraph element with three styled text blocks, each one on a separate line (see the next screenshot).

The result of styled text in PDF

The result of styled text in PDF.

Styling of Paragraph

As well as styling eachTextelement independently, we can also do a similar styling on a whole Paragraphelement. These steps demonstrate how to do that:

  1. Create an instance ofDocumentas done before (lines 7-10) same as before.
  2. Create an instance ofParagraphclass with the rotation of 45° (lines 12-14). Please be aware you need to pass the rotation value to the library in radians. Such logic is encapsulated in thecalculateRadiusFromDegreemethod (lines 42-45).
  3. Create an instance of Paragraph class green dashed borderline. In order to add a paragraph border with some styles, you need to create a new instance ofcom.itextpdf.layout.borders.Borderclass with the desired features first and pass it tosetBordermethod. We used theDashedBorderclass for that purpose, passing the values in the constructor (lines 16-18). Note: there are more options for border styling. You can find another example achieved by theSolidBorderclass in the next example.
  4. Create an instance of Paragraphdefined with a margin (the offset of the paragraph on the page) and padding (the offset of the elements in the paragraph). We set 3 pixels for the margin and 6 pixels for the padding (lines 21-22). We can check the location of the solid border in the last paragraph in the next image to see those settings. 
Java
 




xxxxxxxxxx
1
43


 
1
@Test
2
void styledParagraph() throws Exception {
3
    var label1 = "45° rotation";
4
    var label2 = "green solid border";
5
    var label3 = "6px margin & 3px padding & solid border";
6

          
7
    String simplePdf = "target/dzone-styled-paragraph.pdf";
8
    try (PdfWriter writer = new PdfWriter(simplePdf);
9
            PdfDocument pdfDocument = new PdfDocument(writer);
10
            Document document = new Document(pdfDocument)) {
11

          
12
        Paragraph rotatedParagraph = new Paragraph(label1);
13
        rotatedParagraph.setRotationAngle(calculateRadiusFromDegree(45f));
14
        document.add(rotatedParagraph);
15

          
16
        Paragraph borderedParagraph = new Paragraph(label2);
17
        borderedParagraph.setBorder(new DashedBorder(GREEN, 2f));
18
        document.add(borderedParagraph);
19

          
20
        Paragraph offsetedParagraph = new Paragraph(label3);
21
        offsetedParagraph.setMargin(6f);
22
        offsetedParagraph.setPadding(3f);
23
        offsetedParagraph.setBorder(new SolidBorder(1f));
24
        document.add(offsetedParagraph);
25

          
26

          
27
    } catch (FileNotFoundException e) {
28
        log.error("Creating PDF failed", e);
29
        throw new ITextException(e.getMessage());
30
    }
31

          
32
    try (PdfDocument pdfDocument = new PdfDocument(new PdfReader(simplePdf))) {
33
        String firstPageContent = PdfTextExtractor.getTextFromPage(
34
          pdfDocument.getFirstPage(), 
35
          new LocationTextExtractionStrategy());
36
//          assertThat(firstPageContent).contains(label1);
37
        assertThat(firstPageContent).contains(label2);
38
        assertThat(firstPageContent).contains(label3);
39
    }
40
}
41

          
42
private double calculateRadiusFromDegree(Float rotation) {
43
    // half rotation in Radians is Pi (3.14) -> full rotation is 2 Pi
44
    return PI / 180 * rotation;
45
}



The generated PDF contains three paragraph elements with the defined styling (see the next screenshot).

The result of styled paragraph in PDFThe result of a styled paragraph in PDF.

What else can be done?

As I said in the beginning, the IText 7 is a quite powerful library and we just scratched the surface of it in this article. Other features of the library include:

  • more elements (e.g. tables, barcodes or QR codes),
  • add behavior (e.g. layers, forms, bookmarks or attachments),
  • modify PDF (e.g. add page counter or watermark),
  • convert an HTML into PDF,
  • test PDF formatting,
  • and more.

Conclusion

This article has covered the basics of the IText 7 usage. It was started with the generation of a simple PDF. After that, some text and paragraph styling were added. You can find the demonstrated codes in my GitHub repository.

In the next article, I will cover the generation of barcodes and QR codes.

IText PDF Library unit test Element

Opinions expressed by DZone contributors are their own.

Related

  • Practical Use of Weak Symbols
  • Python and Open-Source Libraries for Efficient PDF Management
  • Improving Java Code Security
  • Reading an HTML File, Parsing It and Converting It to a PDF File With the Pdfbox Library

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!