21
Whitepapers Crystal Reports for J2EE Startup Guide Version 1.0 August 2004

Cr Java Startup Guide

Embed Size (px)

Citation preview

Page 1: Cr Java Startup Guide

Whitepapers

Crystal Reports for J2EE Startup Guide

Version 1.0

August 2004

Page 2: Cr Java Startup Guide

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.

Page 3: Cr Java Startup Guide

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.

Page 4: Cr Java Startup Guide
Page 5: Cr Java Startup Guide

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.)

Page 6: Cr Java Startup Guide

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”.

Page 7: Cr Java Startup Guide

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.Country” 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:

Page 8: Cr Java Startup Guide

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).

Page 9: Cr Java Startup Guide

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.

Page 10: Cr Java Startup Guide

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.

Page 11: Cr Java Startup Guide

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:

Page 12: Cr Java Startup Guide

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

Page 13: Cr Java Startup Guide

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.

Page 14: Cr Java Startup Guide

• 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:

Page 15: Cr Java Startup Guide

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:

Page 16: Cr Java Startup Guide

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:

Page 17: Cr Java Startup Guide

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.

Page 18: Cr Java Startup Guide

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.

Page 19: Cr Java Startup Guide

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

Page 20: Cr Java Startup Guide

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.)

Page 21: Cr Java Startup Guide

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.