Reputation: 217
The JRParameter.REPORT_FILE_RESOLVER is deprecated in version 5.0. The Javadoc suggests to use JasperReportsContext instead.
How to use JasperReportsContext?
The use is requested when using the Struts2 jasper plugin.
connection=dataSource.getConnection();
reportParams.put(JRParameter.REPORT_FILE_RESOLVER, new SimpleFileResolver(reportsDir));
Upvotes: 4
Views: 6282
Reputation: 396
Had the same problem (File resolver in Jasper Reports 5.0.1) and after many hours I found the answer in the JasperReports sources.
LocalJasperReportsContext ctx = new LocalJasperReportsContext(DefaultJasperReportsContext.getInstance());
ctx.setClassLoader(getClass().getClassLoader());
ctx.setFileResolver(new FileResolver() {
@Override
public File resolveFile(String s) {
return new File(s);
}
});
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(jasperfile);
JasperFillManager fillmgr = JasperFillManager.getInstance(ctx);
JasperExportManager exmgr = JasperExportManager.getInstance(ctx);
Edit: The proper solution would include reporting the problem to the plugin's project ticketing system and maybe propose a patch for the resolver implementation.
While waiting for the patch to get accepted, you can extend the JasperReportsResult
class and just override the doExecute()
method, using the code above, with something like this:
protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
// Will throw a runtime exception if no "datasource" property. TODO Best place for that is...?
initializeProperties(invocation);
LOG.debug("Creating JasperReport for dataSource = {}, format = {}", dataSource, format);
HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(ServletActionContext.HTTP_RESPONSE);
// Handle IE special case: it sends a "contype" request first.
// TODO Set content type to config settings?
if ("contype".equals(request.getHeader("User-Agent"))) {
try (OutputStream outputStream = response.getOutputStream()) {
response.setContentType("application/pdf");
response.setContentLength(0);
} catch (IOException e) {
LOG.error("Error writing report output", e);
throw new ServletException(e.getMessage(), e);
}
return;
}
// Construct the data source for the report.
ValueStack stack = invocation.getStack();
ValueStackDataSource stackDataSource = null;
Connection conn = (Connection) stack.findValue(connection);
if (conn == null)
stackDataSource = new ValueStackDataSource(stack, dataSource, wrapField);
if ("https".equalsIgnoreCase(request.getScheme())) {
// set the the HTTP Header to work around IE SSL weirdness
response.setHeader("CACHE-CONTROL", "PRIVATE");
response.setHeader("Cache-Control", "maxage=3600");
response.setHeader("Pragma", "public");
response.setHeader("Accept-Ranges", "none");
}
// Determine the directory that the report file is in and set the reportDirectory parameter
// For WW 2.1.7:
// ServletContext servletContext = ((ServletConfig) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONFIG)).getServletContext();
ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONTEXT);
String systemId = servletContext.getRealPath(finalLocation);
Map parameters = new ValueStackShadowMap(stack);
File directory = new File(systemId.substring(0, systemId.lastIndexOf(File.separator)));
parameters.put("reportDirectory", directory);
parameters.put(JRParameter.REPORT_LOCALE, invocation.getInvocationContext().getLocale());
// put timezone in jasper report parameter
if (timeZone != null) {
timeZone = conditionalParse(timeZone, invocation);
final TimeZone tz = TimeZone.getTimeZone(timeZone);
if (tz != null) {
// put the report time zone
parameters.put(JRParameter.REPORT_TIME_ZONE, tz);
}
}
// Add any report parameters from action to param map.
Map reportParams = (Map) stack.findValue(reportParameters);
if (reportParams != null) {
LOG.debug("Found report parameters; adding to parameters...");
parameters.putAll(reportParams);
}
ByteArrayOutputStream output;
JasperPrint jasperPrint;
LocalJasperReportsContext ctx = new LocalJasperReportsContext(DefaultJasperReportsContext.getInstance());
ctx.setClassLoader(getClass().getClassLoader());
ctx.setFileResolver(parameters.get());
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(jasperfile);
JasperFillManager fillmgr = JasperFillManager.getInstance(ctx);
JasperExportManager exmgr = JasperExportManager.getInstance(ctx);
// Fill the report and produce a print object
try {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(new File(systemId));
if (conn == null) {
jasperPrint = fillmgr.fillReport(jasperReport, parameters, stackDataSource);
}
else {
jasperPrint = fillmgr.fillReport(jasperReport, parameters, conn);
}
} catch (JRException e) {
LOG.error("Error building report for uri {}", systemId, e);
throw new ServletException(e.getMessage(), e);
}
// Export the print object to the desired output format
try {
if (contentDisposition != null || documentName != null) {
final StringBuffer tmp = new StringBuffer();
tmp.append((contentDisposition == null) ? "inline" : contentDisposition);
if (documentName != null) {
tmp.append("; filename=");
tmp.append(documentName);
tmp.append(".");
tmp.append(format.toLowerCase());
}
response.setHeader("Content-disposition", tmp.toString());
}
JRExporter exporter;
if (format.equals(FORMAT_PDF)) {
response.setContentType("application/pdf");
exporter = new JRPdfExporter(ctx);
} else if (format.equals(FORMAT_CSV)) {
response.setContentType("text/csv");
exporter = new JRCsvExporter(ctx);
} else if (format.equals(FORMAT_HTML)) {
response.setContentType("text/html");
// IMAGES_MAPS seems to be only supported as "backward compatible" from JasperReports 1.1.0
Map imagesMap = new HashMap();
request.getSession(true).setAttribute("IMAGES_MAP", imagesMap);
exporter = new JRHtmlExporter(ctx);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl);
// Needed to support chart images:
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
request.getSession().setAttribute("net.sf.jasperreports.j2ee.jasper_print", jasperPrint);
} else if (format.equals(FORMAT_XLS)) {
response.setContentType("application/vnd.ms-excel");
exporter = new JRXlsExporter(ctx);
} else if (format.equals(FORMAT_XML)) {
response.setContentType("text/xml");
exporter = new JRXmlExporter(ctx);
} else if (format.equals(FORMAT_RTF)) {
response.setContentType("application/rtf");
exporter = new JRRtfExporter(ctx);
} else {
throw new ServletException("Unknown report format: " + format);
}
Map exportParams = (Map) stack.findValue(exportParameters);
if (exportParams != null) {
LOG.debug("Found export parameters; adding to exporter parameters...");
exporter.getParameters().putAll(exportParams);
}
output = exportReportToBytes(jasperPrint, exporter);
} catch (JRException e) {
LOG.error("Error producing {} report for uri {}", format, systemId, e);
throw new ServletException(e.getMessage(), e);
} finally {
try {
conn.close();
} catch (Exception e) {
LOG.warn("Could not close db connection properly", e);
}
}
response.setContentLength(output.size());
// Will throw ServletException on IOException.
writeReport(response, output);
}
and than use the new extension as the Result in Struts. Please test if the method is implemented correctly.
The final solution should include the use of a context instance setter on the Result object, or maybe a global static context instance accessible from the Result object.
Upvotes: 1