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.