Spring Boot iText PDF Generation Example from MySQL

SpringBoot iText pdf generation example

Tutorial: “Spring Boot iText PDF Generation Example – Extract MySQL Data to PDF File”

iText is a library for creating and manipulating PDF files in Java and .NET. In the tutorial, we show you how to create a SpringBoot RestAPIs application that uses Spring JPA & iText library to extract data from MySQL records to a PDF file in table format.

What will we do?

What will we do?


  • Create SpringBoot project
  • Customer Model
  • JPA Customer Repository
  • Implement PDF Generator
  • Implement RestAPI Controller
  • Initial Customers
  • Database Configuration
  • Run & Check Results
Related posts:


Technologies

– SpringBoot
– iText
– MySQL

Practice – SpringBoot Pdf generation example

Project Structure ->

Spring Boot iText PDF RestAPI - Project structure
Spring Boot iText PDF RestAPI generation example – Project structure

Create SpringBoot project – Spring Boot iText PDF Generation Example

We use SpringToolSuite to create a SpringBoot project with below dependencies:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>      
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>      
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.0.6</version>
</dependency>   
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Implement Java Model class

We create a Java class model Customer.java with 3 attributes {i, firstname, lastname} ase below code:


package com.loizenai.pdfreport.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name = "customers")
public class Customer{
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;
 
	@Column(name = "firstname")
	private String firstName;
 
	@Column(name = "lastname")
	private String lastName;
 
	protected Customer() {
	}
 
	public Customer(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
 
	public void setId(Long id) {
		this.id = id;
	}
	
	public Long getId() {
		return this.id;
	}
	
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	
	public String getFirstName() {
		return this.firstName;
	}
	
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	public String getLastName() {
		return this.lastName;
	}
	
	@Override
	public String toString() {
		return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
	}
}

Create SpringBoot JPA Repository for PDF Generation Example

We use Spring CrudRepository class to build a CustomerRepository to manipulate data with database:

CustomerRepository.java ->


package com.loizenai.pdfreport.repository;

import org.springframework.data.repository.CrudRepository;

import com.loizenai.pdfreport.model.Customer;
 
public interface CustomerRepository extends CrudRepository<Customer, Long>{
}

Implement SpringBoot iText Pdf Generator Example

For generating data to PDF file, we use APIs of iText Pdf libray as below coding in PDFGenerator.java file:


package com.loizenai.pdfreport.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.loizenai.pdfreport.model.Customer;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFGenerator {
	
	private static Logger logger = LoggerFactory.getLogger(PDFGenerator.class);
	
	public static ByteArrayInputStream customerPDFReport(List<Customer> customers) {
		Document document = new Document();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        
        try {
        	
        	PdfWriter.getInstance(document, out);
            document.open();
        	
            // Add Text to PDF file ->
        	Font font = FontFactory.getFont(FontFactory.COURIER, 14, BaseColor.BLACK);
        	Paragraph para = new Paragraph( "Customer Table", font);
        	para.setAlignment(Element.ALIGN_CENTER);
        	document.add(para);
        	document.add(Chunk.NEWLINE);
        	
        	PdfPTable table = new PdfPTable(3);
        	// Add PDF Table Header ->
            Stream.of("ID", "First Name", "Last Name")
	            .forEach(headerTitle -> {
		              PdfPCell header = new PdfPCell();
		              Font headFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD);
		              header.setBackgroundColor(BaseColor.LIGHT_GRAY);
		              header.setHorizontalAlignment(Element.ALIGN_CENTER);
		              header.setBorderWidth(2);
		              header.setPhrase(new Phrase(headerTitle, headFont));
		              table.addCell(header);
	            });
            
            for (Customer customer : customers) {
            	PdfPCell idCell = new PdfPCell(new Phrase(customer.getId().toString()));
            	idCell.setPaddingLeft(4);
            	idCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            	idCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                table.addCell(idCell);

                PdfPCell firstNameCell = new PdfPCell(new Phrase(customer.getFirstName()));
                firstNameCell.setPaddingLeft(4);
                firstNameCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                firstNameCell.setHorizontalAlignment(Element.ALIGN_LEFT);
                table.addCell(firstNameCell);

                PdfPCell lastNameCell = new PdfPCell(new Phrase(String.valueOf(customer.getLastName())));
                lastNameCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                lastNameCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                lastNameCell.setPaddingRight(4);
                table.addCell(lastNameCell);
            }
            document.add(table);
            
            document.close();
        }catch(DocumentException e) {
        	logger.error(e.toString());
        }
        
		return new ByteArrayInputStream(out.toByteArray());
	}
}

– Segment Code to add PDF text with iText:


// Add Text to PDF file ->
Font font = FontFactory.getFont(FontFactory.COURIER, 14, BaseColor.BLACK);
Paragraph para = new Paragraph( "Customer Table", font);
para.setAlignment(Element.ALIGN_CENTER);
document.add(para);
document.add(Chunk.NEWLINE);

– Segment code to create PDF table having 3 columns:


PdfPTable table = new PdfPTable(3);
...
document.add(table);

-> Create table’s headers:


Stream.of("ID", "First Name", "Last Name")
    .forEach(headerTitle -> {
          PdfPCell header = new PdfPCell();
          Font headFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD);
          header.setBackgroundColor(BaseColor.LIGHT_GRAY);
          header.setHorizontalAlignment(Element.ALIGN_CENTER);
          header.setBorderWidth(2);
          header.setPhrase(new Phrase(headerTitle, headFont));
          table.addCell(header);
    });

-> Add table’s rows, each row has 3 cells that contains a Customer’s data: {id, firstName, lastName}:


for (Customer customer : customers) {
	PdfPCell idCell = new PdfPCell(new Phrase(customer.getId().toString()));
	idCell.setPaddingLeft(4);
	idCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
	idCell.setHorizontalAlignment(Element.ALIGN_CENTER);
    table.addCell(idCell);

    PdfPCell firstNameCell = new PdfPCell(new Phrase(customer.getFirstName()));
    firstNameCell.setPaddingLeft(4);
    firstNameCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    firstNameCell.setHorizontalAlignment(Element.ALIGN_LEFT);
    table.addCell(firstNameCell);

    PdfPCell lastNameCell = new PdfPCell(new Phrase(String.valueOf(customer.getLastName())));
    lastNameCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    lastNameCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
    lastNameCell.setPaddingRight(4);
    table.addCell(lastNameCell);
}

Implement SpringBoot PDF Generation Example RestAPI Controller

CustomerRestAPIs ->


package com.loizenai.pdfreport.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
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 com.loizenai.pdfreport.model.Customer;
import com.loizenai.pdfreport.repository.CustomerRepository;
import com.loizenai.pdfreport.util.PDFGenerator;

@RestController
@RequestMapping("/api/pdf")
public class CustomerRestAPIs {
	
    @Autowired
    CustomerRepository customerRepository;

    @GetMapping(value = "/customers",
            produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<InputStreamResource> customersReport() throws IOException {
        List<Customer> customers = (List<Customer>) customerRepository.findAll();

        ByteArrayInputStream bis = PDFGenerator.customerPDFReport(customers);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "inline; filename=customers.pdf");

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_PDF)
                .body(new InputStreamResource(bis));
    }
}

SpringBoot Initial Data for MySQL database

– In main class, we use CommandLineRunner to init Customer’s records:


package com.loizenai.pdfreport;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.loizenai.pdfreport.model.Customer;
import com.loizenai.pdfreport.repository.CustomerRepository;

@SpringBootApplication
public class SpringJpaPdfReportApplication  implements CommandLineRunner{

	@Autowired
	CustomerRepository repository;
	
	public static void main(String[] args) {
		SpringApplication.run(SpringJpaPdfReportApplication.class, args);
	}

    @Override
    public void run(String... args) throws Exception {
    	
    	if(repository.count() == 0) {
    		// save a list of Customers
    		repository.saveAll(Arrays.asList(new Customer("Jack", "Smith"), 
    										new Customer("Adam", "Johnson"), 
    										new Customer("Kim", "Smith"),
    										new Customer("David", "Williams"), 
    										new Customer("Peter", "Davis")));
    	}

    }
}

SpringBoot MySQL Database Configuration

application.properties ->


spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=12345
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop

Run & Check Results

Run the SpringBoot project, results:

-> MySQL’s records:

SpringBoot RestAPI iText PDF - MySQL check
Spring Boot iText PDF RestAPI generation example – MySQL check

-> PDF File:

Pdf table generated result
Pdf table generated result

Further Reading

iTextPDF Java API

More reading:

SourceCode – SpringBoot RestAPI iText PDF file example

Full sourcecode for the tutorial: “Spring Boot RestAPI using iText to generate data from MySQL to PDF File”:

SpringBoot-RestAPI-iText-PDF-Generator

Leave a Reply

Your email address will not be published. Required fields are marked *