Вы находитесь на странице: 1из 21

Whitepapers

Crystal Reports for J2EE Startup Guide

Version 1.0
August 2004
Crystal Reports for J2EE Startup Guide
Citigate Hudson
August 2004
Summary: This whitepaper provides step-by-step instructions on the details of
generating and displaying reports in various deployment scenarios and application
environments using Crystal Reports for Java2, Enterprise Edition.

Overview
What is the Crystal Reports For J2EE Startup Guide?
The Crystal Reports for J2EE Startup Guide (hereafter known as “the guide”) is intended
to get competent J2EE developers, who are new to Crystal Reports or familiar with older
versions, up to speed quickly, using the product in a variety of reporting scenarios. The
guide presents several scenario-driven approaches to designing and building reports
with Crystal Reports. The guide walks through three different reporting scenarios. The
scenarios increase in difficulty, and are described below:

Scenario Description
Basic A Tabular report, designed using the Expert, utilizing a standalone
report file deployed as part of a JSP-based Web application.
Intermediate A Master-Detail report with drill-down capabilities, designed
manually, utilizing a database view (instead of a straight table) as the
data source and using the Crystal Reports Java Reporting
Components tag library as the presentation layer code.
Deployment We discuss how to pass database credentials in to a report (so that
they need not be deployed with the report itself), how to pass
parameters in to the report (to constrain the data displayed as part of
the report), and how to export to PDF for display within the browser.

Prerequisites
The guide provides the most benefit to developers who are familiar with servlets, JSP,
and the general concepts of J2EE. No particular IDE is assumed—all report development
is presumed to be done using the Crystal Reports report development environment,
rather than using any of the IDE integrations offered by Crystal Reports.
In addition, the guide uses the Xtreme Database sample shipped with Crystal Reports,
which installs itself as an ODBC data source. This means that the sample guides will be
using the JDBC-ODBC driver to access and report off of this database, something that in
general should be avoided for any production system, since the Sun JDBC-ODBC driver
is fairly old and fragile. (We use this database so as to provide a baseline that will be
familiar to Crystal developers and other documentation and guides.) Because of the
fragility of the JDBC-ODBC driver, we will be designing the reports using the direct ODBC
connection support in Crystal Reports, but at runtime the data will be coming through
the JDBC-ODBC driver, just to prove that this is a 100% Pure Java (at least as much as
it can be, using that driver) solution.
One administrative prerequisite must be handled before any samples can be started,
however. Crystal Reports, out of the box, does not ship with a JDBC driver for
developing reports against, and must be downloaded from the Business Objects website,
at http://www.businessobjects.com/products/downloadcenter/. Download the
InstallNewDriversv10.zip file, unzip it, run the installation, and when it is complete,
we’re almost ready to make use of the JDBC driver to build a report against. (You’ll need
to do this if you want to design against the JDBC driver—even though we’re not going to
in this guide, you will once you get past these examples.)
The last step necessary to get things into place is to manually edit a configuration file
that was installed as part of this “new drivers” installation. In the “Program
Files\Common Files\Crystal Decisions\2.5\bin” directory, there is a CRDB_JavaServer.ini
file, which needs to be told where to point to your Java Runtime Environment and a
CLASSPATH setting to include the Crystal Reports CRDBJavaServer.jar file. Set the PATH
setting to point to the “bin” directory of your JRE environment, and make sure the
CLASSPATH setting is correct. (Be careful to use backslashes instead of the forward
slash as it appears in the default file; Crystal Reports takes this string quite literally and
will do no “slash translation” as is common in other Java filenames.) In addition, you will
need to point the IORFileLocation to a viable subdirectory, usually something like
C:\Temp. (You can also configure the JVM’s max and min heap sizes in this configuration
file, as per the –mx and –ms options to the java.exe command-line launcher, but for
now the defaults of 64m and 32m, respectively, should be acceptable.)
Although the J2EE Specification is vendor-agnostic, and encourages developers to write
code that can be deployed into any J2EE-compliant application server environment,
unfortunately it is far more difficult to write about J2EE applications in a concrete fashion
without mentioning any vendor-specific details. Rather than try and work around clumsy
sentences such as “deploy the web application using the vendor’s web application
deployment tool to a servlet context name of ‘Example’, and ensure that the deployment
descriptor contains references…”, we will assume the deployment environment is the
latest version of Tomcat (5.0.27, as of this writing), installed on a Windows box at
C:\Tomcat5.01, and is running on port 8080.

1
Be careful, by the way; if the Tomcat installation path contains a space, you may get
errors that complain that “Report location must be set” at runtime. This is because
despite support within Java for file- or directory-names with embedded whitespace, it’s
still awkward to work with names-with-spaces in them. The workaround, of course, is to
install Tomcat to a directory without spaces in it.
Basic Reporting Scenario
The Basic Reporting Scenario illustrates the simplicity of adding reporting capabilities to
a J2EE web-based application. This scenario creates a report using the Crystal Reports
design-time wizards, a.k.a. Experts, which come with the Crystal Reports Designer
environment. No code will be necessary to generate the report, and only a minimal
amount of code will be necessary to wire up the report into the J2EE application.
To create the sample, start the Crystal Reports environment and begin the design of a
new report using File|New. Select “Using the Report Wizard” (which will most likely be
the default) radio buton, and under “Choose a Wizard” leave it selected on “Standard”,
as per Figure 1 below:

Next you will be greeted with a dialog asking you for the data source to generate the
report from. Generally, when developing reports designed to be run from the J2EE
environment, you will want to use JDBC/JNDI database connections, since that’s how the
report will be fetching data at runtime. Double-click “JDBC(JNDI)” (under the “Create
New Connection” folder in the “Available Data Sources” list), and the “JDBC(JNDI)
Connection” dialog will appear, asking for the JDBC or JNDI connection properties to use
in order to connect to the database. In our case, we’re looking to connect against the
Xtreme Sample Database that’s installed as part of the Crystal Reports environment, so
set the Connection URL to a suitable JDBC URL (“jdbc:odbc:Xtreme ”) and the Database
Classname to the JDBC driver of choice (“sun.jdbc.odbc.JdbcOdbcDriver”)2:

2
Again, because of the fragility of the JDBC-ODBC driver, for purposes of this guide, the
report will be designed using the ODBC driver; for any other JDBC driver, however, you
would proceed exactly as described. (Note that the screen shots after this one will show
designing from the ODBC connection, instead of the JDBC-ODBC connection.)
Click Next, and the wizard will next present “Connection Information” for you to fill in
User ID, password, and database values; these correspond to the parameters used when
connecting via the JDBC DriverManager, and for our purposes can remain as they are.

Once we’ve connected to the database, specify the tables to add to the report by
opening up the “Tables” node underneath the data source, and either double-clicking or
selecting and clicking the “>>” button to insert the table names into the right-hand
column. Select the “Customer” table, and click “Next”.
Select which columns should be displayed as part of this report by, again, double-
clicking the column names in the left-hand tree. Select the following columns:
• Customer
ID
• Customer
Name
• Contact
First Name,
Contact
Last Name,
and
Contact
Position
• Address1
and
Address2
• City,
Region,
Country
and Postal
Code
When these
have been
selected, click
“Next”:
We want to
group the
report by
Country, so on
this next page
double click
the
“Customer.Cou
ntry” item
underneath
“Grouping
Fields” in the
left-hand pane,
and click
“Finish” to
generate the
report:
What we end
up with (after
the Report Designer churns for a while, depending on how much data is in the data
source already) is something similar to the following:
At this point, the report is created and ready to run. The last few steps involve setting
up the J2EE application server environment to host the report from the web application.
For this, we will need to do a few installation/deployment tasks in order to enable
Crystal Reports to execute successfully from the application server environment. Save
the report as “Report1.rpt” to a location of your choice (we’ll copy it from there into the
web application directory in just a bit), and close down the Crystal Reports studio.
Several steps need to be done in order to execute the report from the Tomcat web
application (which we’ll assume is running already in a web application called
“CRStartupGuide”, and is already installed as per the Tomcat administrative interface):
1. Copy Java Reporting Component and necessary support .jars from C:\Program
Files\Common Files\Crystal Decisions\2.5\java\lib and C:\Program Files\Common
Files\Crystal Decisions\2.5\java\lib\external into the “/lib” folder inside the web
application or .war file.
2. Copy the contents of the crystalreportviewers10 directory (found in C:\Program
Files\Common Files\Crystal Decisions\2.5) to a subdirectory of the same name
directly underneath the CRStartupGuide directory (as a peer to WEB-INF). Ensure
that all contents, both files and subdirectories, are copied—there should be about
150 files in all. This name of this subdirectory in the CRStartupGuide directory is
not important, so long as it matches up when referenced in the web.xml file,
which must have the following block added:
<context-param>
<param-name>crystal_image_uri</param-name>
<param-value>crystalreportviewers10</param-value>
</context-param>
Generally, developers will leave the name as is (crystalreportviewers10).
3. Copy the CrystalReportingEngine-config.xml file into the “WEB-INF/classes”
subdirectory from C:\Program Files\Common Files\Crystal Decisions\2.5\java
directory. Open it up, and change the “reportlocation” element to read “..”
instead of its default “../..”3.
4. Copy the report file itself into the WEB-INF directory of the webapp.
5. Write the JSP page (call it basic.jsp, in the root of the web application
subdirectory) that will ask the Crystal Reports rendering engine to take the
passed report and generate HTML from it, echoing it back to the webapp’s
current client. This takes two principal steps. First, we need to create a report
viewer to use to process the HTTP request, and second, we need to create a
report source that the report viewer will use as the input for generating the
report. The report source is an simple object around the filename of the report,
as shown here:
<%@ page
import="com.crystaldecisions.reports.reportengineinterface.*,
com.crystaldecisions.report.web.viewer.*" %>

<%
CrystalReportViewer crv = new CrystalReportViewer();
JPEReportSourceFactory jrsf = new JPEReportSourceFactory();
crv.setReportSource(
jrsf.createReportSource("Report1.rpt",
request.getLocale()));
crv.processHttpRequest(request, response,
application, null);
%>
6. Browse to http://localhost:8080/CRStartupGuide/basic.jsp:

3
This will allow you to “hide” the Crystal Reports .rpt file in the WEB-INF directory,
where it will not be directly browsable by the end user of your application. You could
also hide them in /WEB-INF/classes or /WEB-INF/lib, or any other directory under WEB-
INF, so long as you modify the config file accordingly.
Scenario Conclusion
The Basic scenario describes how easy it is to add reporting to a J2EE web-based
application. However, most real-world reporting demands more sophisticated reports
than just simple dumps of tables, even when grouped as above. The “Intermediate”
scenario walks through the creation and design of a report more commonly seen in
production, a master-detail report.
Intermediate Scenario
In this scenario, the application needs a master-detail report with drill-down capabilities;
users wish to select an item from a high-level view (the “master” report), select it, and
be greeted with a host of informational data about the item selected in another view
(the “detail” report).
The report for this scenario is created by creating a Blank Report in Crystal Reports. A
blank report form will be generated in the designer (the Database Expert will open
immediately after clicking “OK”; for now, just ignore it, but don’t close it):

As you can see, it’s not unlike other IDEs you’re probably familiar with—the panel on the
right is the Explorer, where major elements of the report can be explored and
referenced, and the center area is the design view of the report itself. (As we populate
the report with fields from a table, a new view will open up, previewing the report in a
more WYSIWYG fashion so you can ensure that the report will look the way it should.)
If the Database Expert is closed (perhaps you clicked “Cancel” in the dialog that came
up just after creating the new report), bring it up by selecting Database|Database Expert
from the menubar at the top. Navigate once again to the Xtreme database in the Data
connection tree on the left, and open it if it isn’t already opened. (If you have a large
number of ODBC data sources, scrolling through them all can become tedious—feel free
to right-click on the Xtreme node and select “Add to Favorites” so it will be available
under the Favorites node in the Data connection tree.) Select the “Top Customers” view
from underneath the “Views” node in the Xtreme database, and click OK to close:
At this point, the Database Fields node in the Field Explorer to the right will become
expandable, and when expanded will contain the fields that are available to be placed
within this report:

Building a report from scratch involves


manually placing the report fields from
the Field Explorer (at right) into the
design view of the Crystal Reports
designer. Simply drag the following
fields from the Field Explorer to a
position on the report itself:
• Add the following fields to the
Report Header section:
o Text Object whose text is
“Top Customers Drill
Down Report”. Text
Objects can be added by
selecting Insert|Text
Object from the
menubar at the top of
the application. Place the
Text Object to the left of
the Header area, fill in
the text, and stretch the
size of the TextObject
box so all the text can be seen.
o Insert a Print Date field object just to the right of the Text Object. The
easiest way to insert a Print Date field object is to drag one from the
“Special Fields” node (Print Date) in the Field Explorer to the Report
Header section.
o Insert a Print Time field object in much the same manner, again just to
the right of the date object just inserted.
• Add the following fields to the Group Header section:
o From the menubar, select Insert | Group… and at the Grouping dialog
that opens, select the Top_Customers Country field. This will be the
“master” view, looking at all of the Top Customers by country first. (We’ll
let people drill in on the details of each country first in a few minutes.)

o Next, right-click on the “Running Total Fields” node in the Field Explorer,
and select “New” at the context menu that pops up. This will allow you to
create a new Running total for the group. In this particular case, we want
to see the total sales of the Top Customers by Country, so in the Running
Totals dialog that follows, just select the Top_Customers Last Years Sales
field and hit the “>” button to use it. The default operation, “sum” is
sufficient. When you click OK, a new field will have been added to the
Report Explorer, usually by the name of RTotal0. Simply drag this field to
the Group Header section, right next to the “Group #1 Name” field
introduced by the last step.
• Add the following fields to the Details Section of the report:
o Individually drag the Customer Name, Last Year’s Sales, Contact First
Name and Contact Last Name fields into the Details Section of the report.
Note that Crystal Reports will also add column headers right above the
location of the fields in the Details Section.
o Lastly, right-click on the “Details” section in the left-hand panel (directly
underneath the “Group Header” text), and select “Hide (Drill Down OK)” in
the context menu. This is what will hide the details from the master
report, allowing users to double-click on just the items of interest to them.
When finished, the Crystal Report designer should look something like the following:
Save this report as “MasterDetail.rpt”.
Next, we need to deploy this report as part of a web application. As with the Basic
Scenario, create a new web application in the Tomcat server (or reuse the existing one
we created earlier—creating a new one will reinforce the deployment steps necessary to
get Crystal Reports Java Reporting Components to work in a J2EE environment, reusing
the existing one will get you up and running more quickly), and again go through the
steps listed above:
1. Copy the .jars to /WEB-INF/lib
2. Copy the crystalreportviewers10 subdirectory and mark up the deployment
descriptor accordingly. Remember that this needs to be a <context-param>, not
a servlet <init-param> value.
3. Copy the CrystalReportingEngine-config.xml file to /WEB-INF/classes and change
its “reportlocation” element to be “..”.
4. Copy the MasterDetail.rpt file into /WEB-INF.
Now, however, when we create the intermediate.jsp page that will be used to display
the report, we’ll need to take few more steps to make this application work accordingly.
5. Create the JSP page to reference the Crystal Reports tag library, and use two of
the provided tags to configure the viewer:
<%@ taglib uri="/crystal-tags-reportviewer.tld" prefix="crv" %>
<crv:viewer viewerName="" reportSourceType="reportingComponent">
<crv:report reportName="MasterDetail.rpt" />
</crv:viewer>
6. Configure the /WEB-INF/web.xml deployment descriptor to understand the Taglib
URI reference and redirect it to the appropriate TLD tag library descriptor file:
<taglib>
<taglib-uri>/crystal-tags-reportviewer.tld</taglib-uri>
<taglib-location>
/WEB-INF/crystal-tags-reportviewer.tld
</taglib-location>
</taglib>
After modifying the deployment descriptor, make sure to copy over the .tld file
itself from C:\Program Files\Common Files\Crystal Decisions\2.5\java\lib\taglib.
When executed, the report will appear something like the following:
And when the user chooses to drill down on one particular country in the report, the
viewer will change to display something similar to the following:
Scenario Conclusion
In this scenario, we created a master-detail report to show users rolled-up
summarizations of data elements, and yet allowed them to “drill down” into the
particulars of each category as the mood or need arises. Doing so provides a powerful
way of allowing users to remain at a high level when first looking over a report, yet still
home in on particular details when necessary, all within the same report.
We also made use of the Crystal Reports Java Reporting Components tag library, which
simplified the display of the report itself. Although the rendered display would be
identical to that which would be obtained by calling the Java code directly (as we did for
the Basic scenario), this approach is generally much simpler and cleaner, which is in
keeping with the general philosophy of JSP.
In the next scenario, we will build a report that uses reporting to produce a “document”,
suitable for use in legal work, by exporting the report’s results to Adobe Acrobat PDF
format rather than HTML. In addition, we’ll customize the data returned at runtime by
passing a parameter (which we’ll just take off of the query string, but could easily be
passed in via a form instead) to the report to specify which customer’s current orders to
display.
Deployment
Deploying Crystal Reports has already been discussed to a certain degree, in that we’ve
included the report as part of a Web application’s deployment footprint by referencing
the report from the webapp’s WEB-INF subdirectory, but other deployment
considerations frequently arise and require discussion.

Database Credentials
Frequently, we won’t want to store a report’s database login credentials as part of the
report, because either the credentials aren’t known at report execution time (perhaps
the data returned from the report will vary depending on to whom the report is being
shown) or because we want to avoid the possibility of an attacker somehow gaining
access to the report file and learning passwords from it. In these scenarios, we want to
obtain database credentials at runtime, and pass those in to the report before executing
it.
Doing so is relatively trivial—presuming that the following JSP page is the target of an
HTML form that asks for the user’s userid and password in “userid” and “password”
fields respectively, you can see that passing in database credentials to the report is as
simple as creating a ConnectionInfo object, setting the username and password
properties accordingly, putting it into a ConnectionInfos object, and passing that
ConnecitonInfos object to the viewer before executing the report:
<%@ page import="com.crystaldecisions.report.web.viewer.*,
com.crystaldecisions.reports.reportengineinterface.*,
com.crystaldecisions.sdk.occa.report.data.*,
com.crystaldecisions.sdk.occa.report.reportsource.*" %>
<%
CrystalReportViewer viewer = . . .;

// set credentials information


ConnectionInfo ci = new ConnectionInfo();
ci.setUserName(request.getParameter("userid"));
ci.setPassword(request.getParameter("password"));
ConnectionInfos connections = new ConnectionInfos();
connections.add(ci);
viewer.setDatabaseLogonInfos(connections);
// . . .
%>
When the viewer now executes, it will do so using the database credentials passed in via
the indicated parameters. (It goes without saying that you need to make sure that the
“password” field is appropriately hidden from prying eyes, probably by sending this form
over HTTPS, depending on your particular network topology and security needs.) You
also would want to ensure that any failed login attempts are tracked, so as to guard
against brute-force attacks against the database, one of the usual security
considerations for a web application.
Passing Parameters to Reports
In some cases, a report will want to have input criteria passed into it obtained from the
user rather than hard-coded within the report. Again, this can be done fairly easily by
making use of the Crystal Java API, passing in Parameter objects containing the data
captured from the user, usually from some form of HTML form-based input. Doing so is
fairly straightforward; assuming that the user-entered data is in an HTML form field
called “country” (indicating the Country value to use when restricting the report data to
display), the following Java code would set up the appropriate parameter to the report:
<%@ page import="com.crystaldecisions.report.web.viewer.*,
com.crystaldecisions.reports.reportengineinterface.*,
com.crystaldecisions.sdk.occa.report.data.*,
com.crystaldecisions.sdk.occa.report.reportsource.* " %>

<%
CrystalReportViewer viewer = . . .;

// Passing parameters
Fields fields = new Fields();
ParameterField param = new ParameterField();
param.setReportName("Report"); // must always be set, even if just to ""
param.setName("Country");
Values vals = new Values();
ParameterFieldDiscreteValue val = new ParameterFieldDiscreteValue();
val.setValue(request.getParameter("country"));
vals.add(val);
param.setCurrentValues(vals);
fields.add(param);

viewer.setParameterFields(fields);
%>
Notice that each ParameterField can have multiple values associated with it; although
not used in this scenario, this is to allow for range values to be passed in as well as
specific values, such as a range of names to use (as opposed to a particular name) when
querying the database. This provides a huge range of flexibility in reporting that would
be difficult to create directly without complicated SQL queries.

Exporting Reports
Frankly, not everybody who reads reports adores the HTML format. HTML itself, while a
powerful markup language (particularly when combined with CSS or DHTML), simply
cannot provide the kind of presentation capability that many users will demand,
especially when looking to print reports to paper. In these situations, it would be far
better if the report could be generated to a more presentation-friendly technology, such
as Adobe Acrobat Portable Document Format (PDF), or Microsoft Rich Text Format
(RTF).
Fortunately, Crystal Reports Java Reporting Component provides for such capability; in
essence, the reporting component becomes a renderer of PDF and/or RTF files, rather
than just HTML, and if the user has the Adobe Acrobat Plug-In or Microsoft Word Viewer
installed into their browser, can browse these reports in a far richer format than just
plain HTML.
Exporting a report to PDF or RTF is a matter of using a different “viewer” component to
execute the report against, as shown below:
<%@ page import="com.crystaldecisions.report.web.viewer.*,
com.crystaldecisions.reports.reportengineinterface.*,
com.crystaldecisions.sdk.occa.report.data.*,
com.crystaldecisions.sdk.occa.report.reportsource.*,
com.crystaldecisions.sdk.occa.report.exportoptions.*" %>
<%
String report = "document.rpt";
IReportSourceFactory2 rptSrcFactory = new JPEReportSourceFactory();
IReportSource reportSource = (IReportSource)
rptSrcFactory.createReportSource(report, request.getLocale());

ReportExportControl exportControl = new ReportExportControl();


ExportOptions exportOptions = new ExportOptions();
exportOptions.setExportFormatType(ReportExportFormat.PDF);

PDFExportFormatOptions pdfexpopts = new PDFExportFormatOptions();


exportOptions.setFormatOptions(pdfexpopts);

exportControl.setReportSource(reportSource);
exportControl.setExportOptions(exportOptions);
exportControl.processHttpRequest(request, response,
getServletConfig().getServletContext(),
null);
exportControl.dispose();
%>
Doing so to RTF would set the export format type to ReportExportFormat.RTF, and use
an RTFWordExportFormatOptions instance rather than the PDF one shown above. Note
that the format options class carries a number of variables with it, such as the starting
and ending page number to export. (Officially, one should use the
IPDFExportFormatOptions or IRTFWordExportFormatOptions interfaces instead of their
concrete subclasses, but the two, as of this writing, are one and the same.)
Summary and Conclusions
This document introduced Crystal Reports 10 for J2EE applications through four common
reporting scenarios. The scenarios built upon one another. Each sample report described
one or more features and discussed how to implement each feature in the report.
The Basic scenario created a simple report listing customers from the sample database.
Report Experts did most of the work designing the report. Data was retrieved directly
from the customers table, and was displayed via the Java Reporting Component API.
Drill down capabilities was the highlighted feature in the Intermediate scenario. Drill
down enables users to view the detail records that make up a summary record. This
report introduced on the idea of retrieving data from views, as well as the JSP Tag
library supplied with the Java Reporting Component.
The Sub-report scenario demonstrated embedding a report within a report. Performance
considerations were accounted for by configuring the sub-report to load on the click of a
hyperlink.
The Document scenario highlighted Crystal’s exporting features. Legal documents were
created by exporting a report to PDF format and displaying the PDF data in a Web
browser.
This startup guide touches on many features available with Crystal Reports 10. These
features are designed to ease reporting development and deployment for programmers
and enhance report presentation and functionality for end users.

About the Author


Citigate Hudson is a provider of custom database applications and a
Microsoft Gold Certified Partner for business intelligence solutions. See
their website at www.citigatehudson.com.

Вам также может понравиться