Spring MVC PDF and Excel View Example (using iText)

By Dhiraj Ray, 05 April,2017  

This tutorial explains about generating PDF and excel documents in Spring web mvc using iText PDF library. It uses the content negotiation view resolver provided by spring to generate PDF and excel views. Here we will be creating a simple spring mvc web application using annotations and java configs. This application will be capable of negotiating views between pdf and excel based on the HTTP request. If you are looking for json, xml and html content view resolver then visit here - content negotiation example - json and xml

Project Structure

Here all the spring config classes are inside the package com.devglan.config and all the static components inside webapp/ui. The jsp pages are defined inside WEB-INF/jsp.

pdf-excel-project-strct

Maven Dependencies

pom.xml

The dependencies here are usual dependencies for a spring mvc application.

spring-webmvc - provides core HTTP integration including filters. Including this dependency automatically includes spring-web.

itext - It is required for pdf view.

poi - It is required for excel view.

maven-war-plugin - This is required to build war package by maven as we are excluding web.xml based configurations.

<modelVersion>4.0.0</modelVersion> <groupId>com.devglan</groupId> <artifactId>spring-mvc-content-negotiation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>4.3.7.RELEASE</spring.version> <jstl.version>1.2</jstl.version> <servlet.version>3.0.1</servlet.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.9</version> </dependency> </dependencies> <build> <finalName>spring-mvc-content-negotiation</finalName> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warName>spring-mvc</warName> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </pluginManagement> </build>

Defining Spring Controller

Following is the controller class which is mapped for /users. It is a normal controller class that returns ModelAndView and based on the requested url the resolver will be identified and corresponding response will be generated.

UserController.java
package com.devglan.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.devglan.model.UserDetails; import com.devglan.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/users", method = RequestMethod.GET) public ModelAndView userDetails() { ModelAndView modelAndView = new ModelAndView(); List userDetails = userService.getUserDetails(); modelAndView.addObject("users", userDetails); modelAndView.setViewName("userDetails"); return modelAndView; } }

Defining Spring MVC Service

Following is the service class that generates user details and returns to the controller.

UserServiceImpl.java
package com.devglan.service.impl; import java.util.Arrays; import java.util.List; import org.springframework.stereotype.Service; import com.devglan.model.UserDetails; import com.devglan.service.UserService; @Service public class UserServiceImpl implements UserService { public List getUserDetails() { UserDetails ud1 = new UserDetails(); ud1.setEmail("john@example.com"); ud1.setFirstName("John"); ud1.setLastName("Doe"); UserDetails ud2 = new UserDetails(); ud2.setEmail("vicky@gmail.com"); ud2.setFirstName("vicky"); ud2.setLastName("Ray"); UserDetails ud3 = new UserDetails(); ud3.setEmail("abc@yahoo.co.in"); ud3.setFirstName("abc"); ud3.setLastName("greg"); UserDetails ud4 = new UserDetails(); ud4.setFirstName("xyz"); ud4.setEmail("xyz@gmail.com"); ud4.setLastName("Bard"); return Arrays.asList(ud1, ud2, ud3, ud4); } }

Let us define the POJO now.

UserDetails.java
package com.devglan.model; public class UserDetails { private String firstName; private String lastName; private String email; //getters and setters goes here }

Configuring ServletContex in Spring MVC

This implementaion will be automatically detected by SpringServletContainerInitializer which itself is bootstrapped automatically by any Servlet 3.0 container such as tomcat.

AppInitializer.java
package com.devglan.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class AppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(WebConfig.class); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); } }

Configuring Pdf and Excel view in Spring MVC

ContentNegotiationConfigurer creates a ContentNegotiationManagernand configures it with one or more ContentNegotiationStrategy instances.

configureViewResolvers() will register different view resolvers. Here we are registering view resolvers for pdf, xls and xlsx view. Hence, when a request is made with url ending .xls, a xls view will be rendered and similarly xlsx for view for url ending with .xlsx

WebConfig.java
@Configuration @EnableWebMvc @ComponentScan(basePackages = "com.devglan") public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer .defaultContentType(MediaType.TEXT_HTML) .ignoreAcceptHeader(true); } @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/jsp/", ".jsp").viewClass(JstlView.class); registry.enableContentNegotiation( new XlsView(), new XlsxView(), new PdfView()); } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("/js/**").addResourceLocations("/ui/js/"); registry.addResourceHandler("/css/**").addResourceLocations("/ui/css/"); } }

Now, let us define thee different view classes configured above. Following class will create the pdf view using the model objects which we sent through our controller class.

PdfView.java
package com.devglan.view; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.view.document.AbstractPdfView; import com.devglan.model.UserDetails; import com.lowagie.text.Document; import com.lowagie.text.Element; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfWriter; public class PdfView extends AbstractPdfView { @Override public void buildPdfDocument(Map model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception { @SuppressWarnings("unchecked") List users = (List) model.get("users"); PdfPTable table = new PdfPTable(3); table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER); table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE); table.addCell("First Name"); table.addCell("Last Name"); table.addCell("Email"); for (UserDetails user : users) { table.addCell(user.getFirstName()); table.addCell(user.getLastName()); table.addCell(user.getEmail()); } document.add(table); } }

Following is the Xls view. It will create the Xls view using the model objects which we sent through our controller class.

XlsView
package com.devglan.view; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.servlet.view.document.AbstractXlsView; import com.devglan.model.UserDetails; public class XlsView extends AbstractXlsView { @Override public void buildExcelDocument(Map model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setHeader("Content-Disposition", "attachment; filename=\"users.xls\""); @SuppressWarnings("unchecked") List users = (List) model.get("users"); Sheet sheet = workbook.createSheet("Users Xls"); Row header = sheet.createRow(0); header.createCell(0).setCellValue("First Name"); header.createCell(1).setCellValue("Last Name"); header.createCell(2).setCellValue("Email"); int rowCount = 1; for (UserDetails user : users) { Row fruitRow = sheet.createRow(rowCount++); fruitRow.createCell(0).setCellValue(user.getFirstName()); fruitRow.createCell(1).setCellValue(user.getLastName()); fruitRow.createCell(2).setCellValue(user.getEmail()); } } }

Following is the Xlsx View class. It will create the Xlsx view using the model objects which we sent through our controller class.

XlsxView.java
package com.devglan.view; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.servlet.view.document.AbstractXlsxView; import com.devglan.model.UserDetails; public class XlsxView extends AbstractXlsxView { @Override public void buildExcelDocument(Map model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setHeader("Content-Disposition", "attachment; filename=\"users.xlsx\""); @SuppressWarnings("unchecked") List users = (List) model.get("users"); Sheet sheet = workbook.createSheet("Users Xlsx"); Row header = sheet.createRow(0); header.createCell(0).setCellValue("First Name"); header.createCell(1).setCellValue("Last Name"); header.createCell(2).setCellValue("Email"); int rowCount = 1; for (UserDetails user : users) { Row fruitRow = sheet.createRow(rowCount++); fruitRow.createCell(0).setCellValue(user.getFirstName()); fruitRow.createCell(1).setCellValue(user.getLastName()); fruitRow.createCell(2).setCellValue(user.getEmail()); } } }

Client Side Implementation

Following is the jsp page that will be rendered when no requests with any file extension.

userDetails.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title> Spring Boot Example</title> <link href="css/bootstrap.min.css" rel="stylesheet"> <script src="js/jquery-2.2.1.min.js"></script> <script src="js/bootstrap.min.js"></script> </head> <body> <div> <div class="container" style="margin:50px"> <div class="row text-center"><strong> User Details</strong></div> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-3 text-center"><strong>First Name</strong></div> <div class="col-md-3 text-center"><strong>Last Name</strong></div> <div class="col-md-3 text-center"><strong>Email</strong></div> </div> <c:forEach var="user" items="${users}"> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-3 text-center">${user.firstName}</div> <div class="col-md-3 text-center" >${user.lastName}</div> <div class="col-md-3 text-center">${user.email}</div> </div> </c:forEach> </div> </div> </body> </html>

Run Spring MVC Application

1. Deploy the application to tomcat.

2. Hit the url as http://localhost:8080/spring-mvc-content-negotiation-example/users.pdf and you can see following result.

contentnegotiatingviewresolver-pdf-view

2. Similarly you can hit http://localhost:8080/spring-mvc-content-negotiation-example/users.xls for xls view and http://localhost:8080/spring-mvc-content-negotiation-example/users.xlsx for xlsx view.

Conclusion

I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Download the source

References

Spring MVC Content Negotiation

Spring MVC

Spring Framework Wiki

Suggest more topics in suggestion section or write your own article and share with your colleagues.

Is this page helpful to you? Please give us your feedback below. We would love to hear your thoughts on these articles, it will help us improve further our learning process.

Further Reading: