I have some code for download file from web server. Everything works alright, but in console I have this exception:
июн 26, 2015 2:08:42 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [default] in context with path [/TestTask] threw exception
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:462)
at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleErrorInDevMode(DefaultDispatcherErrorHandler.java:109)
at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleError(DefaultDispatcherErrorHandler.java:57)
at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:909)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:576)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Why and what it can be? And how i can fix this problem? I try find answer in the google, but I failed.
package actions;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Action;
import org.apache.log4j.Logger;
import org.apache.struts.chain.contexts.ServletActionContext;
import service.CsvCreator;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadCsvAction extends ActionSupport {
private static final long serialVersionUID = -4714537109287679996L;
private CsvCreator CSVcreator;
private static final Logger logger = Logger.getLogger(DownloadCsvAction.class);
public CsvCreator getCSVcreator() {
return CSVcreator;
}
public void setCSVcreator(CsvCreator cSVcreator) {
CSVcreator = cSVcreator;
}
@Override
public String execute() {
HttpServletResponse response = org.apache.struts2.ServletActionContext.getResponse();
response.setHeader("Content-Disposition", "attachment; filename=\"phone_records.csv\"");
response.setContentType("text/csv");
ServletOutputStream out;
try {
out = response.getOutputStream();
String tableHeader = "Caller, Event, Reciever, Timestamp\n";
out.write(tableHeader.getBytes("UTF-8"));
out.write(CSVcreator.getAllRecordsInString().getBytes("UTF-8"));
out.flush();
out.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
return SUCCESS;
}
}
And my struts.xml
:
<action name="DownloadCsvAction" class="DownloadCsvAction">
<result name="success" type="dispatcher"/>
</action>
Because response is already committed. You have closed response before it's used by the Struts2.
When your action execution ends, return
Action.NONE
result code. This code tells the invoker to not execute any result because response might be already committed.You can also rewrite the action implementation to use
stream
result type. In this way you have not to do with the response and let Struts2 do the rest. Example of usingstream
result is here.