Jasper sub report error

后端 未结 1 1463
渐次进展
渐次进展 2021-01-26 00:33
com.hughes.exception.HughesException
    at com.hughes.service.serviceImpl.HomeServiceImpl.sendTicketEmail(HomeServiceImpl.java:1094)
    at sun.reflect.NativeMethodAccessorI         


        
相关标签:
1条回答
  • 2021-01-26 00:55

    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).

    0 讨论(0)
提交回复
热议问题