Report with ZK : Using JasperReports As an Example

Henri Chen, Principal Engineer, Potix Corporation
November 19, 2007

Introduction

Report is no doubt a required feature in most enterprise applications. In this article, I want to demonstrate the standard practice to handle reports and how to do it with a famous Java opensource report engine, JasperReports, as an example.

The Operation Flow

The operation flow is quite straightforward. you first have the report engine to generate the final report "stream", be it PDF, RTF, or other formats, the stream is then responsed back to an iframe component. The reader/plugin installed on the browser side will then pick up the job and show the report automatically. If there is no proper reader/plugin installed, a browser download window will popup waiting user's decision to download the report stream as a file for you. The following is the figure that shows the flow.

Report in Action

As you might have known, ZK is a server-centric Ajax framework. That means, your application is running on the server side while ZK framework handles the rest for you. Your application can access to the full power of the server and the full resources in the server easily. Your application runs with the report engine in the server side along with the data sources required to generate the report. There is no remote-procedure-call(RPC) hassles and you can call directly any Java libraries in the server side without worrying about security issues.

The Example Code

The following is the example code with the JasperReports engine. I shamlessly "steal" an existing example directly from the JasperReports project and add some little ZK glue codes.


<?page style="height:100%" ?>
<window width="100%" height="100%">
<borderlayout height="100%">
    <north maxsize="24" size="24" border="0">
        <button label="Report!" onClick="doReport()"/>
    </north>
    <center border="none" flex="true">
        <iframe id="report" />
    </center>
</borderlayout>
<zscript><![CDATA[
    import java.io.*;
    import java.sql.*;
    import org.zkoss.util.media.AMedia;
    import net.sf.jasperreports.engine.JasperRunManager;
    void doReport() {
        InputStream is = null;
        try {
            //generate report pdf stream
            is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("FirstJasper.jasper");
                
            final Map params = new HashMap();
            params.put("ReportTitle", "The First Jasper Report Ever");
            params.put("MaxOrderID", new Integer(10500));

            final byte[] buf = 
                JasperRunManager.runReportToPdf(is, params, getConnection());
                
            //prepare the AMedia for iframe
            final InputStream mediais = new ByteArrayInputStream(buf);
            final AMedia amedia = 
                new AMedia("FirstReport.pdf", "pdf", "application/pdf", mediais);
                
            //set iframe content
            report.setContent(amedia);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            if (is != null) {
                is.close();
            }
        }
    }
    private static Connection getConnection() 
    throws ClassNotFoundException, SQLException
    {
        //Change these settings according to your local configuration
        String driver = "org.hsqldb.jdbcDriver";
        String connectString = "jdbc:hsqldb:hsql://localhost";
        String user = "sa";
        String password = "";

        Class.forName(driver);
        Connection conn = DriverManager.getConnection(connectString, user, password);
        return conn;
    }
]]></zscript>
</window>

The concept is simple. The end user request a report by clicking the button and the "onClick" event handler in the application request the JasperReports engine to generate the PDF report stream. The application then pack the stream into a ZK media with proper file extension and mime-type and set it as the content of the iframe component. The application ends here and the rest is done automatically by the ZK framework. It generates an url token and set the url into iframe's src attribute. This causes the iframe in browser side to request a new page from the given new url. The ZK framework then identifies the request and response with the previously prepared PDF stream back. Until this moment, the PDF-reader/plugin installed on the end user's browser side picks up the job and show the stream in the iframe as a PDF document.

Summary

The practice of having the server to render the result and then send it back to iframe is not limited to the PDF stream only. Theoretically, you can have an Excel engine to generate Excel streams, an RTF engine to generate RTF streams, or an AutoCad engine to generate DWG streams. The imagination is the only limit. In fact, the rendering engine can be even not there in your server. You can just request those rendering results from a web service and so on. I think this is the power of a server centric framework like ZK. Because you run your applications in the server, you got the full power of the server and you enjoy all convenience brought by the server-centric architecture.

I wish this example explains the common question asked on forum regarding how to generate report in ZK. Should you have other questions regarding this practice or you think there is a better approach, please do not hesitate in leaving a comment. We love to hear from you.

 

Comments
 
Marcos de Sousa
2007-11-19

Nice. Using *.jasper report is fast than *.jrxml Now show how to duplicate an report (print twice same report) :-). Marcos de Sousa

sten
2008-03-12

How to make .jasper file?

chee chent
2008-04-17

one of the simplest way is to use I-Report.... u can get that tools in sourceforge.net...

if u are not familiar wf it .... try 2 make use of the report wizard to help ya ...


hope this helps :P

Diogo
2008-06-23

Help please!!!

I used this with a datasource jtds to sqlserver, i only get:
java.lang.NullPointerException.

In other examples as well ... the same message...

Kjell
2008-08-08

Hi. Have generated report, but i don't get data from the original report. Can someone help me?

manuel rodriguez
2008-11-05

in
is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("FirstJasper.jasper");

is sendme null....
i working in java ..how can link to jasper file in "/WEB-INF/jsp/asignacion_documentos/classic_landscape.jasper"

this dont work...is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/WEB-INF/jsp/asignacion_documentos/classic_landscape.jasper");

henrichen
2008-11-19

manuel,

In my example, I put the .jasper file in WEB-INF/class path so I use

Thread.currentThread().getContextClassLoader().getResourceAsStream(...)

In your case, you can try following code:

final Execution exec = Executions.getCurrent();
is = exec.getDesktop().getWebApp().getResourceAsStream(
exec.toAbsoluteURI("/WEB-INF/jsp/asignacion_documentos/classic_landscape.jasper", false));

chandra shekher gupta
2009-02-24

If i want to show Xform results in frame,,would it be right idea??

Basically my service will throw Xform that will contain(model,binding and UI)..and rather calling japer report i will throw the XForm results into IFrame.
Please throw some idea..

m rashed
2009-07-15

can i use this component with flex 3 i want to generate report from server side

pfellmann
2009-07-27

is it possible to see a sample of the jrxml that was used to generate the .jasper ? I'm having some troubles with the Parameters and fields when trying to interface my java server with the precompiled .jasper file

Raghavendra
2009-10-19

Hi all,

I need to use Crystal Reports for developing reports with ZK framework. Any inputs in this regard will be appreciated.

Thanks in advance.

Regards,
Raghavendra

 
 
Leave a Reply
 
Name (required)
Mail (will not be published) (required)
Website
(Case Insensitive)
Bold textItalic textUnderLine textSource CodeHorizontal rulerExternal Link
Post
Preview