简体   繁体   English

Jasper子报告错误

[英]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. 我的Jarper知识很老,但是希望对您有所帮助。

This is because jasper does not find your subreport. 这是因为jasper找不到您的子报表。 Jasper can compile your report, but it does not compile referenced subreports when you call compileReport . Jasper可以编译您的报告,但是当您调用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. Alex K提供的链接对此非常有用。 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. 在Web应用程序中,我发现一种工作习惯是处理编译,填充报表是手动管理。 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() . 这里$P{data}是作为文档参数提供的合适对象,其中getSubreport()最终调用ReportSource.getReport() It could of course be $P{reportSource}.getReport("....") if ReportSource is provided as parameter directly. 如果直接将ReportSource作为参数提供,则当然可以是$P{reportSource}.getReport("....") (We use ReportModel-approach; in short it is presentation model fitted to the context of reports). (我们使用ReportModel-approach;简而言之,它是适合于报告上下文的表示模型)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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