As a follow-up to my previous post about using iReport, I wanted to write some code that would run the report. My goal is something that I can launch from PeopleTools.
Below is some Java that will execute the report and build a PDF output. This class takes the XML data file and the report designed by iReport and produces a PDF out of it.
package net.digitaleagle.psst0101; import java.io.File; import java.util.HashMap; import java.util.Locale; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRParameter; import net.sf.jasperreports.engine.JasperCompileManager; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory; import net.sf.jasperreports.engine.util.FileResolver; import net.sf.jasperreports.engine.util.JRXmlUtils; import org.w3c.dom.Document; public class JasperInterface { private String dataPath; private String basePath; private String reportName; private String reportOutput; public JasperInterface(String dataPath, String basePath, String reportName, String reportOutput) { this.dataPath = dataPath; this.basePath = basePath; this.reportName = reportName; this.reportOutput = reportOutput; } public void run() throws JRException { Document data = JRXmlUtils.parse(dataPath); HashMap parms = new HashMap(); parms.put(JRXPathQueryExecuterFactory.PARAMETER_XML_DATA_DOCUMENT, data); parms.put(JRXPathQueryExecuterFactory.XML_DATE_PATTERN, "yyyy-MM-dd"); parms.put(JRXPathQueryExecuterFactory.XML_LOCALE, Locale.ENGLISH); parms.put(JRParameter.REPORT_LOCALE, Locale.US); FileResolver fileResolver = new FileResolver() { @Override public File resolveFile(String fileName) { return new File(basePath, fileName); } }; parms.put(JRParameter.REPORT_FILE_RESOLVER, fileResolver); JasperReport jr = JasperCompileManager.compileReport(basePath + reportName); JasperPrint pr = JasperFillManager.fillReport(jr, parms); JasperExportManager.exportReportToPdfFile(pr, reportOutput); } }
Here’s some code that can launch the report without needing the JasperReports classes in the classpath. I originally thought about just putting the jar files into the class directory in the PeopleSoft Home, but Jasper Reports has a number of Jar files. So, I created a class that had no dependencies on JasperReports. I tell it the location of the JasperReports installation, and it builds the necessary class path.
package net.digitaleagle.psst0101; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; public class JasperReportRunner { private String jasperPath; private String dataPath; private String basePath; private String reportName; private String reportOutput; /** * @param args */ public static void main(String[] args) { String jasperPath = args[0]; String dataPath = args[1]; String basePath = args[2]; String reportName = args[3]; String reportOutput = args[4]; JasperReportRunner jrr = new JasperReportRunner(jasperPath, dataPath, basePath, reportName, reportOutput); jrr.run(); } public JasperReportRunner(String jasperPath, String dataPath, String basePath, String reportName, String reportOutput) { this.jasperPath = jasperPath; this.dataPath = dataPath; this.basePath = basePath; this.reportName = reportName; this.reportOutput = reportOutput; } public void run() { ArrayList urls = new ArrayList(); File jasperDir = new File(jasperPath); addJars(urls, new File(jasperDir, "dist")); addJars(urls, new File(jasperDir, "lib")); URLClassLoader ucl = new URLClassLoader(urls.toArray(new URL[0])); Class jic; try { jic = ucl.loadClass(this.getClass().getPackage().getName() + ".JasperInterface"); } catch (ClassNotFoundException e) { System.err.println("Could not access JasperInterface class"); e.printStackTrace(); return; } Constructor c = jic.getConstructors()[0]; Object ji; try { ji = c.newInstance(dataPath, basePath, reportName, reportOutput); } catch (Exception e) { System.err.println("Error creating new instance of JasperInterface"); e.printStackTrace(); return; } Method method; try { method = jic.getMethod("run"); } catch (Exception e) { System.err.println("Could not get run method"); e.printStackTrace(); return; } try { method.invoke(ji); } catch (Exception e) { System.err.println("Could not get execute run method"); e.printStackTrace(); return; } } private void addJars(ArrayList urls, File jarDir) { if(!jarDir.exists()) { System.err.println("Could not find Jasper Jar files in directory: " + jarDir.getAbsolutePath()); System.err.println("Check installation directory"); return; } for(File jarFile : jarDir.listFiles()) { if(jarFile.isFile() && jarFile.getName().toLowerCase().endsWith(".jar")) { try { urls.add(jarFile.toURI().toURL()); } catch (MalformedURLException e) { System.err.println("Error loading jar for class path: " + jarFile.getAbsolutePath()); e.printStackTrace(); } } } } }
Resources
One thought on “Running Jasper Reports from Java”