Java.lang.IllegalStateException: getOutputStream () has already been called for this response
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
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";
Mine 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 just give a button that opens me an open save dialog. After clicking this button, I am getting an exception.
How can you avoid this?
It's just a syntax error, the server is confused about how to handle this type of content
<param name="contentType">"application/vnd.ms-excel"</param>
change to
<param name="contentType">application/vnd.ms-excel</param>
note, the value param
is a string without double quotes.
So the actual 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 must initialize excelstream
and provide the getter before returning the result. workbook
do not write in the answer, let it write in 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";
}
Remove absolutely all spaces and gaps between closing%> and opening <%. With space in between, you can automatically call getOutputStream (). Since those spaces or lines are split into the output in the browser: it calls getOutputStream () to render.
This is the only way to find this error in JSP. Otherwise, you will have to rewrite the code that returns the binary as a servlet and just use the JSP page as the launch page to send the user to the servlet when the button is clicked.
Remove any spaces and gaps between closing%> and opening <% and using <% @page trimDirectiveWhitespaces = "true"%> at the top can fix this issue.
Have you read this?
The parameter inputName
needs to be set inputSteam
, but I don't see it anywhere in your code.
You can customize ByteArrayOutputStream
and save the data to ByteArrayInputStream
as shown below
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
/** code to write to outputsteam ***/
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
And you don't need to include these codes
response.setContentType("application/vnd.ms-excel");
outStream= response.getOutputStream();
response.setHeader("Content-Disposition", "attachment; filename=/timesheet.xls");
since you can set the whole thing as a result of the strut action.