1
votes

I am trying to organize project structure inside my current workspace so that I could reuse common resources across multiple projects.

How can I use a report in a project as a sub-report within a different project but within the same workspace without having to use absolute path to the jrxml file? As shown in the screenshot, I am planning to use reports Rpt3.jrxml and Rpt4.jrxml in Project-B (which uses resources in Images directory within the same project) as sub-reports in Rpt1.jrxml and Rpt2.jrxml. I tried making use of Path Variables defined at the project level but those are not getting recognized within the expression editor.

enter image description here

Also could someone advice what would be best practice in this case where I need to reuse a bunch of reports as sub-reports in multiple projects.

Thanks.


EDIT:

Thanks for referencing similar looking threads. Most questions suggested were about JasperReports Server for web based solution/programmatic access and were not addressing the issue of embedding/reusing a sub-report from another project (within same Workspace) or accessing path variable in expression editor or best practices.

1
Most questions suggested were about JasperReports Server for web based solution/programmatic access and were not addressing the issue of embedding/reusing a sub-report from another project (within same Workspace) or accessing path variable in expression editor or best practices. - What do you mean? There are a lot of solutions described at dupes such as: 1) using parameter with path; 2) using FileRepositoryService; 3) using SimpleJasperReportsContext; 4) you can pass classloader via JRParameter.REPORT_CLASS_LOADER - Alex K
I am not currently using FileRepositoryService, not planning to use custom Java code so I believe SimpleJasperReportsContext won't apply. Also none of those talk about best practices when it comes to sharing reports across different projects. Not sure how can I use a path variable defined at the project level in expression editor. - thinkster
Are you planning to show reports to end-users at Studio? ;) - Alex K
These are going to be just run in batch mode to export report documents using an ETL job. No user interaction is involved and I am not currently using any web components or JasperReports Server for this request. - thinkster
I believe for some reason, the expression editor won't recognize those Path variables defined in Project Resources with $V{} syntax. I am not sure if there is a different syntax to it or if there is any alternate option with which those variables are to be explicitly brought in the project execution scope so that jrxml can recognize those value. I am tying to keep it relative to avoid dependencies as there are chances the environment may get changed in the future. - thinkster

1 Answers

2
votes

The possible solution is to use report's parameter

You can create new parameter for storing path to your Workspace and then use this parameter at report(s).

The path to the Workspace can be set with help of this expresion (this is simple Java expression).

<defaultValueExpression><![CDATA[org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot().getLocation().toString()]]></defaultValueExpression>

The ResourcesPlugin class is from Eclipse libraries - you don't need to add additional jar file by yourself.

Working example

My project structure

The workspace structure

I created two projects: Project-A and Project-B. Both projects contain folder Reports for storing templates

Main report

The main report is from Project-B

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Rpt2" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
    <parameter name="curDir" class="java.lang.String">
        <defaultValueExpression><![CDATA[org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot().getLocation().toString()]]></defaultValueExpression>
    </parameter>
    <title>
        <band height="70" splitType="Stretch">
            <subreport>
                <reportElement x="0" y="40" width="560" height="30"/>
                <connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
                <subreportExpression><![CDATA[$P{curDir} + "/Project-A/Reports/Rpt1.jasper"]]></subreportExpression>
            </subreport>
            <staticText>
                <reportElement x="0" y="0" width="550" height="35"/>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <text><![CDATA[Report 2]]></text>
            </staticText>
        </band>
    </title>
</jasperReport>

All you need is to construct subreport's path from two parts: parameter containing absolute path to Workspace and constant String with relative path to subreport ("/Project-A/Reports/Rpt1.jasper").

Subreport

The subreport is from Project-A

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Rpt1" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
    <title>
        <band height="79" splitType="Stretch">
            <staticText>
                <reportElement x="0" y="22" width="560" height="35"/>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <text><![CDATA[Report 1]]></text>
            </staticText>
        </band>
    </title>
</jasperReport>

Output result

I've used One Empty Record data adapter (new JREmptyDataSource(1)) for building main report.

Generated result at JSS:

Generated result with JSS preview

Notes

After designing templates you can use several options for showing subreports:

  • using parameter for passing the part of path in the same way like described above
  • using FileRepositoryService class. It makes possible to use relative path
  • using SimpleJasperReportsContext class. It makes possible to use relative path
  • using JRParameter.REPORT_CLASS_LOADER parameter for passing classloader. It makes possible to use resources loaded by classloader

More info can be found here: