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

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

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

Related

  • Using Java Class Extension Library for Data-Oriented Programming - Part 2
  • Using Java Class Extension Library for Data-Oriented Programming
  • Automating Cucumber Data Table to Java Object Mapping in Your Cucumber Tests
  • What Is API-First?

Trending

  • How to Build Real-Time BI Systems: Architecture, Code, and Best Practices
  • Monolith: The Good, The Bad and The Ugly
  • How Can Developers Drive Innovation by Combining IoT and AI?
  • AI-Driven Root Cause Analysis in SRE: Enhancing Incident Resolution
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Using Barcodes in iText 7

Using Barcodes in iText 7

A developer shows us how to use Java to create several different types of bar codes and explains how these barcodes work to encode data.

By 
Arnošt Havelka user avatar
Arnošt Havelka
DZone Core CORE ·
Jan. 29, 21 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
9.7K Views

Join the DZone community and get the full member experience.

Join For Free

In my previous article, I reviewed the basics of iText 7. Here, I focus on the barcode support provided by the iText 7 library. Firstly, I'll provide a short overview of barcodes, and then demonstrate barcode generation for every supported barcode type in the library.

Overview

Here is a simple definition of ‘barcode’ according to Wikipedia:

A barcode or bar code is a method of representing data in a visual, machine-readable form.

Most barcode standards are managed by the GS1 organization. If you want to see some examples of barcodes, please check the barcode sheet on their site. In general, we recognize two basic barcode types:

  • Linear or one-dimensional (1D).
  • Matrix or multi-dimensional (2D).

iText 7 library supports many barcodes, but not all the options mentioned on Wikipedia. Nevertheless, I believe the library supports all the common ones. The section dedicated to 1D barcodes contains some generalization as there are five supported barcodes. Therefore, I'll begin with an explanation of generating the 2D barcodes, because there are only two of them.

Prerequisite: All the codes below, expect iText 7, are basic knowledge. Please check my previous article where I covered that. Additionally, my project has recently been upgraded to the latest libraries (Spring Boot 2.4.2 and iText 7.1.14).

2D Barcodes

Matrix or multi-dimensional (2D) barcodes are represented by black and white "dots." These barcodes are compact and capable of holding high-capacity symbols in the unit area.

iText 7 supports, as already mentioned, only two types of 2D barcodes: QR codes and Data Matrixes. Let's start with QR codes as this barcode is pretty common these days.

QR Code

A QR code (abbreviated from Quick Response code) often contains data for a locator, identifier, or tracker that points to a website or application. See Wikipedia for more details.

To start QR code generation, follow these steps:

  1. Create an instance of the PdfDocument class as the pdfDocument variable will be used as the main entry point to the PDF content. This instance represents the root element where any desired content can be added (lines 11-13).
  2. To create our first QR code, we should proceed with several steps in order to add a barcode instance into the pdfDocument properly. First, we need to create an instance of the BarcodeQRCode class dedicated to handling the QR code where we pass the barcode value (to be encoded into the QR code) as the constructor argument (line 15). This instance is assigned into the codeFormObject variable to be used next.
  3. Next, we create an instance of the PdfFormXObject class from our codeFormObject variable (line 16). Here we need to pass the pdfDocument instance.
  4. Also, we need to convert the form referenced by thecodeFormObject instance into an Image instance (line 17). We do that by using the createCodeImage method (lines 33-37) and storing it as a codeImage variable for use in the next step.
  5. Finally, we just add the image as the codeImage variable into the pdfDocument (line 18).
  6. Additionally, we may add the barcode value into the pdfDocument(line 20) in order to test PDF generation easily (lines 27-30).
Java
 




x


 
1
class DzoneBarcode2DTests {
2

          
3
    final static Logger log = LoggerFactory.getLogger(DzoneBarcode2DTests.class);
4

          
5
    static final String GITHUB_URL = "https://github.com/arnosthavelka/itext-poc/";
6

          
7
    @Test
8
    void qrBarcode() throws IOException {
9
        String targetPdf = "target/example-qrcode.pdf";
10

          
11
        try (PdfWriter writer = new PdfWriter(targetPdf);
12
                PdfDocument pdfDocument = new PdfDocument(writer);
13
                Document document = new Document(pdfDocument)) {
14

          
15
            var codeObject = new BarcodeQRCode(GITHUB_URL);
16
            PdfFormXObject codeFormObject = codeObject.createFormXObject(pdfDocument);
17
            Image codeImage = createCodeImage(codeFormObject);
18
            document.add(codeImage);
19

          
20
            document.add(new Paragraph(GITHUB_URL));
21

          
22
        } catch (FileNotFoundException e) {
23
            log.error("PDF creatiion failed", e);
24
            throw new ITextException(e.getMessage());
25
        }
26

          
27
        try (PdfDocument pdfDocument = new PdfDocument(new PdfReader(targetPdf))) {
28
            String pdfContent = PdfTextExtractor.getTextFromPage(pdfDocument.getFirstPage(), new LocationTextExtractionStrategy());
29
            assertThat(pdfContent).endsWith(GITHUB_URL);
30
        }
31
    }
32
  
33
    private Image createCodeImage(PdfFormXObject codeImage) {
34
        var codeQrImage = new Image(codeImage);
35
        codeQrImage.setWidth(100);
36
        return codeQrImage;
37
    }
38

          
39
}


Note: The test we added in the previous snippet is not testing the correctness of the QR code (the image itself), but just its processing. Hopefully, I will focus on such tests in a future article in this series.

When we look at the generated PDF we should find the QR code and the label of the encoded barcode value. See the below screenshot.

Screenshot of QR code (including encoded URL value) taken from example-qrcode.pdf.

Data Matrix

A data matrix consists of black and white dots arranged in either a square or rectangular pattern, also known as a matrix. The encoded information can be text or numeric data and it can store up to 2,335 alphanumeric letters. See Wikipedia for more details.

As already mentioned, the use of a data matrix barcode is almost the same as QR codes. We just need to use a different class (BarcodeDataMatrix instead of BarcodeQRCode). We can also simplify the previous verbose code. To generate a data matrix barcode, we should follow these steps:

  1. Create a pdfDocument instance in the same way as before (lines 5-7).
  2. Create an image representing our barcode based on the BarcodeDataMatrix class and put it into the pdfDocument (line 9).
  3. We can also add the barcode value into the pdfDocument(line 10) in order to easily test PDF generation (line 17).
Java
 




xxxxxxxxxx
1
19


 
1
@Test
2
void datamatrixBarcode() throws IOException {
3
    String targetPdf = "target/example-datamatrix.pdf";
4

          
5
    try (PdfWriter writer = new PdfWriter(targetPdf);
6
            PdfDocument pdfDocument = new PdfDocument(writer);
7
            Document document = new Document(pdfDocument)) {
8

          
9
        document.add(createCodeImage(new BarcodeDataMatrix(GITHUB_URL).createFormXObject(pdfDocument)));
10
        document.add(new Paragraph(GITHUB_URL));
11

          
12
    } catch (FileNotFoundException e) {
13
        log.error("PDF creatiion failed", e);
14
        throw new ITextException(e.getMessage());
15
    }
16

          
17
    ... // test PDF content as before
18
}


You can see the output of the generated data matrix barcode based on the code above in the next screenshot.

The screenshot of Data Matrix (including encoded URL value) taken from example-datamatrix.pdf.

1D Barcodes

Linear (1D) barcodes are represented by lines and spaces of various widths that create specific patterns. Since the library supports many 1D barcodes, I use a generalized code to avoid duplication.

Generalized Barcode Processing

The main principles of using the iText 7 library for barcode generation have been explained above. Therefore, the following steps are slightly simplified. This generalized method can be used to process different 1D barcode types very easily. In order to do that, follow these steps:

  1. Prepare a general method called generateBarcodewith these arguments (lines 1-18):
    • A test method name taken from the TestInfo instance (as you can see below) available with the JUnit framework (to be used as a barcode label in our PDF).
    • A barcode value to be encoded into the barcode.
    • A class of the desired Barcode extending the Barcode1D class.
  2. Create a pdfDocument instance as usual (lines 5-7).
  3. Add the passed barcode type taken from the barcodeEAN test method into the document instance (line 9) in order to easily test PDF generation (line 17). It serves only for demonstration purposes.
  4. Create a create1DBarcodemethod (lines 20-30) which accepts these arguments:
    • The pdfDocument instance.
    • A barcode value to be encoded into the barcode.
    • A class of the desired Barcode extending the Barcode1D class (line 10).
  5. Call the create1DBarcode method and add the result into the document instance (line 10).
Java
 




xxxxxxxxxx
1
32


 
1
private <C extends Barcode1D> void generateBarcode(
2
  String barcodeType, String barcodeValue, Class<C> barcodeClass) throws IOException {
3
    String targetPdf = "target/example-" + barcodeType + ".pdf";
4

          
5
    try (PdfWriter writer = new PdfWriter(targetPdf);
6
            PdfDocument pdfDocument = new PdfDocument(writer);
7
            Document document = new Document(pdfDocument)) {
8

          
9
        document.add(new Paragraph(barcodeType));
10
        document.add(create1DBarcode(pdfDocument, barcodeValue, barcodeClass));
11

          
12
    } catch (FileNotFoundException e) {
13
        log.error("Creating PDF failed", e);
14
        throw new ITextException(e.getMessage());
15
    }
16

          
17
    ... // test PDF content
18
}
19

          
20
private <C extends Barcode1D> Image create1DBarcode(
21
  PdfDocument pdfDocument, String code, Class<C> barcodeClass) {
22
    try {
23
        var codeObject = barcodeClass.getConstructor(PdfDocument.class).newInstance(pdfDocument);
24
        codeObject.setCode(code);
25
        return new Image(codeObject.createFormXObject(pdfDocument));
26
    } catch (InstantiationException | IllegalAccessException | 
27
             IllegalArgumentException | InvocationTargetException | 
28
             NoSuchMethodException | SecurityException e) {
29
        throw new ITextException("The creation of Barcode1D class " + barcodeClass.getName() + "failed", e);
30
    }
31
}


The create1DBarcode method from the code above is almost the same as the code for 2D barcode generation. Here are the only exceptions:

  1. A barcode value is not passed in the constructor, but by the setCode method.
  2. An instance of the desired class is not hardcoded into the code. Instead, we use a JDK feature to create a new instance from the passed class as an argument extending the Barcode1D class.

EAN Barcode

The International Article Number (also known as European Article Number or EAN) is used by systems in global trade to identify a specific retail product type, in a specific packaging configuration, from a specific manufacturer. This barcode is represented by the digits (0–9), unlike some other barcodes. See Wikipedia for more details.

To generate an EAN code, we just call the method generateBarcode with these arguments (line 3):

  • A test method name provided by the JUnit framework (as mentioned before).
  • The barcode value to be encoded into the barcode.
  • The BarcodeEAN class.
Java
 




x


 
1
@Test
2
void barcodeEAN(TestInfo ti) throws IOException {
3
    generateBarcode(ti.getTestMethod().get().getName(), "8590345410081", BarcodeEAN.class);
4
}


The generated EAN barcode based on the code above looks like this:

The screenshot of EAN (including test method name) taken from example-ean.pdf.

Code 39

Code 39 allows 43 characters that can be used in the barcode (e.g. A-Z, 0-9, $, %, space, etc.). There is an additional character (denoted as *) that can be used as both start and stop delimiters. Each character is composed of nine elements: five bars and four spaces. Three of the nine elements in each character are wide (binary value 1), and six elements are narrow (binary value 0). See Wikipedia for more details.

We can generate Code 39 using the same method as an EAN barcode mentioned above. We just call the generateBarcode method with the Barcode39 class as the last argument (line 3).

Java
 




x


 
1
@Test
2
void barcode39(TestInfo ti) throws IOException {
3
    generateBarcode(ti.getTestMethod().get().getName(), "A35-8579-78", Barcode39.class);
4
}


The generated Code 39 barcode based on the code above should look like this:

The screenshot of Code 39 (including test method name) taken from example-barcode39.pdf.

Code 128

Code 128 is a high-density linear barcode symbology defined in ISO/IEC 15417:2007. It is used for alphanumeric or numeric-only barcodes. See Wikipedia for more details.

We should use the Barcode128 class as an argument for the generateBarcode method (line 3).

Java
 




xxxxxxxxxx
1


 
1
@Test
2
void barcode128(TestInfo ti) throws IOException {
3
    generateBarcode(ti.getTestMethod().get().getName(), "https://github.com/arnosthavelka/itext-poc/", Barcode128.class);
4
}


The generated Code 128 barcode based on the code above looks like this:

The screenshot of Code 128 (including test method name) taken from example-barcode128.pdf.

MSI Barcode

MSI (also known as Modified Plessey) is a barcode symbology developed by the MSI Data Corporation, based on the original Plessey Code symbology. MSI is used primarily for inventory control, marking storage containers and shelves in warehouse environments. See Wikipedia for more details.

We can generate such a barcode by using the BarcodeMSI class as an argument to the generateBarcode method (line 3).

Java
 




x


 
1
@Test
2
void barcodeMSI(TestInfo ti) throws IOException {
3
    generateBarcode(ti.getTestMethod().get().getName(), "9788027107339", BarcodeMSI.class);
4
}


The generated MSI barcode based on the code above looks like this:

The screenshot of MSI barcode (including test method name) taken from example-barcodeMSI.pdf.

POSTNET

POSTNET (Postal Numeric Encoding Technique) is a barcode symbology used by the United States Postal Service to assist in directing mail. The ZIP Code or ZIP+4 code is encoded in half- and full-height bars. See Wikipedia for more details.

We can generate this final barcode in the same way as all the 1D barcodes above. Just pass the BarcodePostnet class as an argument to the generateBarcode method (line 3).

Java
 




x


 
1
@Test
2
void barcodePOSTNET(TestInfo ti) throws IOException {
3
    generateBarcode(ti.getTestMethod().get().getName(), "9788027107339", BarcodePostnet.class);
4
}


The generated POSTNET barcode based on the code above looks like this:

The screenshot of POSTNET barcode (including test method name) taken from example-barcodePOSTNET.pdf.

Conclusion

In this article, I provided detailed instructions for generating all barcodes supported by the iText 7 library. I began with an overview of generating every 2D barcode type before demonstrating the usage of 1D barcodes. You can find all the code mentioned above in my GitHub repository. 

In my next article, I plan to go back to the beginning and explain text formatting within the PDF page using iText 7.

Barcode IText Test method QR code Testing Data (computing) Matrix (protocol) Java (programming language) Library

Opinions expressed by DZone contributors are their own.

Related

  • Using Java Class Extension Library for Data-Oriented Programming - Part 2
  • Using Java Class Extension Library for Data-Oriented Programming
  • Automating Cucumber Data Table to Java Object Mapping in Your Cucumber Tests
  • What Is API-First?

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!