JasperReports multiple data sources
last modified February 12, 2024
JasperReporte data sources in a s multiple data sources tutorial shows how use multiplreport generated with JasperReports library.
JasperReports is an open-source reporting library. It can create reports in various formats including PDF, HTML, XLS, or CSV. JasperReports creates page-oriented, ready-to-print documents.
JasperReports multiple data sources example
The following application displays data from two different data sources in a report.
pom.xml src └── main ├── java │ └── com │ └── zetcode │ ├── model │ │ ├── Car.java │ │ └── Country.java │ └── main │ ├── CommandLineRunner.java │ └── JasperMultipleDataSources.java └── resources └── report2.xml
This is the project structure.
<?xml version="1.0" encoding="UTF-8"?> <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.zetcode</groupId> <artifactId>multipledatasets</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <exec.mainClass>com.zetcode.main.CommandLineRunner</exec.mainClass> </properties> <dependencies> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>6.9.0</version> </dependency> </dependencies> </project>
The Maven pom.xml
file contains the
jasperreports
dependency.
package com.zetcode.model; public class Car { private Long id; private String name; private int price; public Car() {} public Car(Long id, String name, int price) { this.id = id; this.name = name; this.price = price; } 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 int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { return "Car{" + "id=" + id + ", name=" + name + ", price=" + price + '}'; } }
This is a Car
bean class. It contains car id, name, and price
attributes.
package com.zetcode.model; public class Country { private Long id; private String name; private int population; public Country(Long id, String name, int population) { this.id = id; this.name = name; this.population = population; } 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 int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } }
This is a Country
bean class. It contains country id, name, and
population attributes.
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd"> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="freport" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20"> <style name="field" fontSize="11" /> <style name="textRight" style="field" hAlign="Right" /> <subDataset name="dataset1"> <field name="id" class="java.lang.Long"/> <field name="name" class="java.lang.String"/> <field name="price" class="java.lang.Integer"/> </subDataset> <subDataset name="dataset2"> <field name="id" class="java.lang.Long"/> <field name="name" class="java.lang.String"/> <field name="population" class="java.lang.Integer"/> </subDataset> <parameter name="datasource1" class="java.util.List"/> <parameter name="datasource2" class="java.util.List"/> <detail> <band height="15"> <componentElement> <reportElement x="0" y="0" width="100" height="15"/> <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"> <datasetRun subDataset="dataset2"> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{datasource2})]]></dataSourceExpression> </datasetRun> <jr:listContents height="15" width="220"> <textField> <reportElement x="0" y="0" width="20" height="15" style="field" /> <textElement /> <textFieldExpression class="java.lang.Long"><![CDATA[$F{id}]]></textFieldExpression> </textField> <textField> <reportElement x="50" y="0" width="80" height="15" style="field" /> <textElement /> <textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression> </textField> <textField> <reportElement x="130" y="0" width="80" height="15" style="textRight" /> <textElement /> <textFieldExpression class="java.lang.Integer"><![CDATA[$F{population}]]></textFieldExpression> </textField> </jr:listContents> </jr:list> </componentElement> <componentElement> <reportElement x="250" y="0" width="100" height="15"/> <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd"> <datasetRun subDataset="dataset1"> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{datasource1})]]></dataSourceExpression> </datasetRun> <jr:listContents height="15" width="220"> <textField> <reportElement x="0" y="0" width="20" height="15" style="field" /> <textElement /> <textFieldExpression class="java.lang.Long"><![CDATA[$F{id}]]></textFieldExpression> </textField> <textField> <reportElement x="50" y="0" width="80" height="15" style="field" /> <textElement /> <textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression> </textField> <textField> <reportElement x="130" y="0" width="80" height="15" style="textRight" /> <textElement /> <textFieldExpression class="java.lang.Integer"><![CDATA[$F{price}]]></textFieldExpression> </textField> </jr:listContents> </jr:list> </componentElement> </band> </detail> </jasperReport>
This is the report template file. The report contains two list components. The list components load data from the list parameters passed to the report.
<subDataset name="dataset1"> <field name="id" class="java.lang.Long"/> <field name="name" class="java.lang.String"/> <field name="price" class="java.lang.Integer"/> </subDataset> <subDataset name="dataset2"> <field name="id" class="java.lang.Long"/> <field name="name" class="java.lang.String"/> <field name="population" class="java.lang.Integer"/> </subDataset>
We have two subdatasets; each of them has three fields. The fields are mapped to the attributes of the Java beans.
<parameter name="datasource1" class="java.util.List"/> <parameter name="datasource2" class="java.util.List"/>
The report accepts two java.util.List
parameters.
<componentElement> <reportElement x="0" y="0" width="100" height="15"/> <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" ...
There are two jr:list
components in the report. Each subDataset
is added to one list component.
<datasetRun subDataset="dataset2"> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{datasource2})]]></dataSourceExpression> </datasetRun>
The subDataset
is executed in the datasetRun
tag. The
list parameter is passed to the JRBeanCollectionDataSource
. We
refer to the parameter with the $P{}
syntax.
<jr:listContents height="15" width="220"> <textField> <reportElement x="0" y="0" width="20" height="15" style="field" /> <textElement /> <textFieldExpression class="java.lang.Long"><![CDATA[$F{id}]]></textFieldExpression> </textField> ...
The fields are passed to the textField
components, which are added to the
jr:listContents
tag. The field data is shown with the $F{}
syntax.
package com.zetcode.main; import com.zetcode.model.Car; import com.zetcode.model.Country; import net.sf.jasperreports.engine.JREmptyDataSource; 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 java.util.ArrayList; import java.util.HashMap; public class JasperMultipleDataSources { public void start() throws JRException { var xmlFile = "src/main/resources/report2.xml"; var jasperReport = JasperCompileManager.compileReport(xmlFile); var cars = new ArrayList<>(); cars.add(new Car(1L, "Audi", 52642)); cars.add(new Car(2L, "Mercedes", 57127)); cars.add(new Car(3L, "Skoda", 9000)); cars.add(new Car(4L, "Volvo", 29000)); cars.add(new Car(5L, "Bentley", 350000)); cars.add(new Car(6L, "Citroen", 21000)); cars.add(new Car(7L, "Hummer", 41400)); cars.add(new Car(8L, "Volkswagen", 21600)); var countries = new ArrayList<Country>(); countries.add(new Country(1L, "China", 1382050000)); countries.add(new Country(2L, "India", 1313210000)); countries.add(new Country(3L, "USA", 324666000)); countries.add(new Country(4L, "Indonesia", 260581000)); countries.add(new Country(5L, "Brazil", 207221000)); countries.add(new Country(6L, "Pakistan", 196626000)); countries.add(new Country(7L, "Nigeria", 186988000)); countries.add(new Country(8L, "Bangladesh", 162099000)); var params = new HashMap<String, Object>(); params.put("datasource1", cars); params.put("datasource2", countries); var jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource()); JasperExportManager.exportReportToPdfFile(jasperPrint, "src/main/resources/report2.pdf"); } }
The JasperMultipleDataSources
creates a JasperPrint
file from
the data sources and the report2.xml
template. JasperPrint
represents a page-oriented document that can be viewed, printed, or exported to other formats.
var xmlFile = "src/main/resources/report2.xml"; var jasperReport = JasperCompileManager.compileReport(xmlFile);
We compile the XML template file into a JasperReport
.
JasperReport
is a compiled template ready to be filled
with data.
var cars = new ArrayList<>(); cars.add(new Car(1L, "Audi", 52642)); cars.add(new Car(2L, "Mercedes", 57127)); cars.add(new Car(3L, "Skoda", 9000)); ...
This is a list of car objects.
var countries = new ArrayList<Country>(); countries.add(new Country(1L, "China", 1382050000)); countries.add(new Country(2L, "India", 1313210000)); countries.add(new Country(3L, "USA", 324666000)); ...
This is a list of country objects.
var params = new HashMap<String, Object>(); params.put("datasource1", cars); params.put("datasource2", countries);
The two lists are added to the params
map.
var jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource());
A JasperPrint
object is created; an object that can be
viewed, printed, or exported to other formats. The params
map
is passed to the JasperFillManager.fillReport()
method.
The main data source of the report has an empty data source.
JasperExportManager.exportReportToPdfFile(jprint, "src/main/resources/report2.pdf");
The JasperExportManager.exportReportToPdfFile()
method
exports the JasperPrint
into a PDF file.
package com.zetcode.main; public class CommandLineRunner { public static void main(String[] args) throws Exception { var app = new JasperMultipleDataSources(); app.start(); } }
The CommandLineRunner
sets up the application.
$ mvn compile $ mvn exec:java
We compile and run the application.
In this article we have generated a PDF file report data from two different data sources.