2

Here is my code for which I am getting the following exception

HTTP Status 500 - Unable to show problem report: java.lang.IllegalStateException: getOutputStream() has already been called for this response

The code:

WorkbookSettings wbSettings = new WorkbookSettings();    
OutputStream outStream = null;
            
try
{               
  wbSettings.setLocale(new Locale("en", "EN"));             
  response.setContentType("application/vnd.ms-excel");                  
  outStream= response.getOutputStream();                
  response.setHeader("Content-Disposition", "attachment; filename=/timesheet.xls");             
  WritableWorkbook workbook = Workbook.createWorkbook(outStream, wbSettings);              
  workbook.createSheet("Report", 0);               
  WritableSheet excelSheet = workbook.getSheet(0);              
  service.createLabel(excelSheet);              
  service.createContent(excelSheet);                    
  workbook.write();             
  workbook.close();             
  outStream.flush();               
  outStream.close();                
}               
catch(Exception e)
{
}           
finally
{               
  //outStream.close();      
}   
return "generateReport";

My Struts.xml looks like this:

<result type="stream" name="generateReport">                   
 <param name="contentType">"application/vnd.ms-excel"</param>                  
 <param name="inputName">excelstream</param>                  
 <param name="contentDisposition">contentDisposition</param>                   
 <param name="bufferSize">1024</param>              
</result>

In JSP, I am just giving a button which gives me open, save dialog box. After clicking that button I am getting the exception.

How to avoid this?

Roman C
  • 49,761
  • 33
  • 66
  • 176
Akhilesh N
  • 89
  • 3
  • 4
  • 12
  • Please see these links [Question 1](http://stackoverflow.com/questions/3540464/java-lang-illegalstateexception-getoutputstream-has-already-been-called-for-t) , [Question 2](http://stackoverflow.com/questions/11410313/java-lang-illegalstateexception-getoutputstream-has-already-been-called-for-t) , [Question 3](http://stackoverflow.com/questions/1776142/getoutputstream-has-already-been-called-for-this-response) , [question 4](http://stackoverflow.com/questions/10512179/ava-lang-illegalstateexception-getoutputstream-has-already-been-called-for-th) – Freak Dec 28 '12 at 06:36
  • 1
    Please refer this link : http://stackoverflow.com/questions/1003892/how-to-return-excel-in-struts2-result Remove all response related code in action – Punit Patel Sep 11 '13 at 12:00

4 Answers4

2

It's just a syntax error, the server in confuse how to handle such content type

<param name="contentType">"application/vnd.ms-excel"</param>

change to

<param name="contentType">application/vnd.ms-excel</param>

note, the param value is a string without double quotes.

So, the valid result would be

<result type="stream" name="generateReport">
  <param name="contentType">application/vnd.ms-excel</param>
  <param name="contentDisposition">attachment;filename="timesheet.xls"</param>
  <param name="inputName">excelstream</param>
</result>

the action code should initialize the excelstream and provide getter before returning result. The workbook shouldn't write to the response, let it write to the ByteArrayOutputStream.

private InputStream excelstream;

public InputStream getExcelstream() {
  return excelstream;
}  

public String execute() throws Exception {
  WorkbookSettings wbSettings = new WorkbookSettings();

  try  {  
    ByteArrayOutputStream outstream = new ByteArrayOutputStream();  
    wbSettings.setLocale(new Locale("en", "EN"));        
    WritableWorkbook workbook = Workbook.createWorkbook(outstream, wbSettings);   
    workbook.createSheet("Report", 0);    
    WritableSheet excelSheet = workbook.getSheet(0);    
    service.createLabel(excelSheet);    
    service.createContent(excelSheet);          
    workbook.write();    
    workbook.close();  
    excelstream = new ByteArrayInputStream(outstream.toByteArray());        
  } catch(Exception e) {    
    e.printStackTrace();
    throw e;
  }

  return "generateReport";
}
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • Correct, but I have written the correct syntax and still get the same exception. – Rndm Sep 05 '13 at 13:15
  • @Rndm There's also error in the header for content disposition, the server is not able to handle such filenames. And why don't you use the `stream` result? – Roman C Sep 05 '13 at 13:22
2

Remove absolutely all space and linebreaks between closing %> and opening <%. Having space between those can cause getOutputStream() to be called automatically. Because those spaces or linebreaks are being treated as output to the browser: it calls getOutputStream() to render them.

Its the only way I've found to solve this error in a JSP. Otherwise you'll have to rewrite the code that returns the binary file to be a servlet and just use the JSP page as a launch page to send the user to the servlet when they click the button.

developerwjk
  • 8,619
  • 2
  • 17
  • 33
2

Remove all space and linebreaks between closing %> and opening <% and use <%@page trimDirectiveWhitespaces="true" %> at top can solve this issue.

1

Have you read this?

You need to have a inputSteam set for the inputName paramater but I cannot see it anywhere in your code.

You can set up a ByteArrayOutputStream and store the data to ByteArrayInputStream like below

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

/** code to write to outputsteam ***/

ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

And you do not need to include these codes

response.setContentType("application/vnd.ms-excel");    

outStream= response.getOutputStream();

response.setHeader("Content-Disposition", "attachment; filename=/timesheet.xls");

as you can set all these in the strut action result.

lmcanavals
  • 2,339
  • 1
  • 24
  • 35
Quincy
  • 4,393
  • 3
  • 26
  • 40
  • 1
    I created the Streams with inputStream as excelStream now i am getting this error java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [excelStream] in the invocation stack. Check the tag specified for this action. My Struts XML is same as above. – Akhilesh N Dec 28 '12 at 08:24
  • You need to have a getter method `getExcelstream()` in your action class and returns the inputStream in it. – Quincy Dec 28 '12 at 08:28
  • I do not have the issues mentioned in this answer but getting the same exception when downloading large files. – Rndm Sep 05 '13 at 03:13
  • If the only common thing is the Exception, you should open a question of your and put the bounty on that – Andrea Ligios Sep 05 '13 at 14:55