Incorporating DataVision Into a Java Application
It isn't difficult to incorporate DataVision into a Java application.
Instantiate a Report object and have it read the XML file and possibly a
parameter value XML file, then give the report object a layout engine
object (such as LaTeXLE).
To run a report from a JSP page, see Running DataVision
from JSP below.
To run your application you will need to include in your classpath the
JAR files that are in the lib directory. They include
- DataVision,
- iText, the Java-PDF library by Bruno Lowagie,
- JCalendar, the calendar Swing widget by Kai Toedter,
- BSF, the Bean Scripting Framework from the Apache Jakarta Project,
- JRuby, the Java implementation of Ruby by the JRuby Project, and
Here is the code you need to run a report from within your application.
First, we will present some code chunks interspersed with insightful
commentary. A few complete examples, showing different data sources and
layout engines, will round out this section.
Creating a report object
First, create a report object.
Report report = new Report();
Specifying a database data source
What happens next depends upon the data source that the report XML file
describes. If it's a database, we have to give some information (the
database password) to the report before we read the XML file. If the data
source is a text file, we need to specify some things after the XML file is
read and the data source object is created.
The report's connection to a database can be specified one of three
ways. You can supply a database password, a
java.sql.Connection object, or a
jimm.datavision.sql.Database object.
If you supply a password, the XML file's database connection information
will be used to create a new connection. This is what normally happens when
you open a report via the GUI, for example.
Both of the other methods (supplying a connection or database object)
ignore the database connection information in the report XML file. If you
supply a connection it will not be closed by the report, even if
the report's database connection is reset by calling
Database.reset. You will have to close the connection yourself
after the report is done running.
The only reason you would supply a
jimm.datavision.sql.Database object is to reuse one between
different report instances. The advantage of reusing a database object is
that the database metadata (table names, column names, and more) will only
be read once no matter how many reports use it. Reading the metadata is
time-consuming.
// Give the report enough information to connect to a database
// data source. Pick one of the following three lines.
report.setDatabasePassword("mypassword");
// or
report.setDatabaseConnection(aJdbcConnection);
// or
report.setDataSource(new Database(...));
Reading the report description XML
file
Next, call Report.read to read a report's
description XML. This method can take as an argument a file or an org.xml.sax.InputSource. The InputSource constructor can take a java.io.InputStream, a java.io.Reader, or a String
that specifies a system identifier. If the system identifier is a URI (a URL),
it must be fully resolved.
// Read the report XML from a file or various stream types.
report.read(xmlFileOrInputSource); // Must be after database info
Specifying a text file data source
If the data source is a text file instead of a database, we need to tell
the data source which file to read and optionally override the separator
character specified in the XML file. If no character is defined in either
the XML file or your code, the default character (comma) is used.
The method CharSepSource.setInput can take as an argument a
file name, a java.io.Reader, or a
java.io.InputStreamReader.
CharSepSource src = (CharSepSource)report.getDataSource();
src.setSepChar('\t'); // Optional; overrides default and XML file value
src.setInput(fileNameOrReaderOrInputStreamReader);
Reading parameter values
If necessary, read parameter values. There are three ways a report gets
parameter values: by asking the user, by reading a parameter XML file, or
with custom Java code that sets the parameter values. See Asking for Parameter Values below for a
complete description of the three different ways to set parameter values.
The method Report.setParameterXMLInput is used to read parameter
values from XML. This method takes the same arguments as
Report.read, described above.
// If necessary, read parameter values.
if (report.hasParameterFields())
report.setParameterXMLInput(paramXMLFileOrInputSource);
Setting the layout engine
Next, give the report a layout engine. This example uses the LaTeX
layout engine. You could use HTML, PDF, Swing, or any other one.
report.setLayoutEngine(new LaTeXLE(aWriter));
Running the report
Finally, run the report either in a separate thread or in the current
thread. Report.run runs the report in a separate thread. It
does not wait for the thread to finish. You will have to write the code to
wait. If you call Report.runReport, the report is run
synchronously; the method does not return until the report is done
running.
// Pick one of the following two.
report.run(); // Run the report in a separate thread.
// or
report.runReport(); // Run the report in this thread.
Telling a Swing layout engine to
exit
If you use a Swing layout engine, there is one more thing you may want
to do: exit. When the user closes the Swing report window, the application
does not automatically quit---the event loop keeps running.
The SwingLE layout engine has a method called
close. It does not exit the application, but we can create an
anonymous class that overrides that method and closes the application when
the window is closed. Here's how:
LayoutEngine le = new SwingLE() {
public void close() {
super.close();
System.exit();
}
};
report.setLayoutEngine(le);
Similarly, when the last design window is closed DataVision normally
exits. The method DesignWin.setExitWhenLastWinClosed does what
it says: it lets you determine if DataVision should exit when the last
design window is closed.
All together now
Here's the whole thing all together. This code will run a report that
uses a database connection to read data, reads the report XML file, reads a
parameter file if necessary, and outputs to a PDF file.
Report report = new Report();
report.setDatabasePassword("mypassword");
report.read("reportXmlFile");
if (report.hasParameterFields())
report.setParameterXMLInput("paramXmlFile");
OutputStream out = new FileOutputStream("output.pdf");
report.setLayoutEngine(new PDFLE(out));
report.runReport();
Asking for Parameter Values
There are three ways a report gets parameter values: by asking the user, by
reading a parameter XML file, or with custom Java code that sets the
parameter values.
Asking the User
If you want the user to be prompted for input, you should not give the
report a parameter file name. Instead, you should tell the system that you
want to use a Swing window to prompt the user for parameter values by using
the following code some time before running the report:
ErrorHandler.useGUI(true);
Reading a Parameter XML File
To read a parameter XML file, call Report.setParameterXMLInput.
report.setParameterXMLInput(paramXMLFileOrInputSource);
To specify a parameter file on the command line, use the -r command
line option. See Running DataVision from
the Command Line for details.
Setting Values Manually
To specify a parameter's value within your code, you need to ask the
report object to find it and then set its value.
// Ask the report to find the parameter for you
Parameter p = report.findParameter(new Long(myParamID));
// or p = report.findParameterByName("My Parameter Name");
// Set the parameter's value. This sets a single value.
p.setValue(0, "The New Value");
// To set more values (if it is a range or a list of values), keep
// calling setValue().
// p.setValue(1, "Another Value");
There is one more thing you have to do. As of version 0.7.11, there is a
new method named Report.parametersSetManually. Calling this
method with an argument of true tells the report not to ask
the user and not to read an XML file.
report.parametersSetManually(true);
Calling this method replaces the earlier necessity of creating a
subclass of Report that overrode the
askForParameters method.
Running DataVision from JSP
You can run a report in a JSP page, but you can't display its output
directly, even if you use the HTML layout engine. You need to save the
output to a (possibly temporary) file and then display the contents of that
file or let the user download it.
For an example JSP page, see datavision.jsp in the
examples directory. The comment at the top of that
file contains directions for installing and running it from Tomcat.
If your report contains parameters, you will need to let the user enter
them. You then need to give those values to the report before it is run.
Either save the values into a parameter XML file and call
report.setParamterXMLInput("path_to_param_xml_file");
or use the code found in Asking for Parameter
Values.
Reporting For The Web
With DataVision, by Frank W. Zammetti, is an article that shows you
how to design a simple report and run it from within a Web application.
Running DataVision as an Applet
DataVision can be run as an applet. The file applet.html
contains an example ``applet'' tag suitable for use with DataVision.
The applet code is still under development; expect some
problems.
In the example file applet.html, the ``archive'' attribute
does not contain a database JAR file or jcalendar.jar. To run
reports instead of just design them, you would have to add your JDBC JAR
file and jcalendar.jar to this list. Why aren't those files in
the list already? Because the applet code is being developed first to allow
report design. Running reports should work; I just haven't tested it yet.
Since JRuby (and possibly other Bean Scripting
Framework jar files) uses a custom class loader, you will have to
either sign the applet or edit the client's java.policy file and
add the line
permission java.lang.RuntimePermission "getClassLoader";
Many thanks to Edwin Ramirez, who has funded development of
DataVision in order to create the applet code. All of his suggestions and
feature requests have been folded into DataVision.