java.lang.IllegalStateException: getOutputStream() has already been called for this response when calling JasperReport

笑着哭i 提交于 2019-11-29 05:20:14

You may not have done so directly but several things in your code are suspect and can be modified to get the desired response. The exception you've gotten does not occur for any other reason other than trying to claim the response output stream after the servlet container has attempted to do so or doing so twice

1) The lines

 ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
 HttpServletResponse httpServletResponse = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
 ServletContext servletContext = (ServletContext) externalContext.getContext();

is making repeated (and unnecessary calls) to context resources.

2) You've failed to call responseComplete() on your FacesContext instance which will almost certainly guarantee that writing a file for download to the stream will fail

3)While I'm not certain on this, I'd recommend you just move your report processing from the actionListener to action on your commandButton and remove the ActionListener argument from the method signature accordingly

4)I don't know what type jasperPrint is, but you can use JasperReport's JasperRunManager.runReportToPdfStream() function that accepts an input stream of .jasper file to output your report.

You can combine all that and use the following :

     FacesContext facesContext = FacesContext.getCurrentInstance(); //Get the context ONCE
     HttpServletResponse response = (HttpServletResponse)       facesContext.getExternalContext().getResponse();
     InputStream reportStream =   facesContext.getExternalContext().getResourceAsStream("/web/ireport/monthlyReport.jasper");
try {
    ServletOutputStream servletOutputStream = response.getOutputStream();
    response.setContentType("application/pdf");
    facesContext.responseComplete();

    try {  // Replace this with your desired JR utility method
        JasperRunManager.runReportToPdfStream(reportStream, servletOutputStream, params);
    } catch (JRException ex) {
        //
    }
    servletOutputStream.flush();
    servletOutputStream.close();
} catch (IOException ex) {
   //
} catch (Exception ex) {
       //
   }

Unrelated to your question, you need to be absolutely sure that the path /web/ireport/* is secure. Looks to me like a publicly accessible path.

For Others Help i m posting my final working (Solved) Code

public void init() throws IOException, JRException {
    JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(listReportObjects);
    String reportPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/web/ireport/monthlyReport.jasper");
    jasperPrint = JasperFillManager.fillReport(reportPath, new HashMap(), beanCollectionDataSource);
    httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
}


public void pdf() throws IOException, JRException {
    init();
    httpServletResponse.addHeader("Content-disposition", "attachment; filename=report.pdf");
    servletOutputStream = httpServletResponse.getOutputStream();
    JasperExportManager.exportReportToPdfStream(jasperPrint, servletOutputStream);
    FacesContext.getCurrentInstance().responseComplete();
}

and the xhtml

<h:commandButton id="getPDF" value="PDF" actionListener="#{monthlyReportBean.pdf}" /> 

using FacesContext.getCurrentInstance().responseComplete(); after exporting the report may solve your problem.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!