Hi, everyone!
I have been unsuccessfully trying to pass the information contained on my DataSource into my "Content.jrxml" subreport fields.
I am able to print everything ( Front and Back Cover, some extra pages and an empty Table of Content) so far, except the little piece information regarding fields in that specific sub-report.
I am even capable of passing parameters from the main report to the subreport and print that information correctly. But when it comes to the fields and information that is being inserted in my DataSource object (JRMapArrayDataSource) and trying to pass that instance to my subreport, is printing "null". Meaning that fields under that sub-report are never initialized, probably...
So I try on my main report (Book.jrxml), the following:
<detail>
</pre>
<part uuid="6bbe1f1b-154b-4fe1-8c3b-848219b22e5d">
<p:subreportPart xmlns:p="http://jasperreports.sourceforge.net/jasperreports/parts" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/parts http://jasperreports.sourceforge.net/xsd/parts.xsd">
<subreportParameter name="REPORT_CONNECTION"><subreportParameterExpression><![CDATA[$P{REPORT_CONNECTION}]]></subreportParameterExpression>
</subreportParameter><subreportParameter name="REPORT_DATA_SOURCE"><subreportParameterExpression><![CDATA[$P{data_source}]]></subreportParameterExpression>
</subreportParameter><subreportExpression><![CDATA[$P{report_book_pages_dir} + "/Content.jasper"]]></subreportExpression>
</p:subreportPart>
</part>
</detail>
These are the fields that I am trying to populate under Content.jrxml:
<pre style="margin-top: 0; margin-left: 1em; padding: 1em; border: 1px groove; background-color: #F8F8F8;line-height: 1.3;">
<field name="group_by" class="java.lang.String"/>
<field name="asset_id" class="java.lang.String"/>
<field name="asset_subject" class="java.lang.String"/>
<field name="feature_group" class="java.lang.String"/>
<field name="component" class="java.lang.String"/>
<field name="sub_component" class="java.lang.String"/>
<field name="reference_maps" class="java.util.List"/>
<field name="release_notes" class="java.lang.String"/>
private JRDataSource GetJasperDataSource() { JRMapArrayDataSource dataSource = null; Map mapDataSource[] = new HashMap[notes.size()]; for(int i = 0; i < notes.size(); i++) { HashMap<String, Object> mappedData = new HashMap<String, Object>(); ReleaseNoteItem item = notes.get(i); if(sortByField.equals("feature_group")) mappedData.put("group_by", item.getFeatureGroup()); else if(sortByField.equals("component")) mappedData.put("group_by", item.getComponent()); else if(sortByField.equals("sub_component")) mappedData.put("group_by", item.getSubComponent()); mappedData.put("asset_type", item.getItemType()); mappedData.put("feature_group", item.getFeatureGroup()); mappedData.put("component", item.getComponent()); mappedData.put("sub_component", item.getSubComponent()); mappedData.put("asset_id", item.getId()); mappedData.put("asset_subject", item.getName()); mappedData.put("reference_maps", item.getReferenceMap());//Used for the table in the content mappedData.put("release_notes", item.getReleaseNotes()); mapDataSource[i] = mappedData; } dataSource = new JRMapArrayDataSource(mapDataSource); return dataSource; }
This is the method that generates the main report, and which the DataSource instance is been passed to:
public static void GenerateReport(JRDataSource dataSource, String reportWarnings, boolean includePreface) throws JRException { // Holds compiled jrxml file. JasperReport jasperReport; // Holds report after filling process. JasperPrint jasperPrint; HashMap<String, Object> jasperParameter = new HashMap<String, Object>(); jasperParameter.put("report_title", reportTitle); jasperParameter.put("product_version", productVersion); jasperParameter.put("build_number_from", buildFromLabel); jasperParameter.put("build_number_to", buildToLabel); jasperParameter.put("report_logo", reportLogoPath); /sperParameter.put("data_source", dataSource); jasperParameter.put("report_book_pages_dir", reportBookPagesDir); jasperParameter.put("report_book_images_dir", reportBookImagesDir); //jasperParameter.put("report_book_pages_dir", reportLogoPath); if(includePreface) { jasperParameter.put("preface", ReadPreface()); } jasperParameter.put("warnings", reportWarnings); jasperReport = JasperCompileManager.compileReport(reportTemplatePath); jasperPrint = JasperFillManager.fillReport(jasperReport, jasperParameter, dataSource); //Create the file dir File file = new File(reportOuputPath); file.getParentFile().mkdirs(); //file.delete(); JasperExportManager.exportReportToPdfFile(jasperPrint, reportOuputPath); }
OK, I believe this is information enough, but let me know if you need more details and I will gladly share more...
I believe my problems is not passing correctly the DataSource to the sub-report therefore, fields are getting nulls values.
Would you please help me?
Thank in advance!
PS. Sorry about the post format I am kind of new posting in this blog...
1 Answer:
Sorry, it took me a long time to post back.
I find a solution after Theodor (Jasper API main author give me some insights) and here is it! So, for the Jasper Report engine to handle multiple data sources passed to the report, you have to take into account 2 essential things:
First, for every data source that you want to pass to the Report, you will need to create a new instance. Jasper engine consumes each data source iterating over all the elements in it. When it gets to the next page, there won't be any data, fields or information to read from and fill up the fields on that particular page. Therefore, information won't show up (null) or "blank", depending on the report template configuration.
Last, make sure you pass a new JREmptyDataSource() when filling the report and pass the data sources instance as parameters, and later as sub-parameters for each individual page. Like this
jasperPrint = JasperFillManager.fillReport(jasperReport, jasperParameter,new JREmptyDataSource() );
That way main report, or the wrapping report (the book), does not use any data source of the pages instances (if it does not need it, of course) and each page will get a data source, through the parameters.
Ultimately, on runtime, it the page of the book can consume individually each data source without affecting each other.
Let me know if this makes any sense? Thanks
What type of datasource are you using? (JSON, CSV, JDBC)
Hello, Javier thanks for the quick reply!
I am using a map, a JRMapArrayDataSource map object that is been filled up in the GetJasperDataSource() method.
The items at that point have information from other processes and that is used to populate the map.
So it's not a file or DB connection I will say is a Bean in any case.