Note that the current implementations rely on the Jakarta Commons BeanUtils library to
retrieve JavaBean property values, so check their documentation to see how you can use
nested JavaBean properties with report fields.
Let’s say that the current JavaBean object inside the data source is of type
contains nested supplier information accessible by calling the
which returns a
object. In this case, you could have a report field that maps to
the supplier’s address if it is called
Note that in the past, report fields did not accept dots, spaces, or other special characters
in their names. Therefore, to access nested JavaBean properties, the data source relied on
the field’s description, if present, to identify the property, because dots might appear
inside the field’s description. For backward-compatibility reasons, the current
implementations still look into the field’s description first, by default. If there is no
description, then the report field name is used for locating the JavaBean property. If this
default behavior is not desirable, especially if the field description is already used for
other purposes, you can use special data source constructors that receive a flag called
to suppress this behavior.
A special field mapping can be used to access the current JavaBean object itself. Thus,
when a field uses
as description or name, the data source will return the current
JavaBean object as field value. This is useful when the report needs to extract from the
current object some data that does not correspond to a property that follows JavaBeans
standards (for instance, the data is returned by a method that takes some arguments), or
when the current object needs to be passed to as argument to a method called in one of
the report expressions.
The JavaBeans data source implementation contain few methods that are useful in
method returns the underlying bean collection or array used by the
method returns the total number of beans contained in the
collection or array used by the data source.
method returns a copy of data source by creating a fresh
data source that uses the same underlying JavaBeans collection or array.
You can use the last method, for instance, when a master report contains a subreport that
needs to iterate on the same JavaBeans collection as the master. In this case, the
subreport would use the following data source expression:
JasperReports is shipped with two data source implementations that can wrap arrays or
wraps an array
can be used
to wrap a
These implementations are useful if the parent application already stores the reporting
data available in-memory as
object in the wrapped array or
collection is considered a virtual record in the data source, and the value of each report
field is extracted from the map using the report field name as the key.
Map-based data source implementations contain the same set of utility methods as
JavaBeans data sources (described in the previous section):
to access the underlying map collection or array
to return the total number of maps/records
to create a fresh copy of the data source
In some Swing-based desktop client applications, the reporting data might already be
available in the form of a
implementation used for
components on various forms. JasperReports can
generate reports using this kind of data if a given
object is wrapped in a
being passed as the data source for the report-filling process.
There are two ways to use this type of data source. Normally, to retrieve data from it,
you must declare a report field for each column in the
object bearing the same name as the column it
maps. Sometimes it is not possible or desirable to use the column name, however,
because the report field name and columns could still be bound to report fields using
their zero-based index instead of their names.
For instance, if you know that a particular column is the third column in the table model
), then you could name the corresponding field
and use the
column data without problems.
An example is provided in the
XML documents can be used as report data sources by means of a data source
implementation. JasperReports features a built-in XML data source implementation
) that is based on DOM
and uses XPath expressions to select data from the XML document.
An XML data source instantiation involves the following inputs:
An XML document. The parsed document, its location, or its source is provided as
an argument to the data source constructor.
An XPath expression to select the node set that corresponds to the data source
record list. The expression is passed to the data source as a constructor argument.
The default XPath expression selects the document node itself; in this case the data
source would produce a single record. The XPath expression is executed when the
data source is instantiated; each item in the resulting node set will generate a
record/row in the data source.
For every field in the report/data set, an XPath expression to select the field value
for each record. The field’s XPath expression is provided by the field description
element in JRXML). The field’s XPath expression is
executed for each record using as a context node the current node from the main
An XML data source can be used create sub–data sources to be used for subreports or
subdatasets. There are two methods of creating a sub–data source from a parent XML
A sub–data source can be created for a new document that uses the current node as
a root node. An XPath expression can additionally be specified to select the list of
nodes for the sub–data source. The
methods should be used to create
sub–data sources in this scenario.
The same document can be reused for a new sub–data source, which would specify
a different XPath expression for the main node set. This can be accomplished via
The built-in XML data source is a generic implementation that is very flexible due to the power of XPath
and hence convenient in many cases. However, especially when dealing with large XML documents, this
implementation might not perform optimally because DOM would require large amounts of heap space for the in-
memory document, and XPath expression evaluations would cause slower data processing speeds. In such
cases, custom data source implementations that use SAX or other stream parser mechanisms to process specific
XML documents would significantly increase the performance.
To illustrate the preceding concepts, consider the following XML document:
<Address>Obere Str. 57</Address>
<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
<Address>Avda. de la Constitución 2222</Address>
<Phone type="Fixed">(5) 555-4729</Phone>
To create a data source that iterates the
nodes, you could use the following:
new JRXmlDataSource(document, "/CompanyData/Customer")
Possible field mappings would be as follows:
: Map the
attribute of the current
: Map the value of the
child node of the current node.
Phone[@type = "Fixed"]
: Map the fixed phone number of the current customer.
: Absolute XPath expressions are also possible;
the field would yield the same value for each record.
To create a sub–data source that iterates on the
nodes under the current
node, the following expression could be used as a subreport data source:
To create a sub–data source that only includes the
node, you could use the
Jaxen as XPath interpreter
XML data sources work by interpreting XPath expressions and selecting nodes and
values from the XML document based on these expressions. This functionality related to
XPath processing has been extracted into a generic service interface called
The XPath executer implementation used by XML data sources can be configured via a
JasperReports property named
This property gives the name of a XPath executer factory class, which has to implement
JasperReports includes two built-in XPath executer implementations, one based on
Apache Xalan (
) and the second on Jaxen
). The Xalan-based implementation is used by default
for backward compatibility reasons.
In many cases, though, the Jaxen XPath executor provides better performance than an
executor that uses Xalan. To switch to the Jaxen XPath executer, one needs to set the
. property to
is usually done by including the following line in the
To switch back to Xalan, one would comment or remove the property line, or explicitly
set the property to
The XML data source provides localization support for both number and date/time
values rendered as text in the wrapped XML document.
In order to parse these text values into
according to the declared report field type in the report template, the program needs to
know which pattern and locale to use. For date/time report fields, if the text value inside
the XML representing time is rendered in a specific time zone, then this time zone needs
to be provided to the data source so that it is taken into account when parsing.
There are four setter methods in the
class for specifying:
Number pattern: To use for parsing all text values corresponding to report fields of
or any subclass of it
Date pattern: To use for parsing all date/time values corresponding to report fields
or any subclass of it
Locale: To use for getting localized number and date parsers
Time zone: To use for properly translating time values when they are not expressed
in GMT (
Patterns should be non-localized and in accordance with the
pattern syntax. If
specific patterns are not supplied, the defaults for these two format classes apply.
You can see how this data source implementation works by checking the
sample provided with the project source files.
Sometimes data that users need to fill the report with is found in plain text files, in a
certain format, such as the popular CSV (comma-separated value).
JasperReports provides an implementation for such a data source, by wrapping the CSV
data from a text file into a
The CSV data source usually needs to read a file from disk, or at least from an input
stream. Thus, the
can be initialized in three ways, depending on
where it gets the data:
An input stream:
The CSV format employs certain formatting rules. Data rows are separated by a record
delimiter (text sequence) and fields inside each row are separated by a field delimiter
(character). Fields containing delimiter characters can be placed inside quotes. If fields
contain quotes themselves, these are duplicated (for example,
The default values in JasperReports (and also the most common for CSV files) are a
comma for field delimiter and a newline (
) for record delimiter. Users can override
these default values by calling
. For example, on some systems, users may need to
replace the default
Since CSV does not specify column names, the default convention is to name report
and map each column with the field found at index
in each row (these
indices start with 0). To avoid this situation, users have two possible solutions:
method to force the program to read
the column name from the first line of the CSV file.
Providing an array of column names using the
Note that in both cases, the number of provided column names must be at least equal
with the number of actual fields in any record, otherwise an exception will be thrown.
Also, for any column name in the data source, an equivalent report field must exist.
Handling data types for fields in CSV data sources is special since the CSV file format
does not provide such information. This matter is solved by trying to match each field in
the data source to its corresponding report field type. For number and date/time fields,
converting text values to
requires parsing using format objects. This is controlled by specifying the date and
number format objects to be used with the
instance by calling its
before passing it to the report-filling process.
The CSV data source implementation also has a
useful for design tools creators. See the “Data Source Provider” section later in this
chapter for more details.
When reporting data is in Microsoft Excel files (XLS), the
implementation can be used to read it and feed it into the report.
The XLS data source uses the JExcelApi library to load the XLS workbook and read
from it. Instances of this data source can be created by supplying either an in-memory
workbook object, a file, or an input stream to read the data from
Report-field mapping for this data source implementation is very similar to the CSV data
source field-mapping explained in the previous section. It works on the assumption that
the workbook contains data in a tabular form (rows are records and columns contain
class is a very simple
data source implementation that simulates a data source with a given number of virtual
records inside. It is called “empty data source” because even though it has one or more
records inside, all the report fields are null for all the virtual records of the data source.
Such a simple data source implementation is used by the UI tools to offer basic report
preview functionality, or in special report templates, or for testing and debugging
is an extension of
interface, to which it adds
the possibility of moving the record pointer back before the first virtual record. It adds
only one method, called
to the interface.
Rewindable data sources are useful when working with subreports. If a subreport is
placed inside a band that is not allowed to split due to the
setting and there is not enough space on the current page for the subreport to be rendered,
then the engine has to give up rendering the current band, introduce a page break, and
restart the band and the subreport on the next page. But since the subreport has already
consumed some of the supplied data source records when trying to render the band on
the previous page, it needs to move the record pointer of the data source back before the
first data source for the subreport to restart properly.
All built-in data source implementations are rewindable except for the
, which does not support
moving the record pointer back. This is a problem only if this data source is used to
manually wrap a
before passing it to the subreport. It is not a
problem if the SQL query resides in the subreport template because the engine will re-
execute it when restarting the subreport on the next page.
To simplify integration with the GUI tools for creating and previewing report templates,
the JasperReports library has published an interface that allows those tools to create and
dispose of data source objects. This is the standard way to plug custom data sources into
a design tool.
This is very useful when the developer wants to preview the reports with the design tool
and use the actual data that the target application will supply at runtime. In order to
achieve this, simply create a custom implementation of the
interface and make it
available to the design tool to create the required data sources to use during report
The data source provider interface has only a few methods that allow creating and
disposing of data source objects and also methods for listing the available report fields
inside the data source if possible. Knowing which fields will be found in the created data
sources helps you to create report field wizards inside the design tools to simplify report
The library also comes with an abstract implementation of the
interface that can be used as the base class for creating data source provider
implementations that produce JavaBean-based data sources.
uses Java reflection to provide available report fields names for a given JavaBean class.
For more details about data source providers, check the Javadoc API documentation.
To fill a report, provide the reporting engine with the report data, or at least instruct it
how to get this data.
JasperReports normally expects to receive a
object as the report data source, but
it has also been enhanced to work with JDBC so that it can retrieve data from relational
databases if required.
The library allows the report template to specify the SQL query for report data if this
data is located in relational databases.
The SQL query specified in the report template is taken into account and executed only if
object is supplied instead of the normal
object when filling the report.
This query can be introduced in the JRXML report template using the
element. If present, this element comes after the report parameter declarations and before
the report fields. It’s complete syntax is given in Listing 8-2.
Listing 8-2. JRXML Syntax
<!ELEMENT queryString (#PCDATA)>
language CDATA "sql"
Here is a simple SQL query that retrieves data from a table called
placed in a
<queryString><![CDATA[SELECT * FROM Orders]]></queryString>
Report parameters in the query string are important to further refine the data retrieved
from the database. These parameters can act as dynamic filters in the query that supplies
data for the report. Parameters are introduced using a special syntax, similar to the one
used in report expressions.
Documents you may be interested
Documents you may be interested