Spring MVC Controller code: getOutputStream() has already been called for this response

I'm trying to assemble a CSV file from some DB data and send it to the client from my Spring MVC controller (and associated services). I'm using SuperCSV to handle the writing and output: http://supercsv.sourceforge.net/

So, here's the controller method:

@RequestMapping(value="/getFullReqData.html", method = RequestMethod.GET)
public void getFullData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws IOException{
    logger.info("INFO:  ******************************Received request for full Req data dump");

    List<Requirement> allRecords = reqService.getFullDataSet(ProjectService.getProjectID((String)session.getAttribute("currentProject")));
    response.setContentType("text/csv;charset=utf-8"); 
    response.setHeader("Content-Disposition","attachment; filename=nistData.csv");
    OutputStream fout= response.getOutputStream();  
    OutputStream bos = new BufferedOutputStream(fout);   
    OutputStreamWriter outputwriter = new OutputStreamWriter(bos); 

    ICsvBeanWriter writer = new CsvBeanWriter(outputwriter, CsvPreference.EXCEL_PREFERENCE);
    try {
      final String[] header = new String[] { 
              "ReqID", 
              "ColName1",
              "ColName2",
              "ColName3",
              "ColName4",
              "ColName5", 
              "ColName6",
              "ColName7",
              "ColName8",                                 
              "ColName9",
              "ColName10" };

      // the actual writing
      writer.writeHeader(header);

      for(Requirement aCR : allRecords){
          writer.write(aCR, header);
      }

    } finally {
        writer.close();
    }
};

This is actually moving forward and getting the response to the client browser which triggers the download of the csv file.

Two problems:

1) I'm getting a pile of server-side exception spewage (below)

2) The CSV file has only the headers in it and no data, despite the allRecords list showing as fully populated in the debugger.

I'm hoping the failure-to-populate is caused by the exception, but I'm suspicious. Exception trace:

SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:633)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:214)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:105)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:105)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:182)
at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:123)
at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
at org.apache.jsp.error_jsp._jspService(error_jsp.java:102)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

The exception looks to get passed along as I'm seeing it 4 times per invocation of this method.

All documentation I've found has people who are embedding their response.getOutputStream() inside scriptlets instead of being in a servlet. The method I've got up above is inside the Spring MVC controller, so the advise of "move it to a servlet!" doesn't seem to apply here. From what I can tell, I'm only invoking the response.getOutputStream() one time, and the method is blowing up on the first call.

I'm stumped. Help?

Answers


Your flow is probably raising an exception somewhere in the request mapped method - probably in writer.write(aCR, header); which then goes to the finally block, closes the response stream, then the exception bubbles up to the servlet, which tries to handle it by an error page(check your web.xml error-page tags) , which because the response stream is closed cannot render the error jsp cleanly and hence the exception message you are seeing.

It will be good if you can catch the exception within the controller and print the stack trace to see what could be going wrong in the controller while writing to the output stream.


Need Your Help

Is Tomcat 5.5 compatible with Java 7?

tomcat java

My server runs a legacy Debian 4, Tomcat 5.5 and JDK 5. I plan to (if possible) install JDK 7 on the server and let Tomcat 5.5 runs on JDK 7, without upgrading Tomcat.

Can I pass a different value as a input from using button but display something else in MVC3

c# asp.net asp.net-mvc-3 razor

I have a list of button which has to display the number of comments as the value of the button. But when I click the button I want to send/pass the comment Id to the method that is submitted. Is th...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.