1

I am using struts2 and jasper report in a little web application. I am getting the following error when I am trying to export the report. Report is exported successfully but an error is printed in the log and struts unable to redirect to the success page after executing the action as well.

I have searched this through the internet but I was unable to clarify this. Could anybody please help me to clarify this.

    ERROR Dispatcher - Exception occurred during processing request: Cannot call sendRedirect() after the response has been committed
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
   at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:482)
   at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:137)
   at org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper.sendRedirect   (SaveContextOnUpdateOrErrorResponseWrapper.java:74)
   at org.apache.struts2.dispatcher.ServletRedirectResult.sendRedirect(ServletRedirectResult.java:243)
   at org.apache.struts2.dispatcher.ServletRedirectResult.doExecute(ServletRedirectResult.java:226)
   at org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186)
   at org.apache.struts2.dispatcher.ServletRedirectResult.execute(ServletRedirectResult.java:161)
   at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:367)
   at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:271)
   at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
   at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
   at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
   at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
   at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
   at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
   at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept   (AnnotationValidationInterceptor.java:68)


<struts>

<package name="user" namespace="/" extends="struts-default">

    <action name="testJPReport" class="testUserSupport" method="exportReportAsPdf">
        <result name="success">report.jsp</result>
    </action>
</package>
</struts>


    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

<bean id="testUserSupport"
      class="net.lavanya.app.lav.report.web.TestUserAction">
</bean>

public class TestUserAction  extends ExportSupport{

public String exportReportAsPdf() {
    Map<String, Object> param = new HashMap<>();
    try {
        DataBeanMaker dataBeanMaker = new DataBeanMaker();
        ArrayList<Test> dataBeanList = dataBeanMaker.getTestDataBeanList();
        processReport(ReportTypeEnum.PDF, dataBeanList, "test", param);

    } catch (Exception exception) {
        exception.printStackTrace();
    }
    return SUCCESS;
}

}

package net.test.app.report.web;


import com.opensymphony.xwork2.ActionSupport;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

 public class ExportSupport extends ActionSupport implements     ServletResponseAware, ServletRequestAware {

    private HttpServletResponse httpServletResponse;
    private HttpServletRequest httpServletRequest;
    private String contentType = "APPLICATION/OCTET-STREAM";


@Override
public void setServletResponse(HttpServletResponse httpServletResponse) {
    this.httpServletResponse = httpServletResponse;
}

@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
    this.httpServletRequest = httpServletRequest;
}

    public void processReport(ReportTypeEnum reportTypeEnum, List<?>      beansList, String reportName, Map<String, Object> parameters) throws       Exception {
        switch (reportTypeEnum) {
            case PDF:
                processReportAsPDF(beansList, reportName, parameters);
                break;
            default:
                throw new RuntimeException("Un supported report type");
    }
}

private void processReportAsPDF(List<?> beansList, String reportName, Map<String, Object> parameters) throws Exception {
    System.out.println(">>>>>>>Start processing of pdf report!");

    JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(beansList);
    JasperDesign jasperDesign = JRXmlLoader.load(getJasperFilePath(reportName));
    JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
    setResponseHeaderData(reportName, ReportTypeEnum.PDF);
    ServletOutputStream sos = httpServletResponse.getOutputStream();
    JasperExportManager.exportReportToPdfStream(jasperPrint, sos);
    sos.flush();
    sos.close();
    httpServletResponse.getOutputStream().flush();
    httpServletResponse.getOutputStream().close();

    System.out.println(">>>>>>>End processing of pdf report!");
    return;

}

private InputStream getJasperFilePath(String reportName) throws FileNotFoundException {
    System.out.println(">>>>>>> Path : " + httpServletRequest.getSession().getServletContext().getRealPath("/reports/" + reportName + ".jrxml"));
    return new FileInputStream(httpServletRequest.getSession().getServletContext().getRealPath("/reports/" + reportName + ".jrxml"));
}

private void setResponseHeaderData(String reportName, ReportTypeEnum reportTypeEnum) {
    httpServletResponse.setContentType(contentType);
    StringBuilder headerBuilder = new StringBuilder();
    headerBuilder.append("Attachment;Filename=").append("\"").append(reportName).append(".").
            append(reportTypeEnum.getReportType()).append("\"");

    httpServletResponse.setHeader("Content-Disposition", headerBuilder.toString());
    System.out.println(">>>>>>>End of setting response headers for report download");
}
}
Dilan
  • 1,389
  • 5
  • 14
  • 24

1 Answers1

1

I could not find the sendRedirect in your code. Any way please consider that there is only one http response for every HTTP request you may need some JavaScript solution in the client side.

The export action, or generally the stream result type action should look as below:

 @Action(value = "sample-export", results = { @Result(name = "success", type = "stream", params = {
            "inputName", "inputStream", 
            "contentType",   "${exportContentType}; charset=UTF-8", 
            "Content-Disposition", "attachment; filename=\"${filename}\"", 
            "contentDisposition","attachment; filename=\"${filename}\"", 
            "bufferSize", "2048" }) })
    public String export() throws ClientException {

        inputStream = exportInputStream();

        return SUCCESS;

    }
    //Setter and getters for inputStream (java.io.InputStream)

As you see returning success will not and actually should not redirect user to a new page, user sends a request and gets an stream (PDF for example) as a result.

If you want to redirect you need to do more by javascript, or change the download steps, please see Is it possible in Struts 2 to have a result that downloads a file (stream) *and* redirects? which may help. By changing your download steps, I mean you can save the file on a temp location on your server, redirect user to a final page and put the download link there.

Community
  • 1
  • 1
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
  • Yes. It is also enough to call the download action in [one of the ways described here](http://stackoverflow.com/a/16900840/1654265) to prevent the need to redirect anything – Andrea Ligios May 18 '15 at 12:03