简体   繁体   中英

The Jasper Reports servlet stopped working after calling response.getOutputStream()

I have code such as below. The program stopped working at line servletOutputStream = response.getOutputStream(); . I don't know how to resolve this? Can anybody help me with this problem?

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException, SQLException, JRException, ParserConfigurationException, SAXException {
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try {

        out.println ("<html>");
        out.println ("    <head>");
        out.println ("        <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>");
        out.println ("        <title>JSP Page</title>");
        out.println ("    </head>");
        out.println ("    <body>");
        out.println ("        <h1>Hello iReport!</h1>");

        String resourceName = "D:/classic.jrxml";         
        response.setContentType("application/pdf");
        ServletOutputStream servletOutputStream = null;
        servletOutputStream = response.getOutputStream(); // <--
        InputStream reportStream = getServletConfig().getServletContext().getResourceAsStream(resourceName);
        try {
                Driver driver = new org.gjt.mm.mysql.Driver();
                DriverManager.registerDriver(driver);
                String conString = "jdbc:mysql://localhost:3306/quanlynhasach";
                Properties info = new Properties(); 
                info.setProperty("characterEncoding", "utf8");
                info.setProperty("user", "root"); 
                info.setProperty("password", ""); 
                Connection con =  DriverManager.getConnection(conString, info);               
                JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream,new HashMap<Object, Object>(), con);
                con.close();

        }catch(Exception e){
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
             e.printStackTrace(printWriter);
            response.setContentType("text/plain");
            response.getOutputStream().print(stringWriter.toString());
        }
        out.println ("    </body>");
        out.println ("</html>");

    } finally {     

        out.close();
    }
}  // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/** 
 * Handles the HTTP <code>GET</code> method.
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {
        try {
            processRequest(request, response);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        }
    } catch (SQLException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    } catch (JRException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    }
}

/** 
 * Handles the HTTP <code>POST</code> method.
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    try {
        try {
            processRequest(request, response);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
        }
    } catch (SQLException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    } catch (JRException ex) {
        Logger.getLogger(iReport.class.getName()).log(Level.SEVERE, null, ex);
    }
}

/** 
 * Returns a short description of the servlet.
 * @return a String containing servlet description
 */
@Override
public String getServletInfo() {
    return "Short description";
}// </editor-fold>

Look here:

PrintWriter out = response.getWriter();
// *snip*
servletOutputStream = response.getOutputStream();

You're getting both the Writer and OutputStream from the response. This is not allowed. Read their javadocs:

getOutputStream()

 ServletOutputStream getOutputStream() throws java.io.IOException 

Returns a ServletOutputStream suitable for writing binary data in the response. The servlet container does not encode the binary data.

Calling flush() on the ServletOutputStream commits the response. Either this method or getWriter() may be called to write the body, not both.

and

getWriter()

 java.io.PrintWriter getWriter() throws java.io.IOException 

Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding() . If the response's character encoding has not been specified as described in getCharacterEncoding (ie, the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.

Calling flush() on the PrintWriter commits the response.

Either this method or getOutputStream() may be called to write the body, not both.

(emphasis mine)

The problem is in your particular case however much bigger. You're attempting to inline the PDF result of a Jasper Report between those HTML tags within a HTML response. I'm not sure what you thought or smoked while you wrote the code, but that is definitely not going to work. You need to rewrite the servlet that way so that it only returns the PDF and not that bunch of HTML noise. You should move all that HTML out the servlet into some JSP file. Then, you can call that servlet by a simple download link in the JSP

<a href="yourServletUrl">Download PDF</a>

or inside an <iframe> (yes, in JSP)

<iframe src="yourServletUrl" style="width: 500px; height: 300px;"></iframe>

or in an <object> (also here, just in JSP)

<object data="yourServletUrl" type="application/pdf" width="500" height="300" />

Just put that HTML in a JSP page, open the JSP in browser and the webbrowser will take care that the servlet will be invoked and that the PDF will be represented the way you intended.

Your other problem is that the exception handling is not really good. You'll see completely nothing this way as the response buffer is not been resetted. You should instead be doing a

} catch (Exception e) {
    throw new ServletException("descriptive message here", e);
}

as the container knows perfectly how to handle exceptions.

That both your doGet() and doPost() are doing exactly the same is by the way also a design smell. The JDBC driver which you used there is completely outdated and deprecated. The way how you registered the driver is clumsy. That the DB connection is not closed in finally is prone to resource leaking. Okay, I'll stop...

I presume that you are getting an IllegalStateException because you are calling getWriter() and getOutputStream() on the same response. Which you're not allowed to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM