iText PDF + SpringBoot RestAPI – Extract MySQL Data to PDF File

spring-boot-spring-jpa-export-data-pdf-table-file-by-itext-mysql-feature-image

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.

Related posts:
How to use Spring JPA with PostgreSQL | Spring Boot

Technologies

– SpringBoot
– iText 5.0.6
– MySQL

Practice

Project Structure ->

spring-boot-spring-jpa-export-data-pdf-table-file-by-itext-mysql-project-structure

Create SpringBoot project

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>

Customer Model

Customer.java ->


package com.grokonez.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);
	}
}

JPA Customer Repository

CustomerRepository.java ->


package com.grokonez.pdfreport.repository;

import org.springframework.data.repository.CrudRepository;

import com.grokonez.pdfreport.model.Customer;
 
public interface CustomerRepository extends CrudRepository{
}

Implement PDF Generator

PDFGenerator.java ->


package com.grokonez.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.grokonez.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 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 RestAPI Controller

CustomerRestAPIs ->


package com.grokonez.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.grokonez.pdfreport.model.Customer;
import com.grokonez.pdfreport.repository.CustomerRepository;
import com.grokonez.pdfreport.util.PDFGenerator;

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

    @GetMapping(value = "/customers",
            produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity customersReport() throws IOException {
        List customers = (List) 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));
    }
}

Initial Customers

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


package com.grokonez.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.grokonez.pdfreport.model.Customer;
import com.grokonez.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")));
    	}

    }
}

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:

spring-boot-spring-jpa-export-data-pdf-table-file-by-itext-mysql-records

-> PDF File:

spring-boot-spring-jpa-export-data-pdf-table-file-by-itext-mysql-results

SourceCode

SpringJpaPDFReport



By grokonez | October 15, 2018.

Last updated on May 2, 2021.



Related Posts


5 thoughts on “iText PDF + SpringBoot RestAPI – Extract MySQL Data to PDF File”

  1. 1. How can I make generated pdf file automatic download when I hit the api link(like your xls tutorial)
    2. How to make this as generic? For example I have different different objects like customer, user product and I want to make something generic to prepare pdf, xls and download?

    1. Hello, what you have to do is change only ine line of code, this change will let you open de pdf in one separated page and download de pdf:

      headers.add(“Content-Disposition”, “attachment; filename=customers.pdf”);

  2. Hi, Thank for this post. But i have somme difficulties to use this service by my restful (RestTemplate is my client template) ?

  3. Thank you for your post. I encountered by this error:
    “status”:500,”error”:”Internal Server Error”,”trace”:”org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class net.sf.jasperreports.repo.InputStreamResource] with preset Content-Type ‘application/pdf’.
    Please advice

Got Something To Say:

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

*