2

I am using Apache POI for generating Excel file in Java Servlets.

getExcel() function returns HSSFWorkbook, which I want to send to the client.

HSSFWorkbook wb = getExcel();

This is what I have tried so far.

//block1
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
wb.write(outByteStream);
byte [] outArray = outByteStream.toByteArray();
response.setContentType("application/ms-excel");
response.setContentLength(outArray.length);
response.setHeader("Expires:", "0");
response.setHeader("Content-Disposition", "attachment; filename=Demo1.xls");
OutputStream outStream = response.getOutputStream();
outStream.write(outArray);
outStream.flush();

//block2
request.setAttribute("Message", str1);
request.setAttribute("MessageDetails", str2);
request.getRequestDispatcher("/MyFile.jsp").forward(request, response);

Above code sends excel file to the client, but gives me exception:

java.lang.IllegalStateException: Cannot forward after response has been committed

If I remove the block1 or block2 from above code then it will not give error, but I want to send client Excel file and two attributes which I have added to request object.

So can send Excel file to client using request.getRequestDispatcher ? Or is there any better way for doing this?

Any suggestion will be appreciated.

Edit1
I know why I am getting the IllegalStateException, but then my question is how should I send ExcelFile and Request Attributes both to the client?

Edit2
The Reason why I want to send both Excel file and Attributes to the client is that MyFile.jsp has a <div> which will show message send from servlet.

<div style="background-color: aliceblue">
    <h3>${Message}</h3>
</div>

Edit3
The Reason why I want to send message to client is that I am sending this Excel file as an response to Import Excel operation in which client will provide excel file for inserting data in database, and then I am highlighting the excel rows which cannot be inserted due to duplication or any other reasons. So I want to show Import statistics in the Message to client and give him copy of excel file with error rows highlighted.

Bhushan
  • 6,151
  • 13
  • 58
  • 91
  • 2
    You can't execute nor a redirect nor a forward when triggering a file download. Just write the content of the file in the response and close the response stream and let the browser takes care of this. – Luiggi Mendoza Jul 05 '13 at 14:48
  • possible duplicate of [How to send a file from a servlet the "right" way?](http://stackoverflow.com/questions/5805859/how-to-send-a-file-from-a-servlet-the-right-way) – Luiggi Mendoza Jul 05 '13 at 15:00

1 Answers1

2

You are flushing your response and then trying to forward. Container has already sent the response back to the client and now is in a dilemma as to how to forward the request to another JSP, hence it aborts the operation mid way throwing an Exception. HTTP is a request-response model . Once you request , you get back a response . But once the response is already committed the whole transaction is over.

outStream.write(outArray); 
// you already committed the response here by flushing the output stream
outStream.flush(); 

//block2
request.setAttribute("Message", str1);
request.setAttribute("MessageDetails", str2);
// this is illegal after you have already flushed the response
request.getRequestDispatcher("/MyFile.jsp").forward(request, response);

As per the Javadoc:

IllegalStateException - if the response was already committed.

After EDIT1:

No you cannot do both . You need to decide what you want. Write the bytes to the response setting proper HEADERS and MIME-TYPE. You cannot get the browser download something as well as show a JSP page from the same response.

AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • Have you tested this? Note my comment on OP's question, then please test this code to see if it really works. – Luiggi Mendoza Jul 05 '13 at 14:52
  • @TheNewIdiot Thanks for answer, I know why I am getting the `IllegalStateException`, but then my question is how should I send `ExcelFile` and `Request Attributes` both to the client? – Bhushan Jul 05 '13 at 14:55
  • Executing a forward after preparing the response for a file download... OP wants to trigger a file download and a forward, which is not possible and you're not providing a solution either. Note that it is not a dilemma, it is simple: the server won't do any. – Luiggi Mendoza Jul 05 '13 at 14:55
  • @LuiggiMendoza This is OP's code , i have added comments to specify what is happening. – AllTooSir Jul 05 '13 at 14:55
  • One not-so-right workaround would be to trigger two requests beforehand to get two responses. – skuntsel Jul 05 '13 at 15:03
  • @LuiggiMendoza Do you mean to say once the response is flushed , the remaining code in Servlet won't be executed ? – AllTooSir Jul 05 '13 at 15:04
  • 1
    No, but you won't be able to forward the response or send a redirect. – skuntsel Jul 05 '13 at 15:05
  • @skuntsel Yes that is what I meant . I said *Container has already sent the response back to the client and now is in a dilemma as to how to carry on the forward the request to another JSP* , hence it aborts the operation mid way throwing an exception ! What is wrong in this statement ? – AllTooSir Jul 05 '13 at 15:06