JavaData & JavaCreating a Graphical Report in JasperReport

Creating a Graphical Report in JasperReport

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

JasperReport is a powerful reporting tool that can be used to build rich report content in accordance with business application needs. This open source library provides the necessary APIs that go beyond mere textual reporting to graphics and charts that enhance information visualization and data analysis. With extensive file format support, reports can be delivered to any format such as PDF, HTML, XLS, CSV, XML, or directly to a printer. Developers get a wide variety of options at their disposal with considerable implementation ease. What sets JasperReport apart from many of its contemporary tools is that it opened a horizon for many third-party innovations. They can be seamlessly imbibed into the core reporting tool and orchestrated to suffice critical reporting needs. Here, we focus on creating a simple graphical report with the help of a few third-party libraries.

What We Need

Everything is not that pink and rosy when you get down to implementation, but the outcome is definitely awesome. The reason is, that like many others, JasperReport also asks for quite a number of third-party libraries and they are not bundled when you download the JasperReport library. Hunting these dependency files can really be a pain in the neck. Of course you can go for maven repositories, but let’s get completely dirty here; we’ll hunt them down. Here is what I found out as a list of what we need, at least when creating the following application.

  • Commons-beanutils-1.8.2.jar: Conforms to the Java beans naming pattern.
  • Commons-collections-3.2.jar: Provides a bundle of data structure; with its many uses, has become a standard form handling collection in Java.
  • Commons-digester-2.1.jar: This component provides a common implementation for reading XML configuration files, used for initializing Java objects.
  • Commons-logging-1.2.jar: Logging components that help in logging information at runtime.
  • DynamicJasper-5.0.3.jar: Provides APIs that hide several complexities of of JasperReport and helps in creating a report dynamically.
  • Jasperreports-6.1.0.jar: The core library of the reporting tool.
  • Jcommon-1.0.23.jar: Provides miscellaneous class support to JFreeChart, often bundled together.
  • Jfreechart-1.0.19.jar: Java chart library that helps in creating charts in a report.

And of course:

A word of caution though: Be careful when choosing the versions for jar libraries. Any version incompatibility in the dependency files may result in erratic behavior during compilation or runtime. The version numbers for the jar files given above work fine for the article. Consider consulting the appropriate documentation and manuals before adding extra libraries to the existing code. Another problem you may face while compiling the following code on a Linux platform. The compiler may report something like “font not found.” This occurs due to our using msttcore fonts in the report. So, you may either need to download and install msttcore fonts for the Linux platform or modify the code appropriately or switch to the Windows platform and run the example.

Car.java

This a model class used for a data transaction operation.

package org.mano.report;

public class Car {
   private int id;
   private String model;
   private String manufacturer;
   private int quantity;
   private String year;

   public Car() {
      super();
   }

   public Car(int id, String model,
         String manufacturer,
         int quantity, String year) {
      super();
      this.id = id;
      this.model = model;
      this.manufacturer = manufacturer;
      this.quantity = quantity;
      this.year = year;
   }

   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   public String getModel() {
      return model;
   }

   public void setModel(String model) {
      this.model = model;
   }

   public String getManufacturer() {
      return manufacturer;
   }

   public void setManufacturer(String manufacturer) {
      this.manufacturer = manufacturer;
   }

   public int getQuantity() {
      return quantity;
   }

   public void setQuantity(int quantity) {
      this.quantity = quantity;
   }

   public String getYear() {
      return year;
   }

   public void setYear(String year) {
      this.year = year;
   }
}

DummyDB.java

This class simulates a backend database with some dummy data and can be modified to use an actual database appropriately.

package org.mano.report;
import java.util.ArrayList;
import java.util.List;
public class DummyDB {
   public static List<Car> getListOfCars() {
      List<Car> list = new ArrayList<>();
      list.add(new Car(1, "X6 M", "BMW", 78, "2011"));
      list.add(new Car(2, "340i", "BMW", 32, "2011"));
      list.add(new Car(3, "Veyron 16.4 GS Vi", "BMW", 25, "2014"));
      list.add(new Car(4, "SRX 3.0", "Cadillac", 14, "2015"));
      list.add(new Car(5, "CTS-V Coupe", "Cadillac", 10, "2009"));
      list.add(new Car(6, "Escalate Hybrid", "Cadillac", 5, "2012"));
      list.add(new Car(7, "Stingray", "Corvette", 31, "2015"));
      list.add(new Car(8, "Camaro Z/28", "Corvette", 78, "2012"));
      list.add(new Car(9, "Z06 Coupe", "Corvette", 69, "2013"));
      list.add(new Car(10, "488 GTB", "Ferrari", 1, "2013"));
      list.add(new Car(11, "458 Spec Aperta", "Ferrari", 56,"2010"));
      list.add(new Car(12, "Aventadore SV", "Lamborghini", 7, "2011"));
      list.add(new Car(13, "H LP610-4", "Lamborghini", 9,"2011"));
      return list;
   }
}

ReportBase.java

This is the base class for reporting needs in an application. The class can be further modified to put together all common needs of inheriting concrete classes.

package org.mano.report;

import java.awt.Color;

import ar.com.fdvs.dj.domain.Style;
import ar.com.fdvs.dj.domain.builders.ColumnBuilder;
import ar.com.fdvs.dj.domain.constants.Border;
import ar.com.fdvs.dj.domain.constants.Font;
import ar.com.fdvs.dj.domain.constants.HorizontalAlign;
import ar.com.fdvs.dj.domain.constants.Transparency;
import ar.com.fdvs.dj.domain.constants.VerticalAlign;
import ar.com.fdvs.dj.domain.entities.columns.AbstractColumn;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public abstract class ReportBase {

   protected AbstractColumn modelCol;
   protected AbstractColumn mfgCol;
   protected AbstractColumn qtyCol;
   protected AbstractColumn yearCol;

   public ReportBase() {
      modelCol = ColumnBuilder.getNew()
      .setColumnProperty("model", String.class.getName())
      .setTitle("Model").setWidth(70).build();
      mfgCol = ColumnBuilder.getNew()
      .setColumnProperty("manufacturer", String.class.getName())
      .setTitle("Manufacturer").setWidth(70).build();
      qtyCol = ColumnBuilder.getNew()
      .setColumnProperty("quantity", Integer.class.getName())
      .setTitle("Quantity").setWidth(70).build();
      yearCol = ColumnBuilder.getNew()
      .setColumnProperty("year", String.class.getName())
      .setTitle("Year").setWidth(70).build();
   }

   public Style getHeaderStyle() {
      Style headerStyle = new Style();
      headerStyle.setFont(Font.VERDANA_MEDIUM_BOLD);
      headerStyle.setBorderBottom(Border.PEN_2_POINT());
      headerStyle.setHorizontalAlign(HorizontalAlign.CENTER);
      headerStyle.setVerticalAlign(VerticalAlign.MIDDLE);
      headerStyle.setBackgroundColor(Color.DARK_GRAY);
      headerStyle.setTextColor(Color.WHITE);
      headerStyle.setTransparency(Transparency.OPAQUE);
      return headerStyle;
   }

   protected JRDataSource getDataSource() {
      JRDataSource dataSource = new JRBeanCollectionDataSource(
      DummyDB.getListOfCars());
      return dataSource;

   }

}

Report.java

This is the concrete implementation of the report design class. This class creates two charts (pie and bar chart) with the dummy data supplied. The code is self-explanatory; refer to the Java docs of the JasperReport library and the DynamicJasper library for more information on the APIs used.

package org.mano.report;

import java.awt.Color;

import ar.com.fdvs.dj.domain.DynamicReport;
import ar.com.fdvs.dj.domain.builders.DynamicReportBuilder;
import ar.com.fdvs.dj.domain.chart.DJChart;
import ar.com.fdvs.dj.domain.chart.DJChartOptions;
import ar.com.fdvs.dj.domain.chart.builder.DJBarChartBuilder;
import ar.com.fdvs.dj.domain.chart.builder.DJPieChartBuilder;
import ar.com.fdvs.dj.domain.chart.plot.DJAxisFormat;
import ar.com.fdvs.dj.domain.constants.Font;
import ar.com.fdvs.dj.domain.entities.columns.PropertyColumn;

public class Report extends ReportBase {

   private DynamicReportBuilder builder;

   public Report() throws Exception {
      builder = new DynamicReportBuilder();

      builder.addColumn(modelCol);
      builder.addColumn(mfgCol);
      builder.addColumn(qtyCol);
      builder.addColumn(yearCol);

      builder.setUseFullPageWidth(true);
      builder.setDefaultStyles(null, null, getHeaderStyle(), null);
   }

   private DJChart createBarChart() {

      DJAxisFormat categoryAxisFormat = new DJAxisFormat("category");
      categoryAxisFormat.setLabelFont(Font.ARIAL_SMALL);
      categoryAxisFormat.setLabelColor(Color.DARK_GRAY);
      categoryAxisFormat.setTickLabelFont(Font.ARIAL_SMALL);
      categoryAxisFormat.setTickLabelColor(Color.DARK_GRAY);
      categoryAxisFormat.setTickLabelMask("");
      categoryAxisFormat.setLineColor(Color.DARK_GRAY);

      DJAxisFormat valueAxisFormat = new DJAxisFormat("value");
      valueAxisFormat.setLabelFont(Font.ARIAL_SMALL);
      valueAxisFormat.setLabelColor(Color.DARK_GRAY);
      valueAxisFormat.setTickLabelFont(Font.ARIAL_SMALL);
      valueAxisFormat.setTickLabelColor(Color.DARK_GRAY);
      valueAxisFormat.setTickLabelMask("#,##0.0");
      valueAxisFormat.setLineColor(Color.DARK_GRAY);

      DJChart chart = new DJBarChartBuilder()
      .setX(20).setY(10).setWidth(500)
      .setHeight(250).setCentered(false)
      .setBackColor(Color.LIGHT_GRAY).setShowLegend(true)
      .setPosition(DJChartOptions.POSITION_FOOTER)
      .setTitle("Car Sales").setTitleColor(Color.DARK_GRAY)
      .setTitleFont(Font.ARIAL_BIG_BOLD)
      .setSubtitle("Models sold in year(s) 2009-2015")
      .setSubtitleColor(Color.DARK_GRAY)
      .setSubtitleFont(Font.GEORGIA_SMALL_BOLD)
      .setLegendColor(Color.DARK_GRAY)
      .setLegendFont(Font.ARIAL_SMALL_BOLD)
      .setLegendBackgroundColor(Color.WHITE)
      .setLegendPosition(DJChartOptions.EDGE_BOTTOM)
      .setTitlePosition(DJChartOptions.EDGE_TOP)
      .setLineStyle(DJChartOptions.LINE_STYLE_DOTTED)
      .setLineWidth(1)
      .setLineColor(Color.DARK_GRAY).setPadding(5)
      .setCategory((PropertyColumn) yearCol).addSerie(qtyCol)
      .setShowLabels(false).setCategoryAxisFormat(categoryAxisFormat)
      .setValueAxisFormat(valueAxisFormat).build();
      return chart;
   }

   private DJChart createPieChart() {
      DJChart chart = new DJPieChartBuilder()
      .setX(20).setY(10).setWidth(500)
      .setHeight(250).setCentered(false)
      .setBackColor(Color.LIGHT_GRAY).setShowLegend(true)
      .setPosition(DJChartOptions.POSITION_FOOTER)
      .setTitle("Car Sales").setTitleColor(Color.DARK_GRAY)
      .setTitleFont(Font.ARIAL_BIG_BOLD)
      .setSubtitle("Units sold in year(s) 2009-2015")
      .setSubtitleColor(Color.DARK_GRAY)
      .setSubtitleFont(Font.GEORGIA_SMALL_BOLD)
      .setLegendColor(Color.DARK_GRAY)
      .setLegendFont(Font.ARIAL_SMALL_BOLD)
      .setLegendBackgroundColor(Color.WHITE)
      .setLegendPosition(DJChartOptions.EDGE_BOTTOM)
      .setTitlePosition(DJChartOptions.EDGE_TOP)
      .setLineStyle(DJChartOptions.LINE_STYLE_DOTTED)
      .setLineWidth(1)
      .setLineColor(Color.DARK_GRAY).setPadding(5)
      .setKey((PropertyColumn) modelCol).addSerie(qtyCol)
      .setCircular(true).build();
      return chart;
   }

   public DynamicReport getPieReport() throws Exception {
      builder.addChart(createPieChart());
      return builder.build();
   }
   public DynamicReport getBarReport() throws Exception {
      builder.addChart(createBarChart());
      return builder.build();
   }
}

Main.java

The is the main class of the application and creates a two-page report with the same data, one as a pie chart and another with a bar chart.

package org.mano.report;

import java.util.List;

import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;
import ar.com.fdvs.dj.core.DynamicJasperHelper;
import ar.com.fdvs.dj.core.layout.ClassicLayoutManager;

public class Main {

   public static void main(String[] args) throws Exception {

      JasperPrint jp1 = DynamicJasperHelper.generateJasperPrint(
      new Report().getPieReport(), new ClassicLayoutManager()
      DummyDB.getListOfCars());
      JasperPrint jp2 = DynamicJasperHelper.generateJasperPrint(
      new Report().getBarReport(), new ClassicLayoutManager(),
      DummyDB.getListOfCars());

      List<JRPrintPage> pages = jp2.getPages();
      for (int j = 0; j < pages.size(); j++) {
         JRPrintPage object = (JRPrintPage) pages.get(j);
         jp1.addPage(object);

      }
      JasperViewer.viewReport(jp1, false);
   }
}

Output: Two-page Report, Page 1 of 2 and Page 2 of 2

Jasper1
Figure 1: Report, page 1

Jasper2
Figure 2: Report, page 2

Conclusion

The preceding example can easily be modified to use a backend database and fetch filtered data with appropriate queries. The design can be further modified according to the user’s taste and preferences. This rudimentary example demonstrates what the outcome can be with very little effort. Real examples can contain several lines of complex code to realize reporting needs. However, you can take from here and design an awesome report with your creative ingenuity.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories