Search code examples
javaservletsherokujasper-reports

Jasper report on heroku in a jsf app


I am working in an application that uses jasperreports. It uses Primefaces with Mojarra, and is deployed in Jetty. When I deploy the app locally, it does work ok. But when I deploy in heroku it is not working.

When I deploy it to heroku I obtain:

HTTP ERROR 500

Problem accessing /clients.pdf. Reason:

Server Error Caused by:

java.lang.NullPointerException at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2310) at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2323) at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2794) at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801) at java.io.ObjectInputStream.(ObjectInputStream.java:299) at net.sf.jasperreports.engine.util.ContextClassLoaderObjectInputStream.(ContextClassLoaderObjectInputStream.java:58) at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:244) at net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:229) at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:405) at net.sf.jasperreports.engine.JasperRunManager.runToPdfStream(JasperRunManager.java:201) at net.sf.jasperreports.engine.JasperRunManager.runReportToPdfStream(JasperRunManager.java:720) at co.qcsc.spatha.web.servlet.ReportServlet.generateReport(ReportServlet.java:62) at co.qcsc.spatha.web.servlet.ReportServlet.processRequest(ReportServlet.java:37) at co.qcsc.spatha.web.servlet.ReportServlet.doGet(ReportServlet.java:25) at javax.servlet.http.HttpServlet.service(HttpServlet.java:735) at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1367) at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:180) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:484) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111) at org.eclipse.jetty.server.Server.handle(Server.java:350) at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454) at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890) at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:620) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538) at java.lang.Thread.run(Thread.java:744)

The code that sends the pdf report is this:

public class ReportServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        generateReport(request, response);
    }

    public void generateReport(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Connection connection;
        InputStream reportStream =getServletConfig().getServletContext().getResourceAsStream(
                "/resources/reports/index.jasper");
        ServletOutputStream servletOutputStream = response.getOutputStream();
        try {
            Class.forName("org.postgresql.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:postgresql://localhost:5432/sid", "sid",
                    "sid");
            response.setContentType("application/pdf");
            JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, new HashMap(),
                    connection);
            connection.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (JRException e) {
            e.printStackTrace();
        }
        servletOutputStream.flush();
        servletOutputStream.close();
    }

And in the c.xhtml:

...
    <h:form id="reportForm">
        <p:commandButton value="Generate Report" id="generate_report"
                oncomplete="reportDialogWidget.show()"/>
    </h:form>
    <p:dialog id="reportDialog" modal="true" widgetVar="reportDialogWidget" dynamic="true" resizable="true" maximizable="true" showEffect="fade" hideEffect="explode">
        <iframe src="/clients.pdf" width="800" height="600"></iframe>
    </p:dialog>
...

The section related to this servlet in web.xml:

  <servlet>
    <servlet-name>ReportServlet</servlet-name>
    <servlet-class>com.jg.servlet.ReportServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ReportServlet</servlet-name>
    <url-pattern>/clients.pdf</url-pattern>
  </servlet-mapping>

I've been searching, but I have not found anything that helps me. I think this is information is enough to get some help, but if I am missing something please let me know, I will add anything needed.

Thanks in advance for reading my question.


Solution

  • Something with this line:

    InputStream reportStream =getServletConfig().getServletContext().getResourceAsStream(
                "/resources/reports/index.jasper");
    

    When you get resource as stream, you have to make sure the resource exist. Heroku might not be finding it. Check that it was committed too or better still check for null pointer exception on reportStream before using it.