Jasperserver report execution service with collection parameter - jasper-reports

I have some trouble generating jasper report when i try to pass more than on value to a collection type parameter in my request body.
In my rapport my parameter is decribed like this
<parameter name="skillList" class="java.util.Collection" nestedType="java.lang.String">
<parameterDescription><![CDATA[list of skill]]></parameterDescription>
</parameter>
In jaspersoft studio when i tried to visualize my report and add more value it work well and my report is generated
But when i try to use the execution service of the server using HTTP POST with a request body like this one :
<reportExecutionRequest>
<reportUnitUri>MyReportURI</reportUnitUri>
<async>false</async>
<outputFormat>pdf</outputFormat>
<parameters>
<reportParameter name="title">
<value>--- titre test ---</value>
</reportParameter>
<reportParameter name="header">
<value>### header test ###</value>
</reportParameter>
<reportParameter name="name">
<value>LE TUTOUR</value>
</reportParameter>
<reportParameter name="surname">
<value>Erwan</value>
</reportParameter>
<reportParameter name="skillList">
<value>java</value>
<value>maven</value>
</reportParameter>
</parameters>
</reportExecutionRequest>
If I have only one value in the skillList parameter my rapport is well generated, but when I add another one I have a HTTP 400 bad request.
In the documentation of the service there is many exemple with more than one value so i don't understand why my repport is not generated.
If someone have a solution or have encountered the same issue and solved it i woul not say no to some help.
edit
In a new attempt I changed my parameter, it's now a subdataset
<subDataset name="listSkill" uuid="8027f62e-3b29-4faf-b11a-185b4db46d6f">
<field name="skill" class="java.lang.String">
<fieldDescription><![CDATA[_THIS]]></fieldDescription>
</field>
</subDataset>
and the way to use it
<componentElement>
<reportElement x="0" y="200" width="100" height="30" uuid="26b52f0f-e1e0-451e-9183-2df0f1f1ce65"/>
<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
<datasetRun subDataset="listSkill" uuid="593d4d96-cbaf-46ba-94ef-97344e0cb4f2">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{skills}) ]]></dataSourceExpression>
</datasetRun>
<jr:listContents height="30" width="100">
<textField>
<reportElement x="0" y="0" width="100" height="30" uuid="061f84d9-205a-4f49-a711-1f657b1fa5fd"/>
<textFieldExpression><![CDATA[$F{skill}]]></textFieldExpression>
</textField>
</jr:listContents>
</jr:list>
</componentElement>
still work in jaspersoft studio when I generate my report, but not when in try to execute it, using the REST API of the server.

Solved this:
Now I only pass 1 parameter to my rapport, a json string with all my parameters as fields.
I use a data adapter that match that string and replaced all the $P{xxxx} by $F{xxxx}.
Then I use the JSON_INPUT_STREAM parameter of the report to cast that string to byte array input stream.
In this json string, my lists object are described like this
"LIST_SKILL": [
["skill one", "value 1"],
["skill two", "value 2"],
["skill three", "value 3"]
]
Then on my list object, in the dataSet properties::JRDatasource expression
((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("LIST_SKILL")
After that, my report is correctly generated in jaspersoft studio / server and with rest service call.

Related

Maps component is not working in Jasper 6.2.0

We need a help to execute the maps in jasper report
We have used below command which is working fine in 6.2.0 (10/6/2018).
Now it is stop to display map and getting error. Hence we added map.key to resolve and also experimented with latest map component, but not able get map as previously.
Could you please help us to resolve this issue.
Thank you
Map key data
<property name="net.sf.jasperreports.components.map.key" value="AIzaSy**********5w"/>
<property name="net.sf.jasperreports.components.map.version" value="3"/>
map component added in summary
<componentElement>
<reportElement x="0" y="0" width="572" height="680" uuid="d66b99c0-0651-47f0-954f-90fc23b4a344">
<printWhenExpression><![CDATA[$F{row_num}!= null]]></printWhenExpression>
</reportElement>
<c:map xmlns:c="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" evaluationTime="Band" mapType="hybrid">
<c:latitudeExpression><![CDATA[Float.parseFloat($F{center_lat})]]></c:latitudeExpression>
<c:longitudeExpression><![CDATA[Float.parseFloat($F{center_lng})]]></c:longitudeExpression>
<c:zoomExpression><![CDATA[Integer.parseInt($P{ZOOM})]]></c:zoomExpression>
<c:markerData>
<dataset/>
<c:item>
<c:itemProperty name="latitude">
<valueExpression><![CDATA[Float.parseFloat($F{latitude})]]></valueExpression>
</c:itemProperty>
<c:itemProperty name="longitude">
<valueExpression><![CDATA[Float.parseFloat($F{longitude})]]></valueExpression>
</c:itemProperty>
<c:itemProperty name="label">
<valueExpression><![CDATA[$F{row_num}]]></valueExpression>
</c:itemProperty>
</c:item>
</c:markerData>
</c:map>
</componentElement>

How to center align barcode using jasperreports and barcode4j

I use iReport 5.5.0. How to center align a barcode component?
Relevant fragment of my jrxml is below.
<componentElement>
<reportElement x="0" y="9" width="113" height="36" uuid="a11badb4-7c31-4011-83ae-f287b457939a"/>
<jr:Code128 xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" textPosition="bottom">
<jr:codeExpression><![CDATA[$F{number}]]></jr:codeExpression>
</jr:Code128>
</componentElement>
Create a style, let's call it "Barcode", like:
<style name="Barcode" fontName="Helvetica" fontSize="10" hAlign="Center" vAlign="Middle"/>
and set the style property of your barcode element to "Barcode".

Print footer on first page only

I would like to have a footer appear only on the first page of jasper reports.
After searching the forums, I have seen this question asked and improperly answered several times here. As many have suggested I have tried putting a print when expression on the footer band to prevent it from printing when it isn't the first page like:
new Boolean($V{PAGE_NUMBER}.intValue() == 1)
This does not work though. The result is that none of the attributes of the page footer print, but the footer block still prints and takes up space preventing the detail from using the whole page. Effectively, you have a footer with data on the first page and a footer with no data on every following page.
Does anyone know a trick how to actually make this work?
Definitely there does not seem to be a direct way of achieving it, at least with current version of Jasper libraries available. However here's a very crude workaround that worked for us in a similar requirement. I separated out only the footer management part of the code into a sample project this morning and it works fine.
Notes:
Not sure if this works with complex reports (especially if column-footer needs to be printed, as we manually modify the columnFooterOffsetY value). We had to generate a simple report with only title, detail and footer bands.
Importantly, i do not recommend using this solution for complex requirements as it may induce maintainability issues in long run (especially if you migrate to a later version of jasperreports library in future which might have modified the report-filling logic).
I have used JasperReports library version 5.0.0 for the testing.
How the example is built:
Created JRXML with iReport, with a printwhenexpression, new Boolean($V{PAGE_NUMBER}.intValue() == 1, for the page-footer band.
Created a Custom report-filler instance, extending the JRVerticalFiller class.
Sample source XML used: (add additional lines to the XML so that the report wraps to multiple pages)
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1001" name="AAA" email="aaa#somecorp.com" salary="20500.125"/>
<employee id="1002" name="BBB" email="bbb#somecorp.com" salary="10000.500"/>
<employee id="1003" name="CCC" email="ccc#somecorp.com" salary="12275.750"/>
<employee id="1004" name="DDD" email="ddd#somecorp.com" salary="10750.750"/>
</employees>
JRXML created with iReport (with a printwhenexpression for the footer band):
<?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="jr_footer_display_test" pageWidth="792" pageHeight="288" orientation="Landscape" columnWidth="752" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="27ac3ae2-27da-484b-b088-b4d79aa973cc">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<queryString language="xPath">
<![CDATA[//employee]]>
</queryString>
<field name="email" class="java.lang.String">
<fieldDescription><![CDATA[./#email]]></fieldDescription>
</field>
<field name="id" class="java.lang.String">
<fieldDescription><![CDATA[./#id]]></fieldDescription>
</field>
<field name="name" class="java.lang.String">
<fieldDescription><![CDATA[./#name]]></fieldDescription>
</field>
<field name="salary" class="java.lang.String">
<fieldDescription><![CDATA[./#salary]]></fieldDescription>
</field>
<background>
<band splitType="Stretch"/>
</background>
<columnHeader>
<band height="50">
<staticText>
<reportElement uuid="c3d42e71-672e-402f-9fbb-4889be2a269b" x="29" y="2" width="100" height="20"/>
<textElement/>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement uuid="a4c42dc4-4276-485a-b5a6-b4e6bd2bc217" x="136" y="2" width="100" height="20"/>
<textElement/>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement uuid="157e527b-7ad5-46bf-a06d-2fa0a2686b1e" x="253" y="2" width="100" height="20"/>
<textElement/>
<text><![CDATA[Email]]></text>
</staticText>
<staticText>
<reportElement uuid="4d87c542-7057-4bc1-9a7e-fbd6a554f33a" x="386" y="2" width="100" height="20"/>
<textElement/>
<text><![CDATA[Salary]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="21" splitType="Stretch">
<textField>
<reportElement uuid="31d09543-a128-469a-be38-3d8987ba781b" x="29" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="ce5c11f8-68da-4efd-93fa-e1f1b5ce407f" x="136" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="300dcc3b-8a2a-489d-8518-7283c95b2f88" x="253" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="a37f2df9-2459-446d-bc47-488a336aa60e" x="386" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{salary}]]></textFieldExpression>
</textField>
</band>
</detail>
<pageFooter>
<band height="40" splitType="Stretch">
<printWhenExpression><![CDATA[new Boolean($V{PAGE_NUMBER}.intValue() == 1)]]></printWhenExpression>
<textField>
<reportElement uuid="3d9beff7-69b8-44d9-af80-2962b9262368" x="29" y="12" width="80" height="20"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA["Page: "+$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>
Custom report-filler implementation: (this handles the height resetting logic to ensure detail band stretches longer from page 2 onwards)
public class CustomVerticalFiller extends JRVerticalFiller {
private JRFillBand detailBand = null;
private int pageNumber = -1;
protected CustomVerticalFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport) throws JRException {
super(jasperReportsContext, jasperReport);
detailBand = detailSection.getFillBands()[0];
}
// this method gets called after each detail band row is filled
protected void resolveBandBoundElements(JRFillBand band, byte evaluation) throws JRException {
if(band == detailBand) {
if((detailBand.getBreakHeight() > columnFooterOffsetY - offsetY) && (columnIndex == columnCount - 1)) {
// we have reached end of a page
pageNumber++;
// we reset the offset when we are at the end of page 2, so that jasper continues to fill data
if(pageNumber == 1) {
columnFooterOffsetY += pageFooter.getHeight();
}
}
}
}
}
And the Java code that actually uses the custom filler to export a PDF:
InputStream inputStream = new FileInputStream(new File(<my jrxml file path>));
JRDataSource dataSource = new JRXmlDataSource(new File(<my source xml file path>), "//employee");
Map parameters = new HashMap();
JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
CustomVerticalFiller customVerticalFiller = new CustomVerticalFiller(DefaultJasperReportsContext.getInstance(), jasperReport);
JasperPrint jasperPrint = customVerticalFiller.fill(parameters, dataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, <target pdf file path>);
You should put this code on Band Properties Print when expression of PageFooter
new Boolean( $V{PAGE_NUMBER}.intValue() == 1 )
Unfortunately #emecheon answer doesn't work with current jasper version ( I use 6.7.0), but cure is pretty much the same.
I change columnFooterOffsetY after first page.
This way you can have footer of different size for each page.
public class CustomVerticalFiller extends JRVerticalFiller {
private int pageNumber = 0;
public CustomVerticalFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport) throws JRException {
super(jasperReportsContext, jasperReport);
}
#Override
protected void addPage(JRPrintPage page) {
super.addPage(page);
pageNumber++;
if (pageNumber == 2) {
columnFooterOffsetY += pageFooter.getHeight();
}
}
}
The expression I use to print a footer only on the first page is the following:
In the Print When Expression field
IF($V{PAGE_NUMBER}.intValue()==1,TRUE( ),FALSE( ))
It checks whether this is the first page and if so it returns true and prints the band. If not, it does not print anything.
If you would like to print one footer on the first page and a different one on the following pages. I use this code as the expression for the subreport properties. (not print when expression)
IF($V{PAGE_NUMBER}.intValue()==1,"subreportFooter1.jasper","subreportFooter2.jasper")

PieChart: When and how we should use Increment Type?

The code of my servlet:
JasperCompileManager.compileReportToFile(jrxmlSourcePathMain,
jrxmlDestPathMain);
InputStream isRef = new FileInputStream(new File(jrxmlDestPathMain));
ServletOutputStream sosRef = response.getOutputStream();
response.setContentType("application/pdf");
JasperRunManager.runReportToPdfStream(isRef, sosRef, new HashMap(),
new JRBeanCollectionDataSource(buyBookInfoList));
sosRef.flush();
sosRef.close();
The snippet of jrxml file:
<summary>
<band height="265" splitType="Stretch">
<pieChart>
<chart isShowLegend="true" renderType="svg" theme="default">
<reportElement uuid="c6a09cc9-bd15-4b09-8657-05868a148f18" x="0" y="0" width="554" height="265"/>
<chartTitle position="Top" color="#FF0000">
<font fontName="宋体" size="18" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
<titleExpression><![CDATA["报表演示"]]></titleExpression>
</chartTitle>
<chartSubtitle color="#0000FF">
<font fontName="宋体" size="14" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
<subtitleExpression><![CDATA["子标题"]]></subtitleExpression>
</chartSubtitle>
<chartLegend textColor="#33FF33" backgroundColor="#6666FF" position="Right">
<font size="12" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</chartLegend>
</chart>
<pieDataset>
<keyExpression><![CDATA[$F{username}]]></keyExpression>
<valueExpression><![CDATA[$F{buyBookNum}]]></valueExpression>
</pieDataset>
<piePlot isShowLabels="true" isCircular="false" labelFormat="姓名为:{0}">
<plot orientation="Horizontal" labelRotation="180.0"/>
<itemLabel/>
</piePlot>
</pieChart>
</band>
</summary>
I set Increment Type property for PieChart value with different values: none, report, page. But I did not notice any difference in generated reports.
So my question is how to use the PieChart's Increment Type property?
What is a purpose of this property?
The increment type allows you to tell the pie chart when to select values to use. For example, if you want to create a pie chart that shows sales in the USA, Canada, and Mexico, you might increment over a "country" group.

Displaying object as image inside a list component

Problem
I have to display an object as an image inside a list component based on a particular count (intNote). While using an image path from specific location the images are displayed.
Question
How can I display an object as an image inside a list component?
Source
The JRXML:
<subDataset name="Q2">
<field name="strVert" class="java.awt.Image"/>
</subDataset>
<field name="intNote" class="java.lang.Integer"/>
<componentElement>
<reportElement x="130" y="72" width="25" height="35"/>
<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Horizontal" ignoreWidth="true">
<datasetRun subDataset="Q2">
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource($F{intNote})]]></dataSourceExpression>
</datasetRun>
<jr:listContents height="35" width="25">
<image isUsingCache="false">
<reportElement x="3" y="10" width="16" height="17" forecolor="#FFFFFF"/>
<graphicElement>
<pen lineWidth="1.25"/>
</graphicElement>
<imageExpression class="java.awt.Image"><![CDATA[$F{strVert}]]></imageExpression>
</image>
</jr:listContents>
</jr:list>
</componentElement>
Thank you.
In jasper you can display images by putting the current image location instead of the varible intNote.it is the only possible way to get the image in the output.
Try to make $F{strVert} class as java.io.InputStream