Using PrintWriter and OutputStream

33,659

Solution 1

Would be useful to see the stack trace.

You might try running a sanity check first though: Modify that code to simply write a static string (hello world) to the ServletOutputStream and set content type to text/html. As that should work fine:

public void handle(HttpServletResponse res, Connection connection, String path)throws Exception{
ServletOutputStream out = null;
try {
    byte[] bytes = "hello world".getBytes();
    res.setContentType("text/html");
    res.setContentLength(bytes.length);
    out = res.getOutputStream();
    out.write(bytes, 0, bytes.length);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    out.flush();
    out.close();
}

HTH

Solution 2

Some ideas:

  • PrintWriter isn't going to work if you are working with a binary stream (PDF are binary)
  • The illegal state might occur if there is client side timeout or disconnect. A packet trace of the process will tell you a lot (even if you can't read them well). Look at WireShark or what is available for your platform. Its worth your time to learn at least a little bit about what happens at the wire level.
  • Make sure the data you are getting back from the report generate is actually a pdf. Write it to a file and attempt to open.
  • Some situations need you to set the http length header before writing to the stream otherwise they give up when the data starts to show. Might be necessary here.

Solution 3

How exactly is the code invoked? Judging from the stacktrace it look like that you're running the Java class with the handle method using scriptlets inside a JSP file (the inicio2.jsp to be precise). After that the Java class has written the report to the OutputStream, the JSP file would continue with outputting the remnant of the file itself (including whitespace!), which would implicitly invoke the getWriter() to write it to response. Exactly that would cause an IllegalStateException as you're facing now when the getOutputStream() is already been called before in the Java class.

It's good that Java code is been placed in a Java class, but that doesn't mean that you may still use JSP to invoke it. The JSP should not contain any single line of Java code. JSP itself is as being a view technology part of the output. To fix this all, just have a Struts action class (or a HttpServlet) which you can invoke by a HTML <form> or <a>.

Share:
33,659
Random
Author by

Random

I'm the developer with a hell of deadlines, I'm the coder that does all the extra hours, I'm the programer that works without rest, I must be crazy... I'm moving to IT! Random is actually alive, but he travels a lot. He has been coding C/C++ and Java/J2EE proyects since 2003. He loves chess, poetry, RPGs, Table Games and hates a lot of people-persons. He collects computers and put them funny names. He thinks dogs are like most humans. Plain stupid. He likes cats. And Terry Pratchett.

Updated on November 25, 2020

Comments

  • Random
    Random over 3 years

    I am creating a project with struts and I have a problem using Jasper IReports. I want to export some info into a pdf file and I keep getting the java.lang.IllegalStateException: getOutputStream() has already been call... Exception due to openning a ServletOutputStream in my code when the page already opens a PrintWriter.

    The code is in the model (so it is not in the jsp, it's in a java file), as it follows:

        public void handle(HttpServletResponse res, Connection connection, String path)throws Exception{
        ServletOutputStream out = null;
        try {
    
            JasperDesign jasperDesign = JRXmlLoader.load(path);
            JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
            byte[] bytes = JasperRunManager.runReportToPdf(jasperReport, null, connection);
            res.setContentType("application/pdf");
            res.setContentLength(bytes.length);
            out = res.getOutputStream();
            out.write(bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
        }
    

    I have checked the connection, the path and the HttpServletResponse and are all working fine.

    I'm very newbie with Jasper Reports as well as with coding stuff into PDF so you can -correctly- suposse that I have a minimal idea of what I am doing here and that, obviously my code is copy/pasted from somewhere through the net.

    I have tried to use PrintWriter instead of OutputStream, transforming bytes into a String and using the PrintWriter.append(String) method (allthought is not String is CharSequence), but it doesn't extract the data into the PDF.

    I have also tried to get the PrintWriter, close it to open the OutputStream (didn't work) or flush it (neither).

    Any help with a solution to use any out that could show the data in a pdf would be great. Thanks a lot!