Java Jasper Reports With Spring MVC

Do you like this?

Summary:
This example shows you how to generate a simple report using Jasper Reports with Spring MVC. We will also see how Maven can be utilized to handle library dependencies.


Content:

In this tutorial, I assume you've already had a fair understanding about Spring MVC, Maven, and Jasper Reports. Hence, I'm not gonna cover what they are and their terminologies here. Instead I will just jump into the practical side of it. Following is the content of our Maven pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>reporting</artifactId>
  <version>1</version>
  <name>Reporting</name>
  <description>To use JasperReport</description>
  
  <dependencies>
     
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-core</artifactId>
  		<version>3.2.4.RELEASE</version>
  	</dependency>
  	<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.0.0.RELEASE</version>
    </dependency>
    <dependency>
	  <groupId>net.sourceforge.argparse4j</groupId>
	  <artifactId>argparse4j</artifactId>
	  <version>0.4.1</version>
	</dependency>
	<dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports</artifactId>
        <version>5.2.0</version>
    </dependency>
            
  </dependencies>
  <build>
	<plugins>
		<plugin>
		<groupId>org.codehaus.mojo</groupId>
		<artifactId>exec-maven-plugin</artifactId>
		<version>1.2.1</version>
		<executions>
			<execution>
			<goals>
			  <goal>exec</goal>
			</goals>
			</execution>
		</executions>
		<configuration>
			<executable>maven</executable>
		</configuration>
		</plugin>
	</plugins>
  </build>
</project>
As you can see, the pom.xml file uses the following:
  • Spring Framework and its context library which can be used to load bean configuration files
  • Jasper Reports
  • argparse4j to parse the command line arguments
  • exec-maven-plugin is a plugin to load maven enabled projects using a predefined main Java class (public static void main())
The main Java class is MainReporter.java which can be called from the command line:
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;

import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;


public class MainReporter {

	/**
	 * @param args
	 */
	
	static Reporter reporter;
	
	public static void main(String[] args) {
		MainReporter mainReporter= new MainReporter();
		mainReporter.process(args);
		
	}

	private void process(String[] args) {
		ArgumentParser parser = ArgumentParsers.newArgumentParser("MainReporter")
                        .defaultHelp(true)
                        .description("you can add your own arguments");
		 parser.addArgument("-c", "--config")
                        .help("The bean config's file name");
        
		Namespace ns = null;
		try {
                         ns = parser.parseArgs(args);
		} catch (ArgumentParserException e) {
                         parser.handleError(e);
                         System.exit(1);
		}
		GenericApplicationContext context= new GenericApplicationContext();
		XmlBeanDefinitionReader reader= new XmlBeanDefinitionReader(context);
		reader.loadBeanDefinitions(new ClassPathResource (ns.getString("config")));
		context.refresh();
		reporter= (Reporter) context.getBean("reporter");
		reporter.generate(ns);
	}

}

The MainReporter.java reads the argument config from the command line and then loads a Spring bean configuration file with the same name. Below is a sample of the config file. You can have as many configuration files as you want and you can load them one by one using the config argument from the command line.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="reporter" class="your.package.FirstBean" />
</beans>

You can save the file as FirstBean.xml and create other files for SecondBean, so on and so forth. Below is a sample of command line arguments:
1) mvn exec:java -Dexec.mainClass="com.yourpackage.MainReporter" -Dexec.args="-c 'FirstBean.xml'"
2) mvn exec:java -Dexec.mainClass="com.yourpackage.MainReporter" -Dexec.args="-c 'SecondBean.xml'"
Depending on the Bean Configuration file being called, a corresponding reporter variable is created in MainReporter class. Take a look at this line in the Java class:
reporter= (Reporter) context.getBean("reporter");
Following is the Interface file:
import net.sourceforge.argparse4j.inf.Namespace;

public interface Reporter {
	
	void generate(Namespace ns);
}

And below is how you can write code in FirstBean.java:
import java.io.*;
import java.util.HashMap;

import org.springframework.core.io.ClassPathResource;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRCsvDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sourceforge.argparse4j.inf.Namespace;

public class StocktakeReporter implements Reporter {

	public void generate(Namespace ns) {
		String csvFilePath= "/path/to/a/csv/file.csv";
		JRCsvDataSource ds;
		try {
		    ds = new JRCsvDataSource(JRLoader.getLocationInputStream(csvFilePath));
		    ds.setRecordDelimiter("\r\n");
		    ds.setUseFirstRowAsHeader(true);
		    ClassPathResource jasperXML= new ClassPathResource("FirstBeanTemplate.jrxml");
		    JasperReport report= JasperCompileManager.compileReport(jasperXML.getInputStream());
		    JasperPrint jasperPrint = JasperFillManager.fillReport(report,new HashMap(),ds);
		    String pdfFile= "/path/to/the/new/pdf/file.pdf";
		    JasperExportManager.exportReportToPdfFile(jasperPrint,pdfFile);
		} catch (JRException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}


}

What the code above does is that it reads data from a csv file and then fills the data into a pre-created template file FirstBeanTemplate.jrxml. Now in order to create the template file, you can use iReport. It is an open source standalone graphical program that provides report designer capabilities. A standard report template includes the following elements:
  • Title: For the whole report
  • Page Header: specific to each page
  • Column Header: will be repeated on all pages
  • Detail: what will be displayed on the report. In this example, it is the data of each row of the csv file
  • Column Footer: will be repeated on all pages
  • Page Footer: specific to each page
  • Last Page Footer
  • Summary
  • Background
In the Report Inspector window of iReport, you will find Fields section. Right click and then create new fields using the columns' names in your csv file. Jasper will match the data in the csv file with those fields using the columns' names.

 
comments powered by Disqus