This section will contain a list of solutions to common problems. It will also serve as base for those who want to convert their reports manually and will list of features known to work in JFreeReport 0.8 can be achieved in the new system.
How to load a report
Loading the report definition from an XML file hasn't changed much.
Instead of using the ReportFactory
, we now use a centralized ResourceManager
. That resource manager handles all load-operations. It keeps track of changes to the underlying files and tries to apply as much caching as possible. The resource-manager is contained in LibLoader.
Code Block |
---|
ResourceManager manager = new ResourceManager();
manager.registerDefaults();
|
The resource manager provides resource-objects, which grant access to some additional meta-data. The first parameter of the 'create' operation is the source object. This can be anything, like an URL, a File (or a string representation of those) or a byte containing the raw-data. Resources stored on the classpath can be accessed using the String "res:/package/file.name".
You may want to have a look at the sources of the libloader, especially the subpackages file, raw, resource and zip of the package org.jfree.resourceloader.loader and the code of the method org.jfree.resourceloader.ResourceManager.registerDefaultLoaders() in order to understand the resource handling better.
There are ResourceLoaders for reading from Files, from the Classloader, from given byte[] arrays and from zip archives (i.e. jar files). You can register your own implementations of ResourceLoader and AbstractResourceData in order to add other sources.
Code Block |
---|
Resource res = manager.createDirectly(source, JFreeReport.class);
|
In most cases, however, we are interested in the result of the loading, which can be accessed like this.
Code Block |
---|
final JFreeReport report = (JFreeReport) res.getResource();
|
If the report definition contained references to StyleSheets or SQL-Datasources, then these referenced resources have been loaded as well. The report object can be fed directly into the preview components.
How to show a print preview
I assume that you already have a fully initialized JFreeReport-object. Simply create either a PreviewDialog or a PreviewFrame, set the report, and show the report. The dialog and frame can be reused (although noone will be hurt if new dialogs are created for each report).
The preview components have moved from package 'org.jfree.report.modules.gui.base' (in JFreeReport 0.8.x) to 'org.jfree.report.modules.gui.swing.preview'.
JFreeReport does no longer work directly with the JFreeReport object. All configuration and datasource properties are now accessed using a generic interface called 'ReportJob'. The ReportJob holds all information that are neccessary to process a report.
Code Block |
---|
JFreeReport report; // from the parser ..
// create a report-job
ReportJob job = new DefaultReportJob (report);
final PreviewDialog frame = new PreviewDialog();
frame.setReportJob(reportJob);
frame.pack();
RefineryUtilities.positionFrameRandomly(frame);
frame.setVisible(true);
|
How to assign DataSources to an report
When using SQL-DataSources in conjunction with the XML definitions, the parser will already connect the report definition with the datasource The Quadrant-Demo uses SQL-Databases, for example:
Code Block |
---|
<report:report xmlns="http://www.w3.org/1999/xhtml"
xmlns:report="http://jfreereport.sourceforge.net/namespaces/reports/flow">
<report:datasource href="quad.sqlds"/>
<report:query>default</report:query>
..
</report:report>
|
The 'quad.sqlds' is yet another XML file:
Code Block |
---|
<sql-datasource
xmlns="http://jfreereport.sourceforge.net/namespaces/datasources/sql"
xmlns:html="http://www.w3.org/1999/xhtml">
<connection>
<driver>org.hsqldb.jdbcDriver</driver>
<url>jdbc:hsqldb:./sql/sampledata</url>
<properties>
<property name="user">sa</property>
<property name="pass"></property>
</properties>
</connection>
<query name="default">
SELECT
QUADRANT_ACTUALS.REGION,
QUADRANT_ACTUALS.DEPARTMENT,
QUADRANT_ACTUALS.POSITIONTITLE,
QUADRANT_ACTUALS.ACTUAL,
QUADRANT_ACTUALS.BUDGET,
QUADRANT_ACTUALS.VARIANCE
FROM
QUADRANT_ACTUALS
ORDER BY
REGION, DEPARTMENT, POSITIONTITLE
</query>
</sql-datasource>
|
But not everyone uses SQL. To have a generic fallback and as we successfully used those in the past, we also support Swing-TableModels as inputsources. As stated in the documentation, the primitive Swing-Table-DataSources are not parametrizable, so there is no sane chance to get master detail-reports up and running with the default TableReportDataFactory
implementation.
Code Block |
---|
JFreeReport report; // from the parser ..
TableModel model; //
final DefaultReportJob job = new DefaultReportJob(report);
final TableReportDataFactory dataFactory = new TableReportDataFactory("default", tableModel);
job.setDataFactory(dataFactory);
|
The name the Table-Model is registered with the report-data-factory must be the same as the query-name used in the report-object.
How can I format the output of number fields?
formating is now handled by the style system. So if you pass in a number or date object, it can be formated using a style rule. OK, no one wants to declare own rules, so there are some sane defaults:
This is the snipped of the default stylesheet that is responsible for formating values:
Code Block |
---|
@namespace url(http://jfreereport.sourceforge.net/namespaces/reports/flow);
@namespace xml url(http://www.w3.org/XML/1998/namespace);
@namespace report url(http://jfreereport.sourceforge.net/namespaces/engine);
content[report|content] {
content: attr("report|content");
display: inline;
}
content[report|content][report|isDate=true] {
content: format(attr("report|content", date), date);
}
content[report|content][report|isDate=true][report|format] {
content: format(attr("report|content", date), date, attr("report|format",string));
}
content[report|content][report|isNumber=true] {
content: format(attr("report|content", number), number, "#,##0.00");
}
content[report|content][report|isNumber=true][report|format] {
content: format(attr("report|content", number), number, attr("report|format",string));
}
content[report|content][report|isNumber=true][report|isInteger=true] {
content: format(attr("report|content", number), number, "#,##0");
}
content[report|content][report|isNumber=true][report|isInteger=true][format] {
content: format(attr("report|content", number), number, attr("report|format",string));
}
|
In common wording: If you have an "flow:content" element (where flow is a namespace identifier pointing to the namespace uri "http://jfreereport.sourceforge.net/namespaces/reports/flow") that has a 'format' attribute, then the engine will take the value from the 'content' element's content attribute and format the value found there with the formatstring found in the 'format' attribute. The attributes of the namespace 'report' are automaticly filled in by the engine itself, you dont have to care about where they come from, simply assume that they are there whenever you refer to a ContentElement.
Example:
Code Block |
---|
<report:report xmlns:report="http://jfreereport.sourceforge.net/namespaces/reports/flow">
..
<report:content>
<report:value-expression formula="jfreereport:12345678" format="#.##0.00"/>
</report:content>
</report:report>
|