Kotlin + Spring Boot + iText PDF - Export data to PDF example

Hello everyone, today we will learn how to export and download the data as a PDF file in a Kotlin, Spring Boot 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:

  • Spring Boot 
  • Kotlin
  • iText PDF
  • H2DB
  • Spring Data JPA


Project Directory:


Gradle Build(build.gradle.kts) 

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "2.5.4"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.21"
kotlin("plugin.spring") version "1.5.21"
kotlin("plugin.jpa") version "1.5.21"
}

group = "com.knf.dev"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
// https://mvnrepository.com/artifact/com.itextpdf/itextpdf
implementation("com.itextpdf:itextpdf:5.0.6")

}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}

tasks.withType<Test> {
useJUnitPlatform()
}
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "2.5.4"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.21"
kotlin("plugin.spring") version "1.5.21"
kotlin("plugin.jpa") version "1.5.21"
}

group = "com.knf.dev"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
// https://mvnrepository.com/artifact/com.itextpdf/itextpdf
implementation("com.itextpdf:itextpdf:5.0.6")

}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Model (Employee.kt)

package com.knf.dev.KotlinSpringExportPDF.model

import javax.persistence.*

@Entity
@Table(name = "employees")
class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0

@Column(name = "firstname")
var firstName: String? = null

@Column(name = "lastname")
var lastName: String? = null

protected constructor() {}
constructor(firstName: String?, lastName: String?) {
this.firstName = firstName
this.lastName = lastName
}
}

The @Entity annotation specifies that the class is an entity and is mapped to a database table. The @Table annotation specifies the name of the database table to be used for mapping. The @Id annotation specifies the primary key of an entity and the @GeneratedValue provides for the specification of generation strategies for the values of primary keys. The @Column annotation is used to specify the mapped column for a persistent property or field. If no Column annotation is specified, the default value will be applied

DAO layer(EmployeeRepository.kt)

package com.knf.dev.KotlinSpringExportPDF.repository

import com.knf.dev.KotlinSpringExportPDF.model.Employee
import org.springframework.data.repository.CrudRepository


interface EmployeeRepository : CrudRepository<Employee?, Long?>

Spring @Repository annotation is used to indicate that the class provides the mechanism for storage, retrieval, search, update and delete operation on objects.

Utility(PDFGenerator.kt)

package com.knf.dev.KotlinSpringExportPDF.util

import com.itextpdf.text.*
import com.itextpdf.text.pdf.PdfPCell
import com.itextpdf.text.pdf.PdfPTable
import com.itextpdf.text.pdf.PdfWriter
import com.knf.dev.KotlinSpringExportPDF.model.Employee
import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.util.stream.Stream


object PDFGenerator {
private val logger = LoggerFactory.getLogger(PDFGenerator::class.java)
fun employeePDFReport(employees: List<Employee>): ByteArrayInputStream {
val document = Document()
val out = ByteArrayOutputStream()
try {
PdfWriter.getInstance(document, out)
document.open()

// Add Text to PDF file ->
val font = FontFactory.getFont(
FontFactory.COURIER, 14f,
BaseColor.BLACK
)
val para = Paragraph("Employee Table", font)
para.alignment = Element.ALIGN_CENTER
document.add(para)
document.add(Chunk.NEWLINE)
val table = PdfPTable(3)
// Add PDF Table Header ->
Stream.of("ID", "First Name", "Last Name").
                                 forEach { headerTitle: String? ->
val header = PdfPCell()
val headFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD)
header.backgroundColor = BaseColor.LIGHT_GRAY
header.horizontalAlignment = Element.ALIGN_CENTER
header.borderWidth = 2f
header.phrase = Phrase(headerTitle, headFont)
table.addCell(header)
}
for (employee in employees) {
val idCell = PdfPCell(Phrase(employee.id.toString()))
idCell.paddingLeft = 4f
idCell.verticalAlignment = Element.ALIGN_MIDDLE
idCell.horizontalAlignment = Element.ALIGN_CENTER
table.addCell(idCell)
val firstNameCell = PdfPCell(Phrase(employee.firstName))
firstNameCell.paddingLeft = 4f
firstNameCell.verticalAlignment = Element.ALIGN_MIDDLE
firstNameCell.horizontalAlignment = Element.ALIGN_LEFT
table.addCell(firstNameCell)
val lastNameCell = PdfPCell(Phrase(employee.lastName.toString()))
lastNameCell.verticalAlignment = Element.ALIGN_MIDDLE
lastNameCell.horizontalAlignment = Element.ALIGN_RIGHT
lastNameCell.paddingRight = 4f
table.addCell(lastNameCell)
}
document.add(table)
document.close()
} catch (e: DocumentException) {
logger.error(e.toString())
}
return ByteArrayInputStream(out.toByteArray())
}
}

Controller(EmployeeController.kt)

package com.knf.dev.KotlinSpringExportPDF.controller

import com.knf.dev.KotlinSpringExportPDF.model.Employee
import com.knf.dev.KotlinSpringExportPDF.repository.EmployeeRepository
import com.knf.dev.KotlinSpringExportPDF.util.PDFGenerator.employeePDFReport
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 java.io.IOException


@RestController
@RequestMapping("/api/pdf")
class EmployeeController {
@Autowired
var employeeRepository: EmployeeRepository? = null

@GetMapping(value = ["/employees"], produces = [MediaType.APPLICATION_PDF_VALUE])
@Throws(
IOException::class
)
fun employeeReport(): ResponseEntity<InputStreamResource> {
val employees = employeeRepository!!.findAll() as List<Employee?>
val bis = employeePDFReport(employees as List<Employee>)
val headers = HttpHeaders()
headers.add("Content-Disposition", "inline; filename=employees.pdf")
return ResponseEntity.ok().headers(headers).
                              contentType(MediaType.APPLICATION_PDF)
.body(InputStreamResource(bis))
}
}

The @RestController annotation was introduced in Spring 4.0 to simplify the engendering of RESTful web services. It's a convenience annotation that combines @Controller and @ResponseBody.
@RequestMapping annotation maps HTTP requests to handler methods of MVC and REST controllers.

Spring Boot Driver

package com.knf.dev.KotlinSpringExportPDF

import com.knf.dev.KotlinSpringExportPDF.model.Employee
import com.knf.dev.KotlinSpringExportPDF.repository.EmployeeRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import java.util.*


@SpringBootApplication
class KotlinSpringExportPdfApplication : CommandLineRunner {
@Autowired
var repository: EmployeeRepository? = null

@Throws(Exception::class)
override fun run(vararg args: String) {
if (repository!!.count() == 0L) {
// save a list of Employees
repository!!.saveAll(
Arrays.asList(
Employee("Adam", "John"),
Employee("Sibin", "M"),
Employee("Arun", "Mohan"),
Employee("Scott", "Morrison"),
Employee("Hikaru", "Nakamura"),
Employee("Ishivaka", "Yusuke")
)
)
}
}

companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(KotlinSpringExportPdfApplication::class.java, *args)
}
}
}

The @SpringBootApplication annotation is a convenience annotation that combines the @EnableAutoConfiguration, @Configuration and the @ComponentScan annotations.

Run Spring Boot application

Hit this URL in your local system, http://localhost:8080/api/pdf/employees





Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete