JasperReports for Java Developers
上QQ阅读APP看书,第一时间看更新

Chapter 3. Creating Your First Report

In this chapter, you will create, compile, and preview your first report. At the end of this chapter, you will be able to:

  • Create a simple JRXML report template
  • Generate Jasper binary report templates by compiling JRXML files
  • Preview report templates by using JasperReports custom ANT targets
  • Write code that will generate a report from a JasperReport template
  • View generated reports in JasperReports' native format using the tools provided by JasperReports
  • Generate reports that can be viewed in a web browser
  • Identify the JRXML elements corresponding to the different report sections

Creating a JRXML Report Template

The first step when creating a report is to create a JRXML template. As mentioned in Chapter 1, JasperReports JRXML templates are standard XML files. However, by convention, they have an extension of .jrxml, and are referred to as JRXML files or JRXML templates. All JRXML files contain a<jasperReport> root element that can contain many sub-elements. All of these sub-elements are optional. Since our goal for this chapter is to get a feel of how to design a report, we will obviate most of the<jasperReport> sub-elements. We will use only one sub-element, namely the<detail> sub-element.

Our first report will display a static String. Its JRXML follows:

<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="FirstReport">
<detail>
<band height="20">
<staticText> <reportElement x="20" y="0" width="200" height="20"/> <text><! [CDATA[If you don't see this, it didn't work]]></text> </staticText>
</band>
</detail>
</jasperReport>

There are some elements in this JRXML file that we haven't seen before:

  • <staticText> defines static text that does not depend on any datasources, variables, parameters, or report expressions.
  • <reportElement> defines the position and width of the<staticText> element.
  • <text> defines the actual static text that is displayed on the report.

We have seen the<band> element in previous examples. The<detail> element can contain only a single<band> element as its only sub-element. The<band> element can contain many different elements that can be used to display text, charts, images, or geometric figures. In this example, it contains a single<staticText> element.

Note

<reportElement> is a required element not only of the<staticText> element, but also of all sub-elements of the<band> element. The x and y coordinates defined in<reportElement> are relative to the<band> element, which contains its parent element (<staticText> in this example).

Previewing the XML Report Template

JasperReports includes a utility that can be used to preview report designs. This utility makes designing reports much faster, since we can immediately preview a report design without having to compile or fill it.

The utility is a standalone Java application included in the JasperReports JAR file. The class that needs to be executed is net.sf.jasperreports.view.JasperDesignViewer. The easiest way to execute this class is to use an ANT target, including all the required libraries in the CLASSPATH. This is the approach that is used in the JasperReports samples, included in the project ZIP file, and by us as well. The following ANT build file will launch the JasperDesignViewer to preview our report:

<project name="FirstReport XML Design Preview" default="viewDesignXML" basedir=".">
<description>Previews our First Report XML Design</description>
<property name="file.name" value="FirstReport"/>
<!-- Directory where the JasperReports project file was extracted
needs to be changed to match the local environment -->
<property name="jasper.dir" value="/usr/local/share/java/jasperreports-1.1.0"/>
<property name="classes.dir" value="${jasper.dir}/build/classes"/>
<property name="lib.dir" value="${jasper.dir}/lib"/>
<path id="classpath">
<pathelement location="./"/>
<pathelement location="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<target name="viewDesignXML" description="Launches the design viewer to preview the XML report design."> <java classname="net.sf.jasperreports.view.JasperDesignViewer" fork="true"> <arg value="-XML"/> <arg value="-F${file.name}.jrxml"/> <classpath refid="classpath"/> </java> </target>
</project>

This ANT build file must be saved in the same directory as our JRXML file. It is recommended that the JRXML file be saved with the report name as its file name. The report name is defined in the<jasperReport> root element. In the JRXML file, we chose to use FirstReport as the report name. Therefore, the recommended file name for this report template is FirstReport.jrxml.

If we save our ANT build file with the standard name of build.xml, there is no need to specify the build file name in the command line. The build file, in this example, has one<target> element named viewDesignXML. Since this target is the default target, there is no need to specify it in the command line; just typing ant in the command line will execute the default target and a preview of our report will be displayed.

$ ant Buildfile: previewReportDesignXML.xml viewDesignXML:

After executing the viewDesignXML target, we should see a window labeled JasperDesignViewer displaying our report template preview.

Previewing the XML Report Template

The JasperDesignViewer can be safely terminated by closing the window or by hitting Ctrl-c in the command-line window.

In this particular case we can see all the text in the preview, since this report contains only static text. For reports displaying data coming from datasources or report parameters, the actual text won't be displayed in the report. Instead, report expressions for obtaining the data are displayed. This is because JasperDesignViewer does not have access to the actual datasource or report parameters.

Creating a Binary Report Template

JRXML files cannot be used directly to generate reports. They need to be compiled into JasperReports' native binary format. Compiled report templates are called Jasper files. There are two ways to compile a JRXML file into a Jasper file. We can either do it programmatically, or we can do it through a custom ANT task provided by JasperReports.

Compiling a JRXML Template Programmatically

A JRXML template can be compiled into a Jasper file and saved to disk by calling the compileReportToFile() method on the net.sf.jasperreports.engine.JasperCompileManager class. There are three overloaded versions of the JasperCompileManager.compileReportToFile() method, listed below:

  • JasperCompileManager.compileReportToFile(String sourceFileName).
  • JasperCompileManager.compileReportToFile(String sourceFileName, String destFileName).
  • JasperCompileManager.compileReportToFile(JasperDesign jasperDesign, String destFileName).

The following table illustrates the parameters used in these methods:

The following code fragment demonstrates the use of the JasperCompileManager.compileReportToFile() method:

package net.ensode.jasperbook;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
public class FirstReportCompile
{
public static void main(String[] args)
{
try
{
System.out.println("Compiling report...");
JasperCompileManager.compileReportToFile( "reports/FirstReport.jrxml");
System.out.println("Done!");
}
catch (JRException e)
{
e.printStackTrace();
}
}
}

After compiling and executing the code, we should see a file called FirstReport.jasper in the file system. This file is the compiled template in JasperReports' native format. For this example, we chose to use the first version of the JasperCompileManager.compileReportToFile() method we discussed, since by default the root file name is used for the compiled report, and we did not have an in-memory representation of the JRXML template. If we had wished to use a different root file name for the compiled report template, we should have used the second version of the JasperCompileManager.compileReportToFile() method and specified the desired file name as the second parameter.

Previewing the Compiled Report Template

The net.sf.jasperreports.view.JasperDesignViewer discussed previously can be used to preview compiled report templates as well as JRXML templates. Again the easiest way to execute this utility is to wrap a call to it into an ANT target. Let us add a second ANT target to our build.xml file. We will call this new target viewDesign, as it will let us preview the compiled report.

<project name="FirstReport XML Design Preview" default="viewDesignXML" basedir=".">
<description>Previews our First Report Design</description>
<property name="file.name" value="FirstReport"/>
<!-- Directory where the JasperReports project file was extracted,
needs to be changed to match the local environment -->
<property name="jasper.dir" value="/usr/local/share/java/jasperreports-1.1.0"/>
<property name="classes.dir" value="${jasper.dir}/build/classes"/>
<property name="lib.dir" value="${jasper.dir}/lib"/>
<path id="classpath">
<pathelement location="./"/>
<pathelement location="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<target name="viewDesignXML"
description="Launches the design viewer to preview the XML report design.">
<java classname="net.sf.jasperreports.view.JasperDesignViewer"
fork="true">
<arg value="-XML"/>
<arg value="-F${file.name}.jrxml"/>
<classpath refid="classpath"/>
</java>
</target>
<target name="viewDesign" description="Launches the design viewer to preview the compiled report design."> <java classname="net.sf.jasperreports.view.JasperDesignViewer" fork="true"> <arg value="-F${file.name}.jasper"/> <classpath refid="classpath"/> </java> </target>
</project>

We can invoke the new target from the command line as follows:

ant viewDesign

After invoking the target, we should see a window very similar to the one we saw when previewing the JRXML template.

Compiling a JRXML Template through ANT

JasperReports includes a custom ANT task that can be used to compile report templates. Since we don't have to write code to perform the compilation, compiling reports in this manner is very convenient. However, for certain applications we need to compile a report programmatically, for example, in situations where the JRXML file is created at run time. The custom ANT task included by JasperReports is called JRC. It is defined in the net.sf.jasperreports.ant.JRAntCompileTask class. Let us add a third target to our build.xml file to invoke the JRC task.

<project name="FirstReport XML Design Preview" default="viewDesignXML" basedir=".">
<description>Previews and compiles our First Report</description>
<property name="file.name" value="FirstReport"/>
<!-- Directory where the JasperReports project file was extracted,
needs to be changed to match the local environment -->
<property name="jasper.dir" value="/usr/local/share/java/jasperreports-1.1.0"/>
<property name="classes.dir" value="${jasper.dir}/build/classes"/>
<property name="lib.dir" value="${jasper.dir}/lib"/>
<path id="classpath">
<pathelement location="./"/>
<pathelement location="${classes.dir}"/>
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<target name="viewDesignXML"
description="Launches the design viewer to preview the XML report design.">
<java classname="net.sf.jasperreports.view.JasperDesignViewer" fork="true">
<arg value="-XML"/>
<arg value="-F${file.name}.jrxml"/>
<classpath refid="classpath"/>
</java>
</target>
<target name="viewDesign"
description="Launches the design viewer to preview the compiled report design.">
<java classname="net.sf.jasperreports.view.JasperDesignViewer" fork="true">
<arg value="-F${file.name}.jasper"/>
<classpath refid="classpath"/>
</java>
</target>
<target name="compile" description="Compiles the XML report design and produces the .jasper file."> <taskdef name="jrc" classname="net.sf.jasperreports.ant.JRAntCompileTask"> <classpath refid="classpath"/> </taskdef> <jrc destdir="."> <src> <fileset dir="."> <include name="**/*.jrxml"/> </fileset> </src> <classpath refid="classpath"/> </jrc> </target>
</project>

The new target can be invoked from the command line as:

ant compile

The compile target produces the following output:

Buildfile: build.xml compile: [jrc] Compiling 1 report design files. [jrc] log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax). [jrc] log4j:WARN Please initialize the log4j system properly. [jrc] File : /home/heffel/personal_workspace/JasperBookExamples/ reports/FirstReport.jrxml ... OK. BUILD SUCCESSFUL Total time: 4 seconds 

After successful execution of the compile target, we should have a FirstReport.jasper file in the file system. This file is identical to the one generated programmatically by calling the net.sf.jasperreports.engine.JasperCompileManager.compileReportToFile().

Note

As can be seen in the output above, the JRC target will generate a log4j warning. This warning can be safely ignored.

As explained in the previous section, we can preview the generated Jasper file by using the JasperDesign utility included by JasperReports. The output will be identical.