简体   繁体   中英

Jasper sub report error

com.hughes.exception.HughesException
    at com.hughes.service.serviceImpl.HomeServiceImpl.sendTicketEmail(HomeServiceImpl.java:1094)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

.......................................................
..........................................

Caused by: net.sf.jasperreports.engine.JRException: Resource not found at : nullinvoiceDetail.jasper
    at net.sf.jasperreports.repo.RepositoryUtil.getResource(RepositoryUtil.java:155)
    at net.sf.jasperreports.repo.RepositoryUtil.getReport(RepositoryUtil.java:126)
    at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateReport(JRFillSubreport.java:317)
    at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:347)
    at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluate(JRFillSubreport.java:275)
    at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:257)
    at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:473)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:2021)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:755)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:265)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:128)
    at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:836)
    at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:765)
    at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:84)
    at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:624)
    at com.hughes.service.serviceImpl.HomeServiceImpl.sendTicketEmail(HomeServiceImpl.java:1046)
    ... 81 more
JasperReport jasperReport = JasperCompileManager.compileReport(hdnWebInfPath+seperator+"reports"+seperator+"invoice.jrxml");
                        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, model, new JREmptyDataSource());
                        JasperExportManager.exportReportToPdfFile(jasperPrint, fPath+seperator+fileName);

this works when simple report not working for sub reports...

My Jarper knowledge is couple versions old, but lets hope this is helpful.

This is because jasper does not find your subreport. Jasper can compile your report, but it does not compile referenced subreports when you call compileReport . When filling the report referenced subreports are not found because they are not available in working directory.

(Compiling report every time it is requested is kind a bad idea (unless you have some really heavy reasons to do so).)

There are couple of ways solving this. One would be making sure the the paths are correct and precompiling the reports before application deployment. Links Alex K provided are an excellent source for this. If in application compilation is required then using solution below is possible:

In web application I've found that a working practice is to handle compilation and filling your reports is to manage it manually. Here is helper class I wrote. Hope that it is useful (it uses spring, but those parts are easily replaceable).

public class ReportSource {

    // Key = document name, Value = path to .jrxml
    private Map<String, String> reports;
    private final Map<String, JasperReport> compiled;

    private final boolean lazy;

    private final Logger log = Logger.getLogger(ReportSource.class);

    public ReportSource(final boolean lazyBuild) {
        super();
        lazy = lazyBuild;
        compiled = new HashMap<String, JasperReport>();
    }

    public void setCompileTargets(final Map<String, String> targets) {
        reports = new HashMap<String, String>(targets);
        if (!lazy) {
            for (final String key : targets.keySet()) {
                compile(key);
            }
        }
    }

    public JasperReport getReport(final String reportName) {
        if (compiled.get(reportName) == null) { // not found or not compiled
            log.info("Lazily compiling: " + reportName);
            return compile(reportName);
        }
        return compiled.get(reportName);
    }

    private JasperReport compile(final String reportName) {
        final String path = reports.get(reportName);

        InputStream fis = null;
        JasperReport report = null;
        try {
            final FileSystemResourceLoader resourceLoader = new FileSystemResourceLoader();
            fis = resourceLoader.getResource(path).getInputStream();
            log.info("Compiling report: " + reportName + " (" + path + ")");
            report = JasperCompileManager.compileReport(fis);
        } catch (final IOException ioe) {
            throw new IllegalStateException("Configuration error file: " + path + " (for key: " + reportName +") not found.", ioe);
        } catch (final JRException jre) {
            throw new IllegalStateException("Configuration error file: " + path + " (for key: " + reportName +") not found.", jre);
        }

        compiled.put(reportName, report);
        return report;
    }
}

With the help of this class you can refer subreports in documents like this:

<subreport>
    <reportElement x="0" y="0" width="200" height="30"/>
    <subreportParameter name="data">
        <subreportParameterExpression><![CDATA[$P{data}]]></subreportParameterExpression>
    </subreportParameter>
    <subreportParameter name="REPORT_RESOURCE_BUNDLE">
        <subreportParameterExpression><![CDATA[$P{REPORT_RESOURCE_BUNDLE}]]></subreportParameterExpression>
    </subreportParameter>
    <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource()]]></dataSourceExpression>
    <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{data}.getSubreport("name_of_your_subreport")]]></subreportExpression>
</subreport>

Here $P{data} is suitable object provided as document parameter, where getSubreport() ends up calling ReportSource.getReport() . It could of course be $P{reportSource}.getReport("....") if ReportSource is provided as parameter directly. (We use ReportModel-approach; in short it is presentation model fitted to the context of reports).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM