Quarkus Export data to PDF example
Hello everyone, today we will learn how to export and download the data as a PDF file in a Quarkus project.
PDF stands for the Portable Document Format, used to exhibit documents in an electronic form independent of the software, hardware, or operating system they are viewed on.
Technologies used:
- Quarkus 2.2.3.final
- iText 5.0.6
- H2DB
- Hibernate ORM panache
Project Directory:
Maven(pom.xml):
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project. It contains default values for most projects. Some of the configurations that can be designated in the POM is the project dependencies, the plugins or goals that can be executed, the build profiles, and so on. Other information such as the project version, description, developers, mailing lists, and such can withal be designated.
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.knf.dev.demo</groupId>
<artifactId>quarkus_export_data_to_pdf</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<maven.compiler.parameters>true</maven.compiler.parameters>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus-plugin.version>2.2.3.Final</quarkus-plugin.version>
<quarkus.platform.artifact-id>quarkus-universe-bom
</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.version>2.2.3.Final</quarkus.platform.version>
<surefire-plugin.version>2.22.1</surefire-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.0.6</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager
</java.util.logging.manager>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>
</project>
application.properties:
# datasource configuration
quarkus.datasource.db-kind = h2
quarkus.datasource.username = sa
# quarkus.datasource.password =
quarkus.datasource.jdbc.url = jdbc:h2:mem:test
# drop and create the database at startup
quarkus.hibernate-orm.database.generation=drop-and-create
Entity Class(Employee.java):
package org.knf.dev.demo.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String email;
private String country;
private int age;
private String role;
public Employee() {
super();
}
public Employee(String name, String email,
String country, int age, String role) {
super();
this.name = name;
this.email = email;
this.country = country;
this.age = age;
this.role = role;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
EmployeeRepository.java:
package org.knf.dev.demo.repository;
import javax.enterprise.context.ApplicationScoped;
import org.knf.dev.demo.entity.Employee;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
@ApplicationScoped
public class EmployeeRepository implements PanacheRepository<Employee> {
}
PDFHelper.java:
package org.knf.dev.demo.helper;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.stream.Stream;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.knf.dev.demo.entity.Employee;
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 PDFHelper {
public static ByteArrayInputStream
employeePDFReport(List<Employee> employees) {
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("Employee Table", font);
para.setAlignment(Element.ALIGN_CENTER);
document.add(para);
document.add(Chunk.NEWLINE);
PdfPTable table = new PdfPTable(6);
// Add PDF Table Header ->
Stream.of("ID", "Name", "Email", "Country", "Age", "Role").
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 (Employee employee : employees) {
PdfPCell idCell = new PdfPCell(new Phrase(String.
valueOf(employee.getId())));
idCell.setPaddingLeft(4);
idCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
idCell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(idCell);
PdfPCell nameCell =
new PdfPCell(new Phrase(employee.getName()));
nameCell.setPaddingLeft(4);
nameCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
nameCell.setHorizontalAlignment(Element.ALIGN_LEFT);
table.addCell(nameCell);
PdfPCell emailCell = new PdfPCell(new Phrase(String.
valueOf(employee.getEmail())));
emailCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
emailCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
emailCell.setPaddingRight(4);
table.addCell(emailCell);
PdfPCell countryCell = new PdfPCell(new Phrase(String.
valueOf(employee.getCountry())));
countryCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
countryCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
countryCell.setPaddingRight(4);
table.addCell(countryCell);
PdfPCell ageCell = new PdfPCell(new Phrase(String.
valueOf(employee.getAge())));
ageCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
ageCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
ageCell.setPaddingRight(4);
table.addCell(ageCell);
PdfPCell roleCell = new PdfPCell(new Phrase(String.
valueOf(employee.getRole())));
roleCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
roleCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
roleCell.setPaddingRight(4);
table.addCell(roleCell);
}
document.add(table);
document.close();
} catch (DocumentException e) {
}
return new ByteArrayInputStream(out.toByteArray());
}
}
EmployeeService.java:
package org.knf.dev.demo.service;
import java.io.ByteArrayInputStream;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
import org.knf.dev.demo.entity.Employee;
import org.knf.dev.demo.helper.PDFHelper;
import org.knf.dev.demo.repository.EmployeeRepository;
@ApplicationScoped
public class EmployeeService {
@Inject
EmployeeRepository employeeRepository;
@Transactional
public List<Employee> fetchAll() {
dummyDatas();
return employeeRepository.listAll();
}
public ByteArrayInputStream load() {
List<Employee> employees = fetchAll();
ByteArrayInputStream bis = PDFHelper.
employeePDFReport(employees);
return bis;
}
// generate dummy datas
public void dummyDatas() {
for (int i = 1; i <= 20; i++) {
employeeRepository.
persist(new Employee("sibin-" + i,
"mygmail@com-" + i, "USA",
54 + i, "Developer"));
}
}
}
EmployeeController.java:
package org.knf.dev.demo.controller;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.knf.dev.demo.service.EmployeeService;
@Path("/api/export-employees")
public class EmployeeController {
@Inject
EmployeeService employeeService;
@GET
public Response exportCSV() throws Exception {
return Response.ok(employeeService.load(),
MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition",
"attachment; filename = employees.pdf").
build();
}
}
Run & Test:
Start the application: java -jar quarkus-run.jar