July 25, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Doing Dynamic Reporting through JasperReport

  • July 7, 2014
  • By Manoj Debnath
  • Send Email »
  • More Articles »

While getting started with JasperReport, we have seen that we need to create a report template in XML (JRXML) format. We can either hand code the XML and compile to generate <reportname>.jrxml or use tools such as iReport(*), or JasperStudio to do the designing and compiling part. Though these are great tools and an excellent way to create a report in Java, yet, one thing always intrigues; is it always necessary to go through these cumbersome XML when we want to create a simple report from our Java application or use such tools? Isn't there a way where we can write simple Java code to generate a report and forget about XML? If these questions come to your mind too then please read on, we have a good news!

Note: (*) iReport will be soon off the support grid from Jaspersoft Community and JasperStudio will replace it as the official report designer as of version 5.5.0.

Dynamic Reporting

By dynamic report we mean creating a report on the fly from Java code, no XML coding, no compiling report template to JRXML, etc., explicitly working only with pure POJO. JasperReport being a pure Java library has the ability to do that. It is possible, though not a very elegant way of programming, to use only its native APIs, thanks to several third party libraries, which can be integrated conveniently with Jasper to solve our problem. One such third party library is Dynamic Jasper. Here we shall see a sample application integrating both JasperReport and DynamicJasper library to create a dynamic report from a Java application.

What You Need to Do

Download the following software and libraries.

1.      Java SDK (version 8)

2.      NetBeans (version 8.0)

3.      JasperReport Library (Version 5.6.0)

4.    DynamicJasper Library (Version 5.0.0)

That's it! Installing Java SDK and NetBeans is pretty straightforward. To create a reusable user library of JasperReport in Netbeans refer to Getting Started with JasperReport. Dynamic Jasper library can also be set up in Netbeans in a similar manner. Once this is done we are ready to roll.

Note: Once DynamicJasper zip is extracted, it contains a DynamicJasper 5.x.jar. This jar needs to be included into the library along with the JasperReport library.

What's Next

Simple, create a Java Project in Netbeans and include both JasperReport and DynamicJasper Library into the project. Right click on <ProjectName>PropertiesLibraries → Select the Compile tab (if not already selected) → Add Library... button and Import... required libraries.

Importing libraries from available libraries in Netbeans
Figure 1: Importing libraries from available libraries in Netbeans

Sample Project

In our project we shall create a report of the Collection of employees supplied to JasperReport API as a data source. So, Employee class is a simple Java bean, which can act as a data transfer object when working with a database. Since we are not using any database here, the list of employee data comes from the collection object we have created in main (Listing 4). While creating a report dynamically, our main concern is the designing of the report. In this project the whole designing part is handled by the EmployeeReport class.

Structure of the sample project from Netbeans Projects pane
Figure 2: Structure of the sample project from Netbeans Projects pane

Listing 1: log4j.properties

These properties if not set will give a compile time warning. Setting up the following properties is sufficient for this project. For further information refer to Apache log4j manual.

log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p %c:%L - %m%n

Listing 2: Employee.java

A simple java bean, POJO acting as a data transfer object in our project.

public class Employee {
    private int empNo;
    private String name;    
    private int salary;
    private float commission;
 
    public Employee() {
    }
 
    public Employee(int empNo, String name, int salary, float commission) {
        this.empNo = empNo;
        this.name = name;        
        this.salary = salary;
        this.commission = salary*commission;
    }
 
   //...getters and setters
    
}

Listing 3: EmployeeReport.java

This class is the heart of our project. All the designing part of the report is implemented here. Observe that Style object is extensively used to design different parts of the report to modify the look and feel (such as font family used, size, text color its background, etc.) DynamicJasper library provides many factory builder classes such as ColumnBuilder, ReportBuilder etc. to make the report designing through code convenient and easy. The designing code of the report given below is simple, straightforward and self-explanatory but not too refined to keep its simplicity.

//...import statements
 
public class EmployeeReport {
 
    private final Collection<Employee> list = new ArrayList<>();
 
    public EmployeeReport(Collection<Employee> c) {
        list.addAll(c);
    }
 
    public JasperPrint getReport() throws ColumnBuilderException, JRException, ClassNotFoundException {
        Style headerStyle = createHeaderStyle();
        Style detailTextStyle = createDetailTextStyle();        
        Style detailNumberStyle = createDetailNumberStyle();        
        DynamicReport dynaReport = getReport(headerStyle, detailTextStyle,detailNumberStyle);
        JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dynaReport, new ClassicLayoutManager(), new JRBeanCollectionDataSource(list));
        return jp;
    }
    
    private Style createHeaderStyle() {        
        StyleBuilder sb=new StyleBuilder(true);
        sb.setFont(Font.VERDANA_MEDIUM_BOLD);
        sb.setBorder(Border.THIN());
        sb.setBorderBottom(Border.PEN_2_POINT());
        sb.setBorderColor(Color.BLACK);
        sb.setBackgroundColor(Color.ORANGE);
        sb.setTextColor(Color.BLACK);
        sb.setHorizontalAlign(HorizontalAlign.CENTER);
        sb.setVerticalAlign(VerticalAlign.MIDDLE);
        sb.setTransparency(Transparency.OPAQUE);        
        return sb.build();
    }
    
    private Style createDetailTextStyle(){
        StyleBuilder sb=new StyleBuilder(true);
        sb.setFont(Font.VERDANA_MEDIUM);
        sb.setBorder(Border.DOTTED());        
        sb.setBorderColor(Color.BLACK);        
        sb.setTextColor(Color.BLACK);
        sb.setHorizontalAlign(HorizontalAlign.LEFT);
        sb.setVerticalAlign(VerticalAlign.MIDDLE);
        sb.setPaddingLeft(5);        
        return sb.build();
    }
    
      private Style createDetailNumberStyle(){
        StyleBuilder sb=new StyleBuilder(true);
        sb.setFont(Font.VERDANA_MEDIUM);
        sb.setBorder(Border.DOTTED());        
        sb.setBorderColor(Color.BLACK);        
        sb.setTextColor(Color.BLACK);
        sb.setHorizontalAlign(HorizontalAlign.RIGHT);
        sb.setVerticalAlign(VerticalAlign.MIDDLE);
        sb.setPaddingRight(5);        
        return sb.build();
    }
    
    
 
    private AbstractColumn createColumn(String property, Class type,
            String title, int width, Style headerStyle, Style detailStyle)
            throws ColumnBuilderException {
        AbstractColumn columnState = ColumnBuilder.getNew()
                .setColumnProperty(property, type.getName()).setTitle(
                        title).setWidth(Integer.valueOf(width))
                .setStyle(detailStyle).setHeaderStyle(headerStyle).build();
        return columnState;
    }
 
    private DynamicReport getReport(Style headerStyle, Style detailTextStyle, Style detailNumStyle) throws ColumnBuilderException, ClassNotFoundException {
        
        DynamicReportBuilder report=new DynamicReportBuilder();
        
        AbstractColumn columnEmpNo = createColumn("empNo", Integer.class,"Employee Number", 30, headerStyle, detailTextStyle);
        AbstractColumn columnName = createColumn("name", String.class,"Name", 30, headerStyle, detailTextStyle);        
        AbstractColumn columnSalary = createColumn("salary", Integer.class,"Salary", 30, headerStyle, detailNumStyle);
        AbstractColumn columnCommission = createColumn("commission", Float.class,"Commission", 30, headerStyle, detailNumStyle);
        report.addColumn(columnEmpNo)
                .addColumn(columnName).addColumn(columnSalary).addColumn(columnCommission);
                
        StyleBuilder titleStyle=new StyleBuilder(true);
        titleStyle.setHorizontalAlign(HorizontalAlign.CENTER);
        titleStyle.setFont(new Font(20, Font._FONT_GEORGIA, true));
        
        StyleBuilder subTitleStyle=new StyleBuilder(true);
        subTitleStyle.setHorizontalAlign(HorizontalAlign.CENTER);
        subTitleStyle.setFont(new Font(Font.MEDIUM, Font._FONT_GEORGIA, true));
        
        
        
        report.setTitle("Employee Report");
        report.setTitleStyle(titleStyle.build());
        report.setSubtitle("Commission received by Employee");
        report.setSubtitleStyle(subTitleStyle.build());
        report.setUseFullPageWidth(true); 
        return report.build();
    }    
}

Listing 4: DynamicReportApp.java

This class feeds the report with a Collection of Java bean objects, which can be otherwise a Collection of database records if we had fetched records form a back end database. The getReport() function of the EmployeeReport object returns a JasperPrint object. With this, report creation is complete. Now, to view the report we use JasperViewer object of the JasperReport library. That's it!

//...import statements
 
public class DynaReportApp {
 
    public static void main(String[] args) {
 
        Collection<Employee> list = new ArrayList<>();
 
        list.add(new Employee(101, "Ravinder Shah",  67000, (float) 2.5));
        list.add(new Employee(102, "John Smith",  921436, (float) 9.5));
        list.add(new Employee(103, "Kenneth Johnson",  73545, (float) 1.5));
        list.add(new Employee(104, "John Travolta",  43988, (float) 0.5));
        list.add(new Employee(105, "Peter Parker",  93877, (float) 3.5));
        list.add(new Employee(106, "Leonhard Euler",  72000, (float) 2.3));
        list.add(new Employee(107, "William Shakespeare",  33000, (float) 1.4));
        list.add(new Employee(108, "Arup Bindal",  92000, (float) 6.2));
        list.add(new Employee(109, "Arin Kohfman",  55000, (float) 8.5));
        list.add(new Employee(110, "Albert Einstein",  89000, (float) 8.2));
        
        EmployeeReport report = new EmployeeReport(list);
 
        try {
            JasperPrint jp = report.getReport();
            JasperViewer jasperViewer = new JasperViewer(jp);
            jasperViewer.setVisible(true);
 
        } catch (JRException | ColumnBuilderException | ClassNotFoundException ex) {
 
        }
    }
}

Last but not Least

That's all folks, now compile and run.

Report output displayed in JasperView
Figure 3: Report output displayed in JasperView

Conclusion

JasperReport library provided what Java programmers needed and DynamicJasper library complemented it by giving Java programmers what they always wanted. It is not that they do not have their glitches but what this duo JasperReport API and its sidekick DynamicJasper API provides is simply great to program with. Based on experience, I can say start coding now, see for yourself how simple and easy it is. Also do not forget to post your thoughts in the comments below.


Tags: Java, reporting, reporting and predictive tools




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel