| Sign In/My Account | View Cart |
Dynamic Creation of Reports with Apache Formatting Objects
Pages: 1, 2, 3, 4
During development of report generation solutions, various reporting tools and libraries may be selected for use to reduce development time and associated costs. Limiting the impact of changing or adding additional components, and supporting the different configurations that result, can be problematic in this context. Decomposing the system as much as possible into parts that can be removed as easily as they can be added or replaced alleviates some of the problem. Reducing the number of steps to remove or add parts reduces the number of potential errors and facilitates easier reconfiguration. This is the intent of the report-creation component, which defines a static interface whose underlying implementation can be handled by a variety of software product components.
Dependency among parts is the primary determinant of system complexity. Complexity exponentially correlates to increased difficulty in system maintenance, evolution, verifiability, and robustness. Too much dependency defeats the benefits achieved by decomposition. Using well-defined interfaces passing a limited set of parameters limits subsystem dependencies.
Encapsulation involves combining data and behavior behind an interface that exposes only abstracted behavior. Implementation of modules with crossdependencies or duplicate responsibilities increases system complexity and hinders evolution. Encapsulation of the reporting support tools' capabilities within the report content subsystem reduces system complexity.
The reporting system acts as a façade, decoupling the underlying report generation mechanisms completely from the client. It encapsulates the other report generation subsystems and defines an explicit interface defining available capabilities.
Figure 4 shows the basic sequence of events that take place when a report is requested. It is a high-level representation using packages defined in the architecture definition.

Figure 4. Package Level Sequence Definition for Report Request. (You can click on the screen shot to open a full-size view.)
The main responsibilities and interfaces for the packages used in the sequence are as follows:
Responsibilities
Interfaces
To access the reporting system, the following interfaces are defined:
For a synchronous request:
public OutputStream requestReport(String reportType, String styleSheet,
int renderFormat, java.security.Principal principal)For an asynchronous request:
public void requestReport(String reportType, String styleSheet,
int notification, String notificationAddress, int renderFormat,
java.security.Principal principal)Responsibilities
Interfaces
To assemble the data content of the report:
mergeData(java.lang.Principal principal,
String template, String tempFile)
The principal defines the user to be authorized. Template defines the report template that is used as the basis of the report. TempFile is the location of the report with data content only, in XML format.
To apply a style to the report and convert to requested output format:
styleAndRender(String tempFile, String styleSheet,
int renderFormat, OutputStream output)
TempFile is the location of the report data content created from the mergeData call. Stylesheet defines the XSL information used to apply the report style. RenderFormat is a constant value used to define the output format. Output is the OuputStream where the final formatted report is streamed.
Responsibilities
Principal has rights to view the sections of data content that are to become part of the report. Interfaces
Responsibilities
Interfaces
To start the processing of the data producer that gets and returns the report data content as XML:
StringBuffer process( )Responsibilities
Interfaces
The content of the report, the style applied to a report, and the rendered format are all distinct and separate operations. The same content can potentially have different styles applied to it and the styled report can be converted to a number of different formats (e.g., PDF or PostScript).
The first step in creating a report is to access and merge the dynamic content. Data content for a report is defined using XML and a custom defined set of tags and attributes that are relevant to the specific report type. A report template is used to define the type of content that will populate the report and data producers provide the dynamic content.
The second step in report creation is to apply a style to the report content generated in the first step. One or more stylesheets may be defined for a report. The requester of the reporting system may choose which style to apply. Stylesheets use the XSL:FO recommendations from the W3C. The XSL definitions are applied to the XML data using FOP classes. FOP includes a Driver class that starts the translation process, given an XML and XSL file.
InputHandler inputHandler = new XSLTInputHandler(XMLFile, XSLFile);
XMLReader parser = inputHandler.getParser();
The XSLTInputHandler reads in the data and style information, performs the transformation, and streams the new data to an XMLReader.
The data is then ready to be rendered by the FOP tools by defining the desired output format and the OutputStream to use. Using the Apache Formatting Object Processor makes these operations very simple.
driver.setRenderer(outputFormat);
driver.setOutputStream(output);
driver.render(parser, inputHandler.getInputSource());
In the implementation that goes along with this article, the XML data file is generated and saved as a file. The file is useful for validating that the data is correct and for applying various styles during development. A production system would most likely stream the XML data content directly to the XSL transformation processing, eliminating the time it takes to write the data to a file.
FOP provides a number of different renderers as part of the distribution. Additional renderers are in the works or can be added to the libraries as explained on the xml.apache.org FOP Web site.