I am delivering a jasper report as a PDF for download. But when I do it I become unable to make the page to reload or redirect.
The page that causes the download to take place uses a form submission to start the file download. The answer provided by Govinda Sakhare was posted before I made this clarification. However his answer could be implemented with little work as the form only has one choice (big or small).
The function that handles the server response is below:
private void generateReportPDF(JasperReport jasperReport, List<? extends Object> data, Map<String, Object> parameters, HttpServletResponse resp) throws Exception {
byte[] bytes = null;
if( data == null ) {
bytes = JasperRunManager.runReportToPdf(jasperReport, parameters, reportDao.getConnection());
}
else {
bytes = JasperRunManager.runReportToPdf(jasperReport, parameters, new JRBeanCollectionDataSource(data));
}
resp.reset();
resp.resetBuffer();
resp.setContentType("application/pdf");
resp.addHeader("Content-Disposition", "attachment; filename=" + jasperReport.getName() + ".pdf");
resp.setContentLength(bytes.length);
ServletOutputStream ouputStream = resp.getOutputStream();
ouputStream.write(bytes, 0, bytes.length);
ouputStream.flush();
ouputStream.close();
return;
}
Because of this function, my controller is unable to redirect the page and I get the following error when I try to.
SEVERE: Servlet.service() for servlet [myapp-dispatcher] in context with path [/myapp] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed] with root cause
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
I want to reload the page. This is on a label printing screen and after the file download, I want the page to reload/redirect to itself so that labels which were printed are displayed in their new spot. Since the controller is unable to redirect, I have to modify the original process which is handling the response or implement JavaScript to occur after the file has been dealt with.
This question asks about catching downloads and responding to them, but does not involve spring so the answers would require more changes than I want to make.
Using one of the answers from the question I managed to make a workaround but its not satisfactory to me.
$(document).ready(function() {
$('#printBtn').click(function() {
if(confirm('<spring:message code="print.alert.confirm"/>') ? true : false)
{
window.addEventListener('focus', window_focus, false);
function window_focus(){
//remove buttons
var elem1 = document.getElementById('printBtn');
elem1.parentNode.removeChild(elem1);
//elem1.parentNode.replaceChild(newbutton);
var elem2 = document.getElementById('clearBtn');
elem2.parentNode.removeChild(elem2);
var elem3 = document.getElementById('restoreBtn');
elem3.parentNode.removeChild(elem3);
document.getElementById('button_spot').innerHTML = "The page will reload after you get the file.";
//watch for page to lose focus due to download dialog box
window.addEventListener('focusout', pageNoFocus);
function pageNoFocus(){
//watch for page to resume focus
window.removeEventListener('focusout', pageNoFocus);
window.addEventListener('focus', pageFocus);
function pageFocus(){
window.removeEventListener('focus', pageFocus);
location.reload();
}
}
}
return true;
}
return false;
});
$('#clearBtn').click(function() {
return confirm('<spring:message code="print.alert.clear"/>') ? true : false;
});
$('#restoreBtn').click(function() {
return confirm('<spring:message code="print.alert.restore"/>') ? true : false;
});
});