Showing posts with label Jasper Reports. Show all posts
Showing posts with label Jasper Reports. Show all posts

Images in Jasper Report

After years of struggling with report design (using jasperreports and ireport) for web applications, I finally set up a method for fast development of reports. I was loosing lots of time changing and testing the reports (after each report compilation i had to recompile and redeploy my web application, then to access the web page containing the report).

The ideea: to have the report input in a file, to set it as an xml datasource in iReport and to run the report on real test data in iReport interface.

My environment: java 1.5, iReport 2.0.2 (compatible with JasperReports 2.0.2)





1. Parameter values

First, all report parameters must have a default value, and the “Use as a prompt” option unchecked - so that the default value is used without a confirmation popup window at runtime.

Parameter default value, not for prompt

2. Field values from an xml datasource

To set up an xml datasource, create an xml file like in the example below (the node that is repeating corresponds to a detail line of the report):

<?xml version=”1.0&#8243; encoding=”UTF-8&#8243;?>
<ComandaX>
<Product>
<code>ITEM1001</code>
<description>Descriere produs</description>
<cond>1 buc</cond>
<quant>10</quant>
<unitprice>10.10</unitprice>
<totalprice>1010</totalprice>
<no>1</no>
</Product>

<Product>
<code>ITEM1002</code>
<description>Descriere produs 2</description>
<cond>1 buc</cond>
<quant>20</quant>
<unitprice>20.10</unitprice>
<totalprice>4040</totalprice>
<no>2</no>
</Product>
</ComandaX>

Then in iReport, add an xml datasource with the expression /ComandaX/Product (corresponding to the xml above - the path to the node that is repeating):

xml datasource

For this to work and the report to be filled with data, you must also fill for each field the description (the field description must match the field name):

field description

3. Path to images

A trick is necessary to see report resources both in iReport and in production environment. For a web application, a resource loaded from classpath is named relatively, for instance: “/../../resources/logo.jpg” (always with a leading slash). In iReport environment the path to the image can not contain a leading slash (for instance “/opt/resources/logo.jpg”. One solution: to define a report parameter that has default value “/opt/resources/logo.jpg” (used in iReport) and initialized in production environment with another value (for instance “/../../resources/logo.jpg”), and to set the image path using this parameter.

4. Enjoy!

Set the datasource created above as the default datasource and run the report (Execute with active connection). Report changes will take seconds, report designs will only take minutes :) Also, it is much easier to test multiple cases (larger reports for instance), and to develop reports independently (in time, resources) than the rest of the application.

Full example (report template, pdf report, xml datasource)


Click here to View more...

JasperReport API Diagram

http://confluence.atlassian.com/download/attachments/150050/jasper_reports_design_summary.png

Rt click --> View Image (To Enlarge)
Click here to View more...

Run a Jasper Report from Java

This mini-tutorial shows you how to run a report (Jasper Report) from Java code. To run a Jasper Report from Java code you need the following Jasper Report libraries (jar files):

  • jasperreports-1.2.0.jar,
  • commons-beanutils-1.5.jar,
  • commons-collections-2.1.jar,
  • commons-digester-1.7.jar,
  • commons-logging-1.0.2.jar.

You can find these libraries inside the lib directory of the iReport-1.2.0 installation. (For instance, if you have installed iReport in the C:\Courses\CIS4301\ReportGenerator\iReport-1.2.0 directory, you can find these libraries in C:\Courses\CIS4301\ReportGenerator\iReport-1.2.0\lib directory. For information on how to install iReport check this page.)

You also need the oracle JDBC library (classes12.jar file) to connect to the database. You need to put these files into your Java CLASSPATH.

The following Java code uses a Jasper Report design (reportFile paramater) and fills the report with data from database and views the report. An example of a Jasper Report is given here.


public static void runReport(String databaseName, String userName, String password,String reportFile) {
try{
JasperDesign jasperDesign = JRXmlLoader.load(reportFile);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
Connection jdbcConnection = connectDB(databaseName, userName, password);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, jdbcConnection);
JasperViewer.viewReport(jasperPrint);
}catch(Exception ex) {
String connectMsg = "Could not create the report " + ex.getMessage() + " " + ex.getLocalizedMessage();
System.out.println(connectMsg);
}
}


The complete Java Class code is as the following: ReportDriver.java

You can use ReportDriver.java as a driver program from other Java classes as well. Here is an example.

import java.sql.*;
import net.sf.jasperreports.view.JasperViewer;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.JasperReport;
import java.io.OutputStream;

/**
* Driver program to connect to a database and to view a jasper report (.jrxml)
* @author @miT
* @since
*
* Required jar files to run this class:
* 1. jasperreports-1.2.0.jar
* 2. classes12.jar (for Oracle JDBC connection)
* 3. commons-beanutils-1.5.jar
* 4. commons-collections-2.1.jar
* 5. commons-digester-1.7.jar
* 6. commons-logging-1.0.2.jar
*
*/

public class ReportDriver {

/**
* Constructor for ReportDriver
*/
public ReportDriver() {
}

/**
* Takes 3 parameters: databaseName, userName, password
* and connects to the database.
* @param databaseName holds database name,
* @param userName holds user name
* @param password holds password to connect the database,
* @return Returns the JDBC connection to the database
*/
public static Connection connectDB(String databaseName, String userName, String password) {
Connection jdbcConnection = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
jdbcConnection = DriverManager.getConnection(databaseName,userName,password);
}catch(Exception ex) {
String connectMsg = "Could not connect to the database: " + ex.getMessage() + " " + ex.getLocalizedMessage();
System.out.println(connectMsg);
}
return jdbcConnection;
}

/**
* Takes 4 parameters: databaseName, userName, password, reportFileLocation
* and connects to the database and prepares and views the report.
* @param databaseName holds database name,
* @param userName holds user name
* @param password holds password to connect the database,
* @param reportFile holds the location of the Jasper Report file (.jrxml)
*/
public static void runReport(String databaseName, String userName, String password,String reportFile) {
try{
JasperDesign jasperDesign = JRXmlLoader.load(reportFile);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
Connection jdbcConnection = connectDB(databaseName, userName, password);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, jdbcConnection);
JasperViewer.viewReport(jasperPrint);
}catch(Exception ex) {
String connectMsg = "Could not create the report " + ex.getMessage() + " " + ex.getLocalizedMessage();
System.out.println(connectMsg);
}
}

/**
* Uses runReport method to connect to the database and to prepare and view the report.
* @param args Takes 4 arguments as an input: databaseName, userName, password, reportFileLocation
* args[0] holds database name,
* args[1] holds user name
* args[2] holds password to connect the database,
* args[3] holds the location of the Jasper Report file (.jrxml)
*/
public static void main(String[] args) {
if (args.length == 4) {
String databaseName = args[0] ;
String userName = args[1];
String password = args[2];
String reportFile = args[3];
runReport(databaseName, userName, password, reportFile);
}else{
System.out.println("Usage:");
System.out.println("java ReportDriver databaseName userName password reportFileLocation");
}
return;
}
}

A batch file that compiles the above Java Class is like the following (Please note that all the library classes are placed inside the javaLib directory under the current working directory) :

javac -classpath .;javaLib\classes12.jar;javaLib\jasperreports-1.2.0.jar ReportDriver.java
pause

A batch file that runs the ReportDriver Java class is like the following (Again, please note that all the library classes are placed inside the javaLib directory under the current working directory):

REM first parameter is your Oracle connection string. For instance, jdbc:oracle:thin:@oracle1.cise.ufl.edu:1521:orcl
REM second parameter is your Oracle database user name
REM third parameter is database password
REM fourth parameter is report file location. For instance, C:\Courses\CIS4301\WEBPAGE\ReportDemo\jrTemplate\YourUFID_1.jrxml
java -cp .;javaLib\classes12.jar;javaLib\jasperreports-1.2.0.jar;javaLib\commons-digester-1.7.jar;javaLib\commons-collections-2.1.jar;javaLib\commons-logging-1.0.2.jar;javaLib\commons-beanutils-1.5.jar ReportDriver %1 %2 %3 %4
pause

Here is an image showing how I run the above batch file:

This is the report I get after running my Jasper Report template:

For Jasper Report API: http://jasperreports.sourceforge.net/api/index.html

For commons library API: http://jakarta.apache.org/commons/




Click here to View more...

iReports and JasperReports

Intro

Crystal Reports® from Business Objects SA has been a popular business reporting solution for many years. However, the licensing costs and lack of Linux support has led many report developers to look for an alternative open source solution.

In this article we will show you how to write reports using MySQL as the database, JasperReports as the engine, iReport as the designer and a Java servlet to serve reports as PDF documents from Tomcat.

JasperReports

The JasperReports engine is just that: a report engine. Tools from other providers are used to design the report content and layout. This approach gives the report developer flexibility in assembling a reporting toolbox that far exceeds the flexibility offered by traditional one-size-fits-all reporting tools. It is also possible to edit the report definition files by hand for the ultimate in customization.

Use the checklist below to assist you with installing required libraries and components for an end-to-end JasperReports development environment.

Setup Checklist

Complete Description How to get it What to do
Java 1.4.2 SDK (SDK required as iReport uses tools.jar) Download J2SE 1.4.2 from java.sun.com. Install to local hard drive. (The directory created by the installer is called below.)
iReports Download iReport-0.4.1.zip from Sourceforge. Extract to C:\Program Files\. (This directory is called below.)
tools.jar Located on your machine in the /lib/ directory created by Java 1.4.2 SDK installer. Copy this file to your /lib/ directory.

iReports

Starting iReport for the first time

To start iReport for the first time, simply execute the provided startup script. iReport provides two such scripts: startup.bat for Windows and startup.sh for Unix-like OSes, both of which are located in the /bin/ directory. When iReport starts, it will display directory information in the output pane. You will see something similar to:

iReport home (ireport.home system property):.

User home ( user.home system property): C:\WINNT\Profiles\yourusername\.ireport.

iReport default compile directory: D:\temp.

iReport user home directory (iReport compiles here if there are no settings or the user hasn't selected to compile to the report directory):.

Compiler Options

To change the compile directory select "Tools/Options..." from the menu and click the "Compiler" tab. For our example, we chose to compile reports to the same directory as the report definition files.




Preparing the Database

Of course, our report is useless without a source of data with which to populate it. For this, we'll be using a MySQL database accessed via JDBC.

The first step, of course, is creating the database. Since this is just an example app, we'll also insert the data during this step. Click here to download a text file containing the commands used to create and populate the database. Once the DB is up and populated, it's time to set up a way for our report to access it.

Since this webapp is going to be served by Tomcat, we should take advantage of Tomcat's connection management. To do so, we'll define a DataSource as a JNDI resource in the application's context. The document fragment below is the context.xml the sample app uses.

01 <Context path="/jasper_example" docBase="jasper_example" debug="5" reloadable="true"
02 crossContext="true">
03 <Resource name="jdbc/jasper_example" auth="Container" type="javax.sql.DataSource" />
04 <ResourceParams name="jdbc/jasper_example">
05 <parameter>
06 <name>factory</name>
07 <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
08 </parameter>
09 <!-- MySQL Server DB username and password for DB connections -->
10 <parameter>
11 <name>username</name>
12 <value>username</value>
13 </parameter>
14 <parameter>
15 <name>password</name>
16 <value>password</value>
17 </parameter>
18 <!-- Class name for the JDBC driver -->
19 <parameter>
20 <name>driverClassName</name>
21 <value>com.mysql.jdbc.Driver</value>
22 </parameter>
23 <!-- The JDBC connection url for connecting to your MySQL Server DB. -->
24 <parameter>
25 <name>url</name>
26 <value>jdbc:mysql://127.0.0.1/jasperarticle</value>
27 </parameter>
28 <!-- maximum active connections -->
29 <parameter>
30 <name>maxActive</name>
31 <value>3</value>
32 </parameter>
33 <!-- maximum idle connections -->
34 <parameter>
35 <name>maxIdle</name>
36 <value>3</value>
37 </parameter>
38 <!-- connections attempts timeout after 10 seconds -->
39 <parameter>
40 <name>maxWait</name>
41 <value>10000</value>
42 </parameter>
43 </ResourceParams>
44 </Context>

Creating a New Report

Create a Database Connection

To create a new data source to use in your report select "Datasource" from the iReport menu bar, then "Connections / Datasources". Click the "New" button and select "Database JDBC connection" from the first dropdown list. If connecting to a MySQL database, select the com.mysql.jdbc.Driver JDBC Driver. After completing the connection parameters, you should have a JDBC URL similar in form to: jdbc:mysql://192.168.1.100/NameOfYourDB.

If when you test your connection you receive an error dialog with the following message, "Communication link failure: java.io.IOException, underlying cause: Unexpected end of input stream", you should update your MySQL JDBC driver. The latest driver can be found at: http://www.mysql.com/products/connector/j/.

The MySQL driver that ships with iReport does not seem compatible with version 4.1 of MySQL.

At the time of this writing, mysql-connector-java-3.1.8a.zip was the latest production-ready archive available for download. Inside this Zip file, you will find a file named mysql-connector-java-3.1.8-bin.jar; copy this file into the iReport/lib directory, e.g., C:\Program Files\iReport-0.4.1\lib\, and delete any older versions, such as mysql-connector-java-3.0.8-stable-bin.jar.

When iReport starts, it will automatically load all .jar files found in the \lib directory. Restart iReports and test your new Datasource connection.

Creating a New Report File

To create a new report select "File / New Document" from the menu bar. Name the report and select your desired paper size. Do not use spaces in the report name. Next, you will need to set the active database connection in order to use values from your database queries. To do this, select "Build / Set active connection" from the menu and choose the connection defined earlier.

Add Fields From Database Table

First, define a query. Select "Datasource / Report query" from the menu bar; this will open the query dialog where we will create a select query to return values to our report. Enter the following: SELECT ID, Name, Address, City, PostalCode FROM Customer. Note: Explicitly select columns, otherwise only non-null columns will appear in the Report Fields selection dialog.

As you type this query, iReport will attempt to execute the query as you type. Note: You may see exception messages while typing, this is normal behavior and is a way to let you know when the query is malformed. When a parsable query has been entered, iReport will display a list of returned columns beneath the query edit window.

Query Window

To add database fields to the report, select "View / Report Fields". This will open a dialog with a list of fields returned by the SQL query.

Query Window

Drag from the Field name grid column into the "detail" section of the report canvas. You should now have something like this:

Query Window

To test the report, select "Build / Execute report (using active conn.)" from the menu bar. The status window in iReport should display something similar to:

Compiling to file... JasperReports\Simple.jasper -> ...\TestReport.java

Compilation running time : 300

Filling report... jrviewerExporting

Viewing with JasperReports Viewer

Running time : 600

Modifying the Report

Filter Results

Next we'll look at filtering the results returned by our SQL query. iReport allows the designer to add parameters to the report that can be used to filter the SQL results. To add a parameter select "View / Report Parameters" and then click New.

For this example, we defined a parameter with the following values:

parameter dialog

To add a where condition filter, open the query edit dialog ("Datasource / Report query"). We'll modify the SQL statement to look like: SELECT ID, Name, Address, City, PostalCode FROM Customer WHERE Name Like '$P!{NameFilter}%'. If we had hard coded the WHERE condition, it might look like: WHERE Name Like 'ABC%'. To insert the parameter value we replace ABC with $P!{NameFilter}. When the report runs, $P!{NameFilter} will be replaced with the supplied actual value.

Serving JasperReports From a Web Server Using Tomcat

The next thing we will look at is serving our report from a webserver using the Apache Tomcat webserver / servlet container. Installing and configuring Tomcat is beyond the scope of this article. The official Tomcat site can be found at http://jakarta.apache.org/tomcat/index.html.


Setting up the Webapp

Now that we have a report to serve and a database set up to populate our report with data, we just need a web component to serve up the report. That component will be a servlet, so we'll also need a web.xml file so Tomcat will know which requests should be handled by the servlet.

The document below is the web.xml file for the sample application. It is fairly straightforward:

  • it describes the servlet that will be serving the report; we will visit this servlet in more detail in the next section
  • it maps that servlet to handle requests coming to the /ReportEngine path; this could be a regular expression, but we have no need of such complications for this application
  • it sets sessions to time out after 30 minutes
  • it tells the servlet container to use welcome.html as the default page for this webapp's virtual directory
  • it references the jdbc/jasper_example JNDI resource we defined in the previous section
01 <?xml version="1.0" encoding="ISO-8859-1"?>
02 <!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 03 'http://java.sun.com/dtd/web-app_2_3.dtd'>
04 <web-app id="AgreeMgtSys_WebApp">
05 <display-name>jasper_example WAR</display-name>
06 <description>WAR file containing all web pages and servlets.</description>
07 <servlet>
08 <servlet-name>ReportEngine</servlet-name>
09 <display-name>Report Engine</display-name>
10 <description>The servlet that handles requests to display a 11 Jasper report.</description>
12 <servlet-class>com.skillfusion.articles.jasper.ReportEngine</servlet-class>
13 </servlet>
14 <servlet-mapping>
15 <servlet-name>ReportEngine</servlet-name>
16 <url-pattern>/ReportEngine</url-pattern>
17 </servlet-mapping>
18 <session-config>
19 <session-timeout>30</session-timeout>
20 </session-config>
21 <welcome-file-list>
22 <welcome-file>default.html</welcome-file>
23 </welcome-file-list>
24 <resource-ref>
25 <description>DB Connection</description>
26 <res-ref-name>jdbc/jasper_example</res-ref-name>
27 <res-type>javax.sql.DataSource</res-type>
28 <res-auth>Container</res-auth>
29 </resource-ref>
30 </web-app>
Now that we've got the webapp set up properly, let's see how the servlet is actually performing its task.

Serving the Report

Serving JasperReports From a Web Server Using Tomcat

The next thing we will look at is serving our report from a webserver using the Apache Tomcat webserver / servlet container. Installing and configuring Tomcat is beyond the scope of this article. The official Tomcat site can be found at http://jakarta.apache.org/tomcat/index.html.

Once you have Tomcat up and running, it's time to write the servlet: ReportEngine.

001 package com.skillfusion.articles.jasper.example.servlets;
002
003 import java.io.IOException;
004 import java.io.PrintWriter;
005 import java.sql.Connection;
006 import java.sql.SQLException;
007 import java.util.HashMap;
008
009 import javax.naming.Context;
010 import javax.naming.InitialContext;
011 import javax.naming.NamingException;
012 import javax.servlet.ServletException;
013 import javax.servlet.ServletOutputStream;
014 import javax.servlet.http.HttpServlet;
015 import javax.servlet.http.HttpServletRequest;
016 import javax.servlet.http.HttpServletResponse;
017 import javax.sql.DataSource;
018
019 import net.sf.jasperreports.engine.JRException;
020 import net.sf.jasperreports.engine.JasperExportManager;
021 import net.sf.jasperreports.engine.JasperFillManager;
022 import net.sf.jasperreports.engine.JasperPrint;
023
024 /**
025 * The <code>ReportEngine</code> class serves html and pdf reports using
026 * Jasper reports.
027 *
028 * @author SkillFusion
029 */
030 public class ReportEngine extends HttpServlet {
031 /**
032 * Called by the server to allow a servlet to handle a GET request.
033 *
034 * @param request
035 * the request the client has made of the servlet
036 * @param response
037 * the response the servlet sends to the client
038 * @throws ServletException
039 * @throws IOException
040 */
041 public void doGet(HttpServletRequest request, HttpServletResponse response)
042 throws ServletException, IOException {
043
044 // Pass this request off to the handleSubmit method. It's an accepted
045 // best pracice to handle GET and POST submissions the same way unless
046 // there's a good reason not to do so.
047 this.handleSubmit(request, response);
048
049 }
050
051 /**
052 * Called by the server to allow a servlet to handle a POST request.
053 *
054 * @param request
055 * the request the client has made of the servlet
056 * @param response
057 * the response the servlet sends to the client
058 * @throws ServletException
059 * @throws IOException
060 */
061 public void doPost(HttpServletRequest request, HttpServletResponse response)
062 throws ServletException, IOException {
063 // Pass this request off to the handleSubmit method. It's an accepted
064 // best pracice to handle GET and POST submissions the same way unless
065 // there's a good reason not to do so.
066 this.handleSubmit(request, response);
067 }
068
069 /**
070 * Handles form submissions for <code>#doGet</code> and
071 * <code>#doPost</code>.
072 *
073 * @param request
074 * The <code>HttpServletRequest</code> wrapping the HTTP
075 * request that triggered this method.
076 * @param response
077 * The <code>HttpServletResponse</code> that gives this method
078 * access to the HTTP response the servlet container will send
079 * back to the user agent.
080 * @throws IOException
081 * when an error occurs while trying to access the output stream
082 * to notify the user of an error.
083 */
084 protected void handleSubmit(HttpServletRequest request,
085 HttpServletResponse response) throws IOException {
086 // Declare the printwriter (which we'll use if an error occurs), but
087 // don't instantiate it yet because instantiating it will prevent us
088 // from streaming the PDF back to the client if everything else works.
089 PrintWriter out = null;
090
091 Connection conn = null;
092 try {
093 // Get a JDBC Connection
094 Context initContext = new InitialContext();
095 DataSource dataSource = (DataSource) initContext
096 .lookup("java:comp/env/jdbc/jasper_example");
097 conn = dataSource.getConnection();
098
099 // Get report file name from params
100 String rptfilename = request.getParameter("rptfilename");
101
102 // get the name filter
103 String namefilter = request.getParameter("NameFilter");
104
105 // Add filter value to a hashtable of report parameters
106 HashMap params = new HashMap();
107 params.put("NameFilter", namefilter);
108 params.put("testing", "some stuff");
109
110 // fill the report
111 JasperPrint jasperprint = JasperFillManager.fillReport(
112 getServletContext().getRealPath("/") + rptfilename, params,
113 conn);
114
115 // export report to pdf and stream back to browser
116 byte[] pdfasbytes = JasperExportManager
117 .exportReportToPdf(jasperprint);
118
119 ServletOutputStream outstream = response.getOutputStream();
120 response.setContentType("application/pdf");
121 response.setContentLength(pdfasbytes.length);
122
123 response.setHeader("Content-disposition",
124 "inline; filename=\"Report.pdf\"");
125 outstream.write(pdfasbytes);
126
127 } catch (NamingException ne) {
128 // Get the writer from the response so we can output markup
129 out = response.getWriter();
130
131 // There was a problem, either in retrieving the initial context, or
132 // looking for a specific JNDI resource inside that context. Either
133 // way, let the user know.
134 out.println("<html>");
135 out.println("\t<body>");
136 out.println("\t\t<br /><br />");
137 out.println("\t\tDue to a naming problem with this servlet's"
138 + "initial context, the system is unable to display"
139 + "the report at this time.");
140 out.println("\t\t<br /><br />");
141 out.println("\t\tError Message ==> " + ne.getLocalizedMessage());
142 out.println("\t\t<br />");
143 out.println("\t\tCause of Error ==> " + ne.getCause());
144 out.println("\t</body>");
145 out.println("</html>");
146 } catch (SQLException sqle) {
147 // Get the writer from the response so we can output markup
148 out = response.getWriter();
149
150 // Start the html, but don't fill in the juicy bits yet
151 out.println("<html>");
152 out.println("\t<body>");
153
154 // SQLExceptions can be chained. We have at least one exception, so
155 // set up a loop to make sure we let the user know about all of them
156 // if there happens to be more than one.
157 SQLException tempException = sqle;
158 while (null != tempException) {
159 // work
160 // Write out the useful info on this exception to the response
161 out.println("\t\t<br /><br />");
162 out.println("\t\tThe following database error occurred:");
163 out.println("\t\t<br /><br />");
164 out.println("\t\tError Message ==> "
165 + sqle.getLocalizedMessage());
166 out.println("\t\t<br />");
167 out.println("\t\tCause of Error ==> " + sqle.getCause());
168 out.println("\t\t<br />");
169 out.println("\t\tSQL State ==> " + sqle.getSQLState());
170 out.println("\t\t<br />");
171 out.println("\t\tVendor Error Code ==> " + sqle.getErrorCode());
172
173 // loop to the next exception
174 tempException = tempException.getNextException();
175 }
176
177 // Write out the closing tags to the response
178 out.println("\t</body>");
179 out.println("</html>");
180 } catch (JRException jre) {
181 // Get the writer from the response so we can output markup
182 out = response.getWriter();
183
184 // Jasper had an internal error when filling the report. Give the
185 // user the lowdown.
186 out.println("<html>");
187 out.println("\t<body>");
188 out.println("\t\t<br /><br />");
189 out.println("\t\tJasper encountered a problem when attempting"
190 + "to populate the report.");
191 out.println("\t\t<br /><br />");
192 out.println("\t\tError Message ==> " + jre.getLocalizedMessage());
193 out.println("\t\t<br />");
194 out.println("\t\tCause of Error ==> " + jre.getCause());
195 out.println("\t</body>");
196 out.println("</html>");
197 } catch (IOException ioe) {
198 // Get the writer from the response so we can output markup
199 out = response.getWriter();
200
201 // This was an IO error, so it quite possibly resulted from an error
202 // creating the print writer, but we're still gonna give it the old
203 // college try and attempt to send back useful info to the user
204 out.println("<html>");
205 out.println("\t<body>");
206 out.println("\t\t<br /><br />");
207 out.println("\t\tDue to a naming problem with this servlet's"
208 + "initial context, the system is unable to display"
209 + "the report at this time.");
210 out.println("\t\t<br /><br />");
211 out.println("\t\tError Message ==> " + ioe.getLocalizedMessage());
212 out.println("\t\t<br />");
213 out.println("\t\tCause of Error ==> " + ioe.getCause());
214 out.println("\t</body>");
215 out.println("</html>");
216 } finally {
217 try {
218 // We're done here, so clean up the connection
219 conn.close();
220 } catch (SQLException sqle) {
221 // We don't actually care, we were just trying to clean up an
222 // expensive DB connection
223 }
224 }
225 }
226 }


Java2html

Best practices tell us that when the doGet and doPost methods exhibit the same behavior, they should delegate the implementation of that behavior to a helper method. In keeping with that ideal, all the actual work in this servlet is done in the handleSubmit method, which is called by both doGet and doPost.

Inside handleSubmit, we establish a JDBC database connection by looking up a JNDI resource named jdbc/jasper_example, which defines the DataSource for our JDBC connection. Once the connection has been established, handleSubmit begins pulling required information out of the HttpRequest's parameters. Once all the necessary info has been extracted from the HttpRequest and pushed into a Map of parameters, handleSubmit makes a call to JasperFillManager.fillReport. Next, we pass the results of that call to JasperExportManager.exportReportToPdf to convert the report to PDF format. Once that's done, it's a simple matter to write the resulting document back to the HttpResponse as an array of bytes.

To try it out, you can just invoke the deploy target of the Ant buildfile shipped with the sample application. It uses standard Ant targets, along with a few targets provided by Tomcat, to compile the whole webapp into a standard WAR file and deploy it into the servlet container. After that, you should be able to serve up PDF reports using an open-source solution based on Jasper Reports and iReport.

Conclusion

Creating reports with JasperReports technology provides a powerful alternative to closed source business reporting solutions. The benefits of open source, server portability and attractive pricing, makes JaserReports solutions a viable contender for most business reporting efforts.

             

Click here to View more...

Getting Started With JasperReports

Intro :
JasperReports is a very popular open source (LGPL) reporting library written in Java. Unfortunately it is not very well documented and I had a hard time coming up with a simple report. After some research, I was able to generate a simple report, this article summarizes what needs to be done to get started with JasperReports. See Resources for information on how to find additional information and documentation about JasperReports.



Getting Started

JasperReports' reports are defined in XML files, which by convention have an extension of jrxml. A typical jrxml file contains the following elements:

* <jasperReport> - the root element.
* <title> - its contents are printed only once at the beginning of the report
* <pageHeader> - its contents are printed at the beginning of every page in the report.
* <detail> - contains the body of the report.
* <pageFooter> - its contents are printed at the bottom of every page in the report.
* <band> - defines a report section, all of the above elements contain a band element as its only child element.

All of the elements are optional, except for the root jasperReport element. Here is an example jrxml file that will generate a simple report displaying the string "Hello World!"


<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<jasperReport name="Simple_Report">
<detail>
<band height="20">
<staticText>
<reportElement x="180" y="0" width="200" height="20"/>
<text><![CDATA[Hello World!]]></text>
</staticText>
</band>
</detail>
</jasperReport>


For this simple example, I omitted the optional <title>, <pageHeader> and <pageFooter> elements. The <staticText> element, unsurprisingly, displays static text on the report, as can be seen, it contains a single <text> element defining the text that will be displayed.

jrxml files need to be "compiled" into a binary format that is specific to JasperReports, this can be achieved by calling the compileReport() method on the net.sf.jasperreports.engine.JasperCompileManager class. There are several overloaded versions of this method, in our example, we will use the one that takes a single String parameter, consult the JasperReport documentation for details on the other versions of the method.
public class JasperReportsIntro
{
public static void main(String[] args)
{
JasperReport jasperReport;
JasperPrint jasperPrint;
try
{
jasperReport = JasperCompileManager.compileReport(
"reports/jasperreports_demo.jrxml");
jasperPrint = JasperFillManager.fillReport(
jasperReport, new HashMap(), new JREmptyDataSource());
JasperExportManager.exportReportToPdfFile(
jasperPrint, "reports/simple_report.pdf");
}
catch (JRException e)
{
e.printStackTrace();
}
}
}


A jrxml file needs to be compiled only once, but for this simple example it is compiled every time the application is executed. Before a report can be generated, it needs to be "filled" with data, this is achieved by calling the fillReport() method on the net.sf.jasperreports.engine.JasperFillManager class. Again, there are several overloaded versions of the fillReport() method, here we will use one that takes three parameters, an instance of net.sf.jasperreports.engine.JasperReport, a java.util.HashMap containing any parameters passed to the report, and an instance of a class implementing the net.sf.jasperreports.engine.JRDataSource interface. The line that accomplishes this in our example above is

jasperPrint = JasperFillManager.fillReport( jasperReport, new HashMap(), new JREmptyDataSource()); Since our simple report takes no parameters, we pass an empty HashMap as the second parameter, and an instance of net.sf.jasperreports.engine.JREmptyDataSource as the third parameter. JREmptyDataSource is a convenience class included with JasperReports, it is basically a DataSource with no data.

Finally, in our example, we export the report to a PDF file, this way it can be read by Adobe Acrobat, XPDF, Evince, or any other PDF reader, the line that accomplishes this in our example is

JasperExportManager.exportReportToPdfFile(
jasperPrint, "reports/simple_report.pdf");
The parameters are self-explanatory.

Conclusion

JasperReports is a very good and popular open source reporting engine, this guide provides enough information to get started with JasperReports.
       


Click here to View more...

JasperReports Library

The table below list all the configuration properties available for the JasperReports library:

Data Source / Query Executer
Report Compilation
Report Filling



Report Export
Other


Click here to View more...

JRE JDK and JasperReport

Although it was clear to me what happened immediately as I saw stacktrace, I was surprised that it didn't came to my mind during development. One of the tasks I had was to create report in the very simple application. As I wasn't sure about structure of the report and all the fields that should appear in the report I have decided to use jrxml file. jrxml file is XML definition of report and to display it you have to compile it during runtime. The code to do this is actually very simple:

JasperReport report = JasperCompileManager.compileReport("report.jrxml");
When you have instance of the report it is enough to use JasperFillManager to fill it with data.Another possibility is to compile jrxml file to jasper report. This will generate jasper, binary version of the report. When you have compiled report of course you don't have to compile it during runtime.Well, more or less I had XML version of the report, created installation using Null Soft installer, installed it on my computer and everything worked fine. I could create domain objects and display and print reports. So I was happy and delivered the installation to customer (in this case my mom). She installed application without problems, entered necessary data and tried to open report. And then to my surprise report didn't opened but there was message about unexpected error. As soon as I saw the stacktrace it was clear that actually she does not have java installed with JDK but as JRE.And of course JRE is not delivered with compiler and therefore application was not able to compile report. As soon as I changed application to read compiled report everything worked fine. So if you plan to deliver Java application to standard user computers, don't forget to test application on computers where only JRE is installed.
Click here to View more...

Jasper Report - Do's Don'ts

r

Table of Contents

1. Introduction. 4

1.1. Purpose of this document. 4

1.2. Audience.. 4

1.3. Usage.. 4

2. Tools & Technology. 4

2.1. JasperReports. 4

2.2. Purpose.. 4

2.3. Reference to technical managers. 4

2.4. Configuration and setup.. 5

2.5. Technical references. 5

2.6. Implementation Guidelines. 5

2.6.1. Do’s. 5

2.6.2. Don’ts. 5

2.7. Problems / Issues Faced.. 5

2.8. Learning’s. 5


1. Introduction


2. Tools & Technology

2.1. JasperReports

Parameter

Details

Vendor

JasperSoft

Version

2.0.2

Platform

Java & JRE 1.3 or higher

Specific Pre-requisite

Familiarity with Java programming, XML & SQL

Fixes Details


2.2. Purpose

JasperReports is a very powerful and flexible open source report-generating tool that delivers rich content to the screen, printer, or file in PDF, HTML, RTF, XLS, ODT, CSV, or XML format.

The library is written entirely in Java and can be used in a variety of Java-enabled applications, including J2EE or web applications, to generate dynamic content. Its main purpose is to help to create page-oriented, ready-to-print documents in a simple and flexible manner.

2.3. Reference to technical managers

User Interaction Manager

2.4. Configuration and setup

JasperReports is a content-rendering library, not a standalone application. It cannot run on its own and must be embedded in another client- or server-side Java application. JasperReports is a pure Java library and can be used on any platform that supports Java.

All JasperReports functionality is concentrated in a single JAR file, jasperreports-x.x.x.jar. Even though all its reporting functionality is available in this single JAR file, JasperReports relies on other third-party libraries for related required functionality like XML parsing, logging, and PDF and XLS generation.

Include following jars in the classpath to obtain report in HTML And PDF:

1. jasperreport-2.0.2.jar

2. jdt-compiler-3.1.1

3. commons-beanutils-1.7

4. commons-collections-2.1

5. commons-logging-1.0.2

6. commons-logging-api-1.0.2

7. commons-javaflow-20060411

8. commons-digester-1.7

9. itext-1.3.1

2.5. Technical references

Books:

1. JasperReports For Java Developers.

2. The Definitive Guide to JasperReports.

Read the Followings links to get a better idea on Jasper Reports

1. http://jasperreports.sourceforge.net.

2. http://sourceforge.net/projects/jasperreports.

3. http://www.regdeveloper.co.uk/2006/10/24/jasperreports_tutorial/

4. http://www.devx.com/Java/Article/29309/1954?pf=true

5.

2.6. Implementation Guidelines

2.6.1. Do’s

1 While developing a Web Based Application create a folder named report under WEB-INF and place all jasperreport template files (.jrxml).

2. Place all jar files listed above in WEB-INF\lib folder.

3. Step to generate Report

1. Load Xml File (.jrxml).

2. Compile the report template to generate the complied code (.jasper) of report.

3. Fill Report (Pass the Complied file).

4. Export Report to generate report in the required format (HTML/ PDF) using appropriate API methods.

4. Same JasperPrint Object can be used to generate report in multiple formats so

that repeated data access is not required.

5. Avoid writing direct queries in the report template instead pass Object,

ArrayList, Collection or Array of Bean.

2.6.2. Don’ts

1. No event handling mechanisms in jasper reports.

2. Nesting expression tags used in the jrxml file is not possible (E.g.: Can

VariableExpression tag be nested within TextFieldExpression tag)

2.7. Problems / Issues Faced

1. While developing a Portlet Project do not include common-logging-1.0.2.jar, common-logging-api-1.0.2.jar under WEB-INF/lib. Websphere internally uses its own logging framework.

2. StyleSheet can be included in jasper report but there are certain problems encountered.

1. When we execute the report there are certain default setting for font and font size, so these setting are included in the report as inline style. Thus, the resultant effect of external stylesheet does not get reflected onto the report.

2. There isn't any direct solution to use classes defined in stylesheet. Some forum suggests making changes in the DTD of jasper report and then extending the class related to it.

3. No proper documentation is available.

2.8. Learning’s

1. Be careful in writing report template file since it is entirely written in xml.

2. Avoid overlapping bands of different section.

3. Using simple API functions we can generate report HTML\PDF.

4. Data Source : Data used to populate a report may be supplied either as input parameters from a parent application, or a from a data source defined within JasperReports. JasperReports includes JDBC-wrapped data providers for Relational Databases (RDBMS), JavaBeans (EJB, Hibernate), plain old Java objects (POJO), and XML data sources. A single report may use data from multiple data sources, which may be of different types.

5. Drill Down Analysis: Reports can contain hyperlinks, enabling you to create OLAP - style drill-down reports. These allow users to see a high level view of the data and drill-through to areas of interest. This feature can also be used to create a clickable table of contents for fast and easy access to report sections.

6. Internationalization: JasperReports provide support for internationalization provided by the Java platform, including locales. It supports all world languages via Unicode (UTF-8), and also supports other native encodings, such as ISO-8859-1 (Latin 1) for Western European languages. It also supports internationalization via resource files. As a result, a given report may be displayed in different languages and formatted for different locales.

7. Dynamic Query: There are various ways to achieve this. eg. Subreport, Crosstab, passing parameters to the report, we can even integerate hibernate with jasper report to achieve this.

8. Passing values to Servlet from jasper report can be achevied using Query String Parameter.

9. Pagination Scheme can be used incase of large reports

2.8 Limitations Of Jasper Report

1. Application exits when closing the JasperViewer frame:

An application terminates when we close the report viewer frame because JasperViewer class makes call to the System.exit(0). To get around this use the constructor that allows you to set the isExitOnClose to “false” or create your own viewer that uses the more visual basic component implemented by the JRViewer class.[update]

2. Can not use the && logical operator in report expression:

Because the ‘&’ character is a special XML character and the XML

parser is confused when it encounters such characters in the body of

XML element. The solution is to use the XML special syntax that allows

you to introduce XML special characters in the body of an XML element

Put your expression content between the character

Sequences like in the following demo text field expression.

               
                                       
                        
            

2. Returning values from SubReport:

There was no easy way to return to a master report values that were calculated inside a subreport. A new tag is available at

subreport level and enable users to map master report variables to

subreport variables and also specify the way the returned value should be handled(used in calculation or just copied).

Click here to View more...