当前页面: 开发资料首页 → Netbeans 专题 → Generating Reports and PDFs From a Web Application
摘要: When you need to generate a report, a chart, or a PDF file from a web application, you have many third-party products to help you accomplish your task, including the open source JasperReports framework. JasperReports is a reporting tool that outputs reports in HTML, PDF, XLS, CSV, and XML formats. This tutorial show how to integrate the JasperReports framework into a web application that you build using the NetBeans Visual Web Pack
In this tutorial, you create a web application that displays and prints information from a travel database. The web application lets you view a trip report in either HTML format or PDF format.
JavaServer Faces Components/ Java EE Platform |
![]() ![]() | |||
Travel Database | ![]() |
|||
BluePrints AJAX Component Library | ![]() |
* As of the date this tutorial was published, only the Sun Java System Application Server supported Java EE 5.
This tutorial has been tailored for use with the Sun Java Application Server PE 9.0 Update Release 1 and with Tomcat 5.5.17. If you are using a different server, consult the Release Notes and FAQs for known problems and workarounds. For detailed information about the supported servers and Java EE platform, see the Release Notes.
Download jasperreports-1.3.0-project.zip
from http://www.jasperforge.org and extract the files. You must register with JasperForge before you can download the zip file.
JasperReports130
in the Library Name text box, and click OK. jasperreports-1.3.0-project.zip
files. dist
directory, select jasperreports-1.3.0.jar
and press Enter. ../lib
directory (go up one directory and down into the lib
directory). Use Ctrl-Click to select the following JAR files and press Enter. If you are using a different version than 1.3.0, consult the JasperForge web site to determine which JAR files to select.
commons-beanutils-1.7.jar
commons-collections-2.1.jar
commons-digester-1.7.jar
commons-logging-1.0.2.jar
itext-1.3.1.jar
commons-javaflow-20060411.jar
. Verify that you have added the six libraries, as shown in the following figure.
![]() Figure 1: Library Manager Window Showing the JasperReports130 Library |
jasperreports-1.3.0-project.zip
files, select the dist/javadoc
subdirectory, and press Enter. jasperreports-1.3.0-project.zip
files, select the src
subdirectory, and press Enter. You write your JavaReport templates in XML format. To enable the IDE's editor to recognize a JavaReport XML file (JRXML) as an XML file, you use the Options dialog to add jrxml to the Extensions and MIME Types
property for the XML object, as shown in the following figure.
![]() Figure 2: Associating a JRXML file with XML Objects |
Extensions and MIME Types
property to open the customizer editor. jrxml
in the Item text box and click Add. Right-click the jdbc node for the Travel database and choose Connect from the pop-up menu.
If the Travel database is not available, see the Configuration Information section in the NetBeans Visual Web Pack Installation Instructions for information.travel
for the Password and select Remember Password During This Session. TravelReport
.Select the desired Server and Java EE Version, and click Finish.
Your project appears with the initial page (Page1) open in the Visual Designer.
Note that if you use a server other than the Sun Java System Application Server, you must make the database driver available to the server. See the Visual Web Project Configuration section of the Installation Guide for more information.
In the Add Library window, select JasperReports130 as shown in the following figure, and click Add Library.
![]() Figure 3: Adding the JasperReports130 Library |
In this section, you add an images directory and put the company's logo in this directory. Next, you add a JRXML template for the trip report, and you modify the project's build file to compile the JRXML template into a Jasper binary report template.
The JRXML template generates a report like the one shown in the following figure.
![]() Figure 4: Trip Report |
images
in the Folder Name text box and press Enter. Right-click the following image and use your browser's command for saving the image to your disk. Save the image in the path-to-web-project/TravelReport/web/resosurces/images
folder.
![]() Figure 5: Company Logo |
reports
in the Folder Name text box.src
and press Enter. In the Label text box for the src/reports row, change the value to JasperReports Definitions
and press Enter.
Click the Projects header and notice the new JasperReports Definition node, which has a <default package> subnode.
In the next step, you put a report definition in this default package. Later, you modify the build script to compile the report definitions in this folder into thebuild/web/WEB-INF/reports
folder, which is where the runtime code in ApplicationBean1 expects to find them.TripReportByPerson.jrxml
in the File Name text box and press Enter. The new file opens in the XML editor. Copy the following XML tags and and paste into the empty XML file.
Code Sample 1: JasperReport Template TripReportByPerson.jrxml |
<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="TripReportByPerson">
<style name="Arial_Normal" isDefault="true" fontName="Arial" fontSize="12"
isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false"
pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<style name="Arial_Bold" fontName="Arial" isDefault="false" isBold="true"
pdfFontName="Helvetica-Bold"/>
<style name="Arial_Header1" fontName="Arial" isDefault="false" fontSize="22"
isBold="true" pdfFontName="Helvetica-Bold"/>
<style name="Arial_Bold_White" fontName="Arial" forecolor="white"
isDefault="false" fontSize="12" isBold="true" pdfFontName="Helvetica-Bold"/>
<parameter name="LogoURL" class="java.net.URL"/>
<field name="NAME" class="java.lang.String"/>
<field name="TRIPID" class="java.lang.Integer"/>
<field name="DEPDATE" class="java.util.Date"/>
<field name="DEPCITY" class="java.lang.String"/>
<field name="DESTCITY" class="java.lang.String"/>
<field name="DESCRIPTION" class="java.lang.String"/>
<group name="PersonGroup" minHeightToStartNewPage="84">
<groupExpression>
<![CDATA[$F{NAME}]]>
</groupExpression>
<groupHeader>
<band height="64">
<textField>
<reportElement style="Arial_Bold" mode="Opaque" x="0" y="24"
width="550" height="15" backcolor="#e0e0e0" />
<textFieldExpression class="java.lang.String">
<![CDATA["Scheduled Trips for " + $F{NAME}]]>
</textFieldExpression>
</textField>
<line>
<reportElement x="0" y="39" width="550" height="1" />
<graphicElement />
</line>
<frame>
<reportElement x="0" y="40" width="550" height="20"
mode="Opaque" backcolor="lightGray"/>
<staticText>
<reportElement style="Arial_Bold_White" x="20" y="2" width="130" height="15" />
<text><![CDATA[Departure Date]]></text>
</staticText>
<staticText>
<reportElement style="Arial_Bold_White" x="150" y="2" width="130" height="15" />
<text><![CDATA[Departure City]]></text>
</staticText>
<staticText>
<reportElement style="Arial_Bold_White" x="280" y="2" width="130" height="15" />
<text><![CDATA[Destination City]]></text>
</staticText>
<staticText>
<reportElement style="Arial_Bold_White" x="410" y="2" width="130" height="15" />
<textElement textAlignment="Left" />
<text><![CDATA[Purpose]]></text>
</staticText>
</frame>
</band>
</groupHeader>
</group>
<pageHeader>
<band height="94">
<image>
<reportElement x="0" y="0" width="441" height="60"/>
<graphicElement/>
<imageExpression class="java.net.URL">
<![CDATA[$P{LogoURL}]]>
</imageExpression>
</image>
<line>
<reportElement x="0" y="60" width="550" height="1"/>
<graphicElement/>
</line>
<staticText>
<reportElement style="Arial_Header1" x="0" y="60" width="445" height="30" />
<text><![CDATA[Trip Report by Employee]]></text>
</staticText>
</band>
</pageHeader>
<detail>
<band height="20">
<textField pattern="dd/MM/yyyy">
<reportElement x="20" y="0" width="100" height="20"/>
<textFieldExpression class="java.util.Date">
<![CDATA[$F{DEPDATE}]]>
</textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="150" y="0" width="100" height="20"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{DEPCITY}]]>
</textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="280" y="0" width="100" height="20"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{DESTCITY}]]>
</textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="410" y="0" width="100" height="20"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{DESCRIPTION}]]>
</textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
|
Add the following script before the </project>
tag.
The script overrides the -post-compile target, which the IDE calls after it compiles the Java sources. The target script compiles any JRXML file found in the src/reports
folder and puts the compiled report in the build/WEB-INF/reports
folder.
Code Sample 2: build.xml Report Compilation Script |
<!-- Customize the following property to point to the folder
in which you unpacked your Jasper Reports release -->
<property name="jrc.home"
value="JasperReports-Install-Dir/jasperreports-1.3.0"/>
<!-- Define the classpath used for report compilation -->
<path id="jrc.classpath">
<fileset dir="${jrc.home}/dist"
includes="*.jar"/>
<fileset dir="${jrc.home}/lib"
includes="*.jar"/>
</path>
<!-- Define the custom Ant task that compiles report definitions -->
<taskdef name="jrc"
classname="net.sf.jasperreports.ant.JRAntCompileTask">
<classpath refid="jrc.classpath"/>
</taskdef>
<!-- Define the target that will compile reports, after Java compiles
have been completed -->
<target name="-post-compile"
description="Compile all Jasper Reports Definitions">
<!-- Create the output directory first -->
<mkdir dir="${build.web.dir}/WEB-INF/reports"/>
<!-- Compile report definition -->
<jrc srcdir="src/reports"
destdir="${build.web.dir}/WEB-INF/reports">
<classpath
refid="jrc.classpath"/>
<include
name="*.jrxml"/>
</jrc>
<!-- Omit the report definition sources from the webapp -->
<delete>
<fileset dir="${build.web.dir}/WEB-INF/classes"
includes="*.jrxml"/>
</delete>
</target>
|
build.xml
script. In the Files window, expand build > web > WEB-INF > reports, and verify that the IDE generated the TripReportByPerson.jasper
binary.
jrc.home
property in the build.xml
file.The JasperReports framework includes a servlet named ImageServlet
for displaying images in generated HTML reports. Even if you do not include images in your report, you must add a mapping for this servlet, because JasperReports uses blank images for spacing.
ImageServlet
. You use the image URI later when you add code to export the report to HTML. In the Files window, expand web > WEB-INF, and double-click the web.xml node to open it in the XML editor.
Make sure you edit the web.xml file under web > WEB-INF, and not the one under build > web > WEB-INF. If you edit the web.xml under build > web > WEB-INF, you will lose your changes the next time you build the project.In the Servlets editor, click Add Servlet Element.
The Add Servlet dialog box appears as shown in the following figure.
![]() |
In the Add Servlet dialog box, type the following values and click OK.
Text Box | Value |
---|---|
Servlet Name | ImageServlet |
Servlet Class | net.sf.jasperreports.j2ee.servlets.ImageServlet |
URL Patterns | /image |
Close web.xml and save the changes.
Now, the application knows that when it receives a request that is addressed toimage
, the application should send the request to the ImageServlet
instance. Add the following code to the end of the file before the final end brace.
Code Sample 3: Report Generation Code |
/**
* <p>Prefix to the resource name for compiled reports.</p>
*/
private static final String PREFIX = "/WEB-INF/reports/";
/**
* <p>Suffix to the resource name for compiled reports.</p>
*/
private static final String SUFFIX = ".jasper";
/**
* <p>Valid content types for reports that we can produce.</p>
*/
private static final String[] VALID_TYPES =
{ "text/html", // Standard HTML representation
"application/pdf", // Adobe Portable Document Format
};
/**
* <p>Generate the specified report, in the specified output
* format, based on the specified data.</p>
*
* @param name Report name to be rendered
* @param type Content type of the requested report ("application/pdf"
* or "text/html")
* @param data <code>ResultSet</code> containing
* the data to report
*
* @exception IllegalArgumentException if the specified
* content type is not recognized
* @exception IllegalArgumentException if no compiled report definition
* for the specified name can be found
*/
public void jasperReport(String name, String type,
ResultSet data) {
jasperReport(name, type, data, new HashMap());
}
/**
* <p>Generate the specified report, in the specified output
* format, based on the specified data.</p>
*
* @param name Report name to be rendered
* @param type Content type of the requested report ("application/pdf"
* or "text/html")
* @param data <code>ResultSet</code> containing the data to report
* @param params <code>Map</code> of additional
* report parameters
*
* @exception IllegalArgumentException if the specified
* content type is not recognized
* @exception IllegalArgumentException if no compiled report definition
* for the specified name can be found
*/
public void jasperReport(String name, String type,
ResultSet data, Map params) {
// Validate that we recognize the report type
// before potentially wasting time filling the
// report with data
boolean found = false;
for (int i = 0; i < VALID_TYPES.length; i++) {
if (VALID_TYPES[i].equals(type)) {
found = true;
break;
}
}
if (!found) {
throw new IllegalArgumentException("Invalid report type '"
+ type
+ "' requested");
}
// Look up the compiled report design resource
ExternalContext econtext = getExternalContext();
InputStream stream = econtext.getResourceAsStream(PREFIX + name
+ SUFFIX);
if (stream == null) {
throw new IllegalArgumentException("Unknown report name '"
+ name
+ "' requested");
}
try {
data.beforeFirst();
} catch (Exception e) {
throw new FacesException(e);
}
// Fill the requested report with the specified data
JRResultSetDataSource ds = new JRResultSetDataSource(data);
JasperPrint jasperPrint = null;
try {
jasperPrint = JasperFillManager.fillReport(
stream, params, ds);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
} finally {
try {
stream.close();
} catch (IOException e) {
;
}
}
// Configure the exporter to be used, along with the custom
// parameters specific to the exporter type
JRExporter exporter = null;
HttpServletResponse response = (HttpServletResponse)
econtext.getResponse();
FacesContext fcontext = FacesContext.getCurrentInstance();
try {
response.setContentType(type);
if ("application/pdf".equals(type)) {
exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
response.getOutputStream());
} else if ("text/html".equals(type)) {
exporter = new JRHtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER,
response.getWriter());
// Make images available for the HTML output
HttpServletRequest request =
(HttpServletRequest)
fcontext.getExternalContext().getRequest();
request.getSession().setAttribute(
ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
jasperPrint);
exporter.setParameter(
JRHtmlExporterParameter.IMAGES_MAP, new HashMap());
// The following statement requires mapping /image
// to the imageServlet in the web.xml.
//
// This servlet serves up images including the px
// images for spacing.
//
// Serve up the images directly so we
// don't incur the extra overhead associated with
// with a JSF request for a non-JSF entity.
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,
request.getContextPath() + "/image?image=");
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
// Enough with the preliminaries ...
// export the report already
try {
exporter.exportReport();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
// Tell JavaServer Faces that no output is required
fcontext.responseComplete();
}
|
java.io.InputStream
appears in the Fully Qualified Name field for the InputStream
class, and that java.sql.ResultSet
appears in the Fully Qualified Name field for the ResultSet
class. In this application, you use the same database query result set for the trip information to display on the web page and in the generated report. You use the Query Editor to design the database query, as shown in the following figure.
![]() Figure 7: Query Editor Settings for the Trip Result Set |
In the NAME row for the TRAVEL.PERSON table in the grid panel, choose Ascending from the drop-down list in the Sort Type column.
The IDE sets the Sort Order to 1.In the DEPDATE row for the TRAVEL.TRIP table in the grid panel, choose Ascending from the drop-down list in the Sort Type column.
The IDE sets the Sort Order to 2.In this section you add a table to Page1 to display the trip data, and you add buttons to generate the report in HTML and PDF formats, as shown in the following figure.
![]() Figure 8: Page1 |
Trips
in the Title text box. View Report
, and press Enter. id
property to viewReportBtn
. action
property, choose viewReportBtn_action from the drop-down list, and click OK. Create PDF
, and press Enter. id
property to createPdfBtn
. action
property, choose createPdfBtn_action from the drop-down list, and click OK. viewReportBtn_action
method.< Add the following code shown in bold to the body of the viewReportBtn_action
method.
Code Sample 4: viewReportBtn_action Method |
public String viewReportBtn_action() {
// Free up the rowset resources
tripDataProvider.close();
Map fillParams = new HashMap();
// The above statement generates warnings with Java SE 1.5
// To eliminate the warnings, replace with the
// following statement:
// Map<String, URL> fillParams =
// new HashMap<String, URL.>>();
try {
fillParams.put
("LogoURL",
getExternalContext().getResource("/resources/images/logo.gif"));
getApplicationBean1().jasperReport
("TripReportByPerson", "text/html",
getSessionBean1().getTripRowSet(), fillParams);
} catch (Exception e) {
log("Exception generating report", e);
error("Exception generating report: " + e);
}
return null;
}
|
Scroll to the createPdfBtn_action
method and add the following code shown in bold.
Code Sample 5: createPdfBtn_action Method |
public String createPdfButton_action() {
// Free up the rowset resources
tripDataProvider.close();
Map fillParams = new HashMap();
try {
fillParams.put
("LogoURL",
getExternalContext().getResource("/resources/images/logo.gif"));
getApplicationBean1().jasperReport
("TripReportByPerson", "application/pdf",
getSessionBean1().getTripRowSet(), fillParams);
} catch (Exception e) {
log("Exception generating report", e);
error("Exception generating report: " + e);
}
return null;
}
|
In the web application, click View Report to view the report in HTML format.
If you see broken images, open web > WEB-INF > web.xml and make sure that the entry for the ImageServlet exists. Sometimes, the IDE does not save the newly added entries.Extensions and MIME Types
property for XML Objects in the Options dialog box to add jrxml to the list of XML objects. By doing so, the IDE will open jrxml files in the XML editor.net.sf.jasperreports.j2ee.servlets.ImageServlet
in the web.xml
file.facesContext.responseComplete( )
to terminate the current request lifecycle.IMAGES_URI
parameter to pass the URI for the ImageServlet class. For example, if you set the URI to /image, set the IMAGES_URI
parameter to request.getContextPath() + "/image?image=".close
method before filling the report.See Also: