Abort Jasper report generation on NullPointerException - java

I'm creating reports with Jasper Reports (4.0.0) for our project (JRE 1.6.x).
I'm getting bothered with NullPointerExceptions in my scriptlets, as they do not cause the report to abort, they just make the field be silently evaluated to null. As far as I tested, it happens only to NPE's.
The generated reports are quite important and should not have any errors. So, if an exception occurs (like NPE's for some missing data), it should stop the generation, and the database and/or report should be fixed. Such behavior may hide some report coding errors, unless someone spots the missing field.
What is the reason for this behavior with NPE's? Is there any compilation option or execution flag I can switch to make NPE's bubble up as other exceptions do?
I really wish I won't have to wrap every scriptlet method in a try..catch block and throw another exception on NPE's.
Thanks!
Ok, a sample report. It does not uses scriptlets, but generate the NPE directly on a field evaluation (the result is the same), and can be executed directly on iReport preview without parameters:
<?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="NPE_Report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<variable name="NullVariable" class="java.lang.Integer" calculation="System">
<initialValueExpression><![CDATA[null]]></initialValueExpression>
</variable>
<variable name="NotNullVariable" class="java.lang.Integer" calculation="System">
<initialValueExpression><![CDATA[200]]></initialValueExpression>
</variable>
<title>
<band height="72" splitType="Stretch">
<staticText>
<reportElement x="11" y="10" width="179" height="22"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[Successful field evaluation:]]></text>
</staticText>
<textField>
<reportElement x="190" y="10" width="296" height="22"/>
<textElement>
<font size="14"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["0x"+Integer.toHexString($V{NotNullVariable}.intValue()+55)]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="11" y="32" width="179" height="22"/>
<textElement>
<font size="14"/>
</textElement>
<text><![CDATA[NPE on field evaluation:]]></text>
</staticText>
<textField>
<reportElement x="190" y="32" width="296" height="22"/>
<textElement>
<font size="14"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["0x"+Integer.toHexString($V{NullVariable}.intValue()+55)]]></textFieldExpression>
</textField>
</band>
</title>
<detail>
<band height="24" splitType="Stretch"/>
</detail>
</jasperReport>

It doesn't sound like a null pointer expression problem. It sounds like your data source allows null fields. JasperReports is robust enough to handle a report where some information is missing. There is a property you can set so that when information is missing the field prints "null" or is left blank. If you don't want the report to generate at all if the data field is null, modify your data source so the fields are "not null".
Alternatively, drop on a conditional statement so that your scriptlet only runs if th fields are not null and break if they are. Then when the report hits a null field it will stop.

Related

How to print/display MathML expressions?

Currently I'm trying to use a textField with markup="html" but it's not working.
Example
<textField isStretchWithOverflow="true" isBlankWhenNull="true">
<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="100" y="0" width="450" height="25" isPrintWhenDetailOverflows="true" uuid="1aeaa5e9-4136-4239-a301-2733598340d9">
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
<property name="com.jaspersoft.studio.unit.width" value="pixel"/>
</reportElement>
<textElement verticalAlignment="Middle" markup="html">
<paragraph lineSpacing="Single" leftIndent="5" rightIndent="3"/>
</textElement>
<textFieldExpression><![CDATA[$F{question}]]></textFieldExpression>
$F{question} contain:
"<p id="id"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>A</mi><mo>+</mo><mo> </mo><mi>B</mi><mo> </mo><mo> </mo><msqrt><mi>c</mi><mfenced><mrow><mi>d</mi><mfenced open="[" close="]"><mi>r</mi></mfenced></mrow></mfenced></msqrt><mo> </mo><mi>δ</mi><mo> </mo><mo>∞</mo><mi mathvariant="normal">π</mi><mo> </mo></math></p>"
Expected Result :
Result which I get :
The textField does not support MathML, it only support very basic html nor can you use the html component since the JEditorPane on which it's built neither does support MathML
You will need an external library as for example jeuclid, once that you have this library in classpath you can render the xml to a BufferedImage using Converter.render and then display it in jasper report.
This can be done without a java helper class as in this example, hence writting all the code directly in the jrxml on 1 line (using the builder pattern below), but for clarity of example I'm will use external helper class.
Example
java
public class MathML {
public static BufferedImage getImage(String xml, float size) throws IOException, SAXException, ParserConfigurationException {
// Load the string to a node
Element node = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)))
.getDocumentElement();
//Generate the layout parameter
MutableLayoutContext params = new LayoutContextImpl(
LayoutContextImpl.getDefaultLayoutContext());
params.setParameter(Parameter.MATHSIZE, size);
//Render the xml to a BufferedImage
return Converter.getInstance().render(node, params);
}
}
jrxml
<?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="Blank_A4_12" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="8deaea2e-3739-4c4e-b2b5-8c58773ab1a0">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="50" splitType="Stretch">
<image>
<reportElement x="0" y="0" width="100" height="50" uuid="9ee17167-a91e-4725-b36e-a4bba5e24acb">
</reportElement>
<imageExpression><![CDATA[it.jdd.MathML.getImage("<math xmlns='http://www.w3.org/1998/Math/MathML'><mi>A</mi><mo>+</mo><mo> </mo><mi>B</mi><mo> </mo><mo> </mo><msqrt><mi>c</mi><mfenced><mrow><mi>d</mi><mfenced open='[' close=']'><mi>r</mi></mfenced></mrow></mfenced></msqrt><mo> </mo><mi>δ</mi><mo> </mo><mo>∞</mo><mi mathvariant='normal'>π</mi><mo> </mo></math>",70f)]]></imageExpression>
</image>
</band>
</title>
</jasperReport>
Output (export to pdf)

Some currency Symbol in Jasper report is not coming

I have created a jasper report template using jaspersoft studio and I am populating the template using java code. I have some data in the report which needs to be localize and for that I am seeting the "locale" by below code in java.
Locale locale = new Locale("zh", "CN");
templateParameters.put("REPORT_LOCALE", locale); //A map to pass to report
I have also tried -
Locale locale = java.util.Locale.CHINA;
In populated report "Number formatting" is there but currecny symbol is missing(only dollar, pound, euro symbols are coming)
Below is the code I have used in jasper report to populate the text field -
NumberFormat.getCurrencyInstance($P{REPORT_LOCALE}).format($P{Param_Name})
I would be very thankful if someone could pointout the mistake or provide some suggestion.
I believe that your issue related with font supporting.
We should use Font Extensions in case using JRPdfExporter.
I tried to use font with Chinese support and in this case everything is OK.I don't know why using a ton of another fonts is not helping
Example
Java code
Map<String, Object> params = new HashMap<>();
params.put(JRParameter.REPORT_LOCALE, Locale.CHINA);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource());
Report template
There are 4 textFields in jrxml file: two using font with Chinese support and another 2 - without it.
<?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="Show currency" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<parameter name="value" class="java.lang.Double" isForPrompting="false">
<defaultValueExpression><![CDATA[1234.567]]></defaultValueExpression>
</parameter>
<title>
<band height="70">
<textField>
<reportElement x="10" y="10" width="300" height="15"/>
<textElement>
<font fontName="Sharp Dawn"/>
</textElement>
<textFieldExpression><![CDATA[NumberFormat.getCurrencyInstance(new Locale("zh", "CN")).format($P{value})]]></textFieldExpression>
</textField>
<textField>
<reportElement x="10" y="25" width="300" height="15"/>
<textElement>
<font fontName="Sharp Dawn"/>
</textElement>
<textFieldExpression><![CDATA[NumberFormat.getCurrencyInstance($P{REPORT_LOCALE}).format($P{value})]]></textFieldExpression>
</textField>
<textField>
<reportElement x="3" y="40" width="300" height="15"/>
<textFieldExpression><![CDATA[NumberFormat.getCurrencyInstance($P{REPORT_LOCALE}).format($P{value})]]></textFieldExpression>
</textField>
<textField>
<reportElement x="3" y="55" width="300" height="15"/>
<textFieldExpression><![CDATA[NumberFormat.getCurrencyInstance(new Locale("zh", "CN")).format($P{value})]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
Output result
The pdf file generated with help of JRPdfExporter looks like
The Yuan symbol is showing only for first group.

Exporting to Excel with JasperReports: How to add AutoFilter for columns

I am using this code for create report in MS Excel format:
JRXlsExporter exporter = new JRXlsExporter();
From there I don't know if it's possible to tell JasperReports to apply an auto filter on each column.
I was facing the same issue i.e in my spreadsheet(.xls) I wanted to add auto filter to all the columns(15), so I have added one property(Properties expression )name = net.sf.jasperreports.export.xls.auto.filter and value as 'Start' at first column header and same property with value as End at last column header and it worked.
Go to the 'Exporter Parameters' pane and make sure none of the 'Start' or 'Stop' options are set for Auto Filter. Choose the empty space in the related list box (see the attached image). Then run the report again. This time you should see the filters in the right places.
http://community.jaspersoft.com/jaspersoft-studio/issues/6876
JasperReports engine can is able to apply autofilters for columns for MS Excel output format. For applying autofilters we have to use net.sf.jasperreports.export.xls.auto.filter property. We should apply this property for header cells. It is possible to set filter for only one column or for the several columns.
Working example
Datasource
I used the csv datasource in this sample:
language,framework
Java,Guava
Java,Lombok
Java,JasperReports
Java,Spring
Java,Vaadin
C#,ASP.NET MVC
C#,NancyFX
C#,Automapper
JavaScript,AngularJS
JavaScript,React
JavaScript,jQuery
The name of data adapter for this datasource in the example below is frameworks.csv
The report's template
I used Jaspersoft Studio (JSS) for designing a report template.
<?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="excel_filter" pageWidth="595" pageHeight="842" columnWidth="595" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="b521f87a-96ed-43bd-80bd-c7b81ef2e8aa">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="frameworks.csv"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="language" class="java.lang.String"/>
<field name="framework" class="java.lang.String"/>
<columnHeader>
<band height="30" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="278" height="30" uuid="6b8ba60b-3df3-4c78-a780-79ee493ca5f8">
<property name="net.sf.jasperreports.export.xls.auto.filter" value="Start"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<text><![CDATA[Language]]></text>
</staticText>
<staticText>
<reportElement x="278" y="0" width="277" height="30" uuid="731ba580-2168-49f6-b844-d02549d3d83c">
<property name="net.sf.jasperreports.export.xls.auto.filter" value="End"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle"/>
<text><![CDATA[Framework]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="30" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="278" height="30" uuid="7bf9acec-b13a-4261-91c1-0bf6f2c9c784"/>
<textFieldExpression><![CDATA[$F{language}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="278" y="0" width="277" height="30" uuid="d15bd48e-77ee-43df-b11f-4ec1a65811c0"/>
<textFieldExpression><![CDATA[$F{framework}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
I've used the Detail band for showing data. For the first column I set the Start value to the net.sf.jasperreports.export.xls.auto.filter property for staticText in Column Header band (will be the column header in Excel file) and the End value for the second (last) column.
In case using of setting property for only one column the only one filter will be created.
We can easy set property with help of context menu "XLS Tags -> Autofilter -> Start (End)" in JSS.
Output result
The generated output file in MS Excel format contains autofilters for both columns. The file was generated with help of JSS.
Notes:
More information about applying different features for exported Excel files can be found on vendor site

Print an arraylist content with JasperReports

I want to print the content of an ArrayList using JasperReports in Java
Actually I am know little about Jasper Reporting
I use iReport to create Japser Reports and using Java command I will print it.
Now I want to print the student results using JasperReports.
This is my sample results table.
Reg.No SubjectCode Level Semester Grade Marks
132108 CMIS 1113 1 1 A 77
132107 CMIS 1213 1 2 C 57
122101 IMGT 2112 2 1 A 87
122110 IMGT 2213 2 2 A 83
112123 STAT 3113 3 1 C 55
112135 MATH 3213 3 2 B 67
132145 CMIS 1113 1 1 D 17
122118 ELTN 2213 1 2 A 90
112100 CMIS 3213 3 2 A 89
112117 SATA 3113 1 1 A 87
122104 CMIS 2213 2 2 C 54
132104 CMIS 1213 1 2 A 84
So according to my above table I need to print "Results of student in particular level in particular semester".
In my interface I have facility to select the Level and the Semester.
Then the relevant query with generate automatically and results will obtain from the database and using Results object(I create class called 'Results' to store the results of a particular student) I add the results data to a ArrayList.
Now my ArrayList have the Results objects which carries the results of each students in particular level and particular semester.Now I want to print this ArrayList using Jasper report.So expected Jasper Report is like this.For Level 1 and Semester 1,
Reg.No CMIS1113
132108 A
132145 D
For Level 2 and Semester 2,
Reg.No IMGT2213 CMIS2213
122110 A -
122104 - C
Now I have several problems.
1) Normally what I did previously is when I create Jasper Template using iReport I gave the relevant query before creating it.But here query will be changed according to selected Level and Semester.So the result will be changed according to the query.And column headers also changed because subjects are changing.(Number of subject are not similar in each semester and each level)So my question is how can I create a common Jasper Templates to Handle each situation?(if possible)
2) How I print the ArrayList using Java code.I do not know the java code to print the content of ArrayList using Jasper Report.
I know very few things about Jasper Reports.So if you can please help me.Thank You.
you can pass the ArrayList to report as a parameter.
Then in Report create a Subdataset with the same parameter name and type (ArrayList).
Then Create a table component. use the ConnectionExpression:
new net.sf.jasperreports.engine.JREmptyDataSource($P{IN_ARRAY_LIST}.size())
Then map report parameter to table parameter.
Then in TextFields in the table component you can use the expression like that:
$P{IN_ARRAY_LIST}.get($V{REPORT_COUNT})
Make sure that EvaluationTime property of your TextFields is set to now.
UPD:
Short demo report which shows how ArrayList source works:
<?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="ArrayList" language="groovy" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c67d12d3-80cd-46fb-8a79-5c4b0b7c76f9">
<property name="ireport.zoom" value="1.0"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<subDataset name="TableDataset" uuid="628eb9fb-e4f0-4f6c-b5b3-277a14fda6e2">
<parameter name="IN_ARRAY_LIST" class="java.util.ArrayList" isForPrompting="false">
<defaultValueExpression><![CDATA[new java.util.ArrayList()]]></defaultValueExpression>
</parameter>
<variable name="ROW_INDEX" class="java.lang.Integer" resetType="None">
<variableExpression><![CDATA[$V{REPORT_COUNT} - 1]]></variableExpression>
</variable>
</subDataset>
<!-- WHEN YOU CALL YOUR REPORT FROM JAVA, YOU SHOULD PUT YOUR ArrayList into IN_ARRAY_LIST PARAM-->
<parameter name="IN_ARRAY_LIST" class="java.util.ArrayList" isForPrompting="false">
<defaultValueExpression><![CDATA[new java.util.ArrayList()]]></defaultValueExpression>
</parameter>
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="20" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="555" height="20" uuid="d4548efc-5711-42b3-b08a-cb138c5d55cf">
<!-- THIS IS FOR DEMO ONLY - I PUT 2 ROWS INTO ARRAY LIST USING PrintWhenExpression -->
<printWhenExpression><![CDATA[$P{IN_ARRAY_LIST}.add("ROW_1") && $P{IN_ARRAY_LIST}.add("ROW_2")]]></printWhenExpression>
</reportElement>
<text><![CDATA[Report Title]]></text>
</staticText>
</band>
</title>
<pageHeader>
<band height="20" splitType="Stretch"/>
</pageHeader>
<pageFooter>
<band height="20" splitType="Stretch"/>
</pageFooter>
<summary>
<band height="50" splitType="Stretch">
<componentElement>
<reportElement key="table" x="0" y="0" width="555" height="50" uuid="042cdee2-a56a-49af-8a1b-740825446ed5"/>
<jr:table 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="TableDataset" uuid="6f17f8a5-0bcc-4e2a-a900-cdb1e1261d24">
<datasetParameter name="IN_ARRAY_LIST">
<datasetParameterExpression><![CDATA[$P{IN_ARRAY_LIST}]]></datasetParameterExpression>
</datasetParameter>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource($P{IN_ARRAY_LIST}.size())]]></dataSourceExpression>
</datasetRun>
<jr:column width="555" uuid="236aa389-6073-48fa-9b0f-02dcec80551e">
<jr:columnHeader height="30" rowSpan="1">
<staticText>
<reportElement x="0" y="0" width="555" height="30" uuid="18d3f3cc-13fa-4203-b239-45739b1839dc"/>
<text><![CDATA[ArrayList Field Value]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell height="20" rowSpan="1">
<textField>
<reportElement x="0" y="0" width="555" height="20" uuid="a5bd535e-091b-4eef-a0af-e70fc7d2cce2"/>
<textFieldExpression><![CDATA[$P{IN_ARRAY_LIST}.get($V{ROW_INDEX})]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
</band>
</summary>
</jasperReport>
I hope this is clear now.

Calling Java API in the iReport expression

I'm trying to attach a call to a Java library into the iReport expression.
I tried this with a very simple library returning a hello world string.
package utils;
public class Hello {
public static String hello()
{
return "Hello";
}
}
Within iReport, i want to use this API. I compiled the above library into a jar file. Added the location in Tools -> Options -> Classpath.
then tried the following:
Editing the expression in a a text field new utils.Hello().hello()
Creating a new field and setting its type to utils.Hello. Then using the field.hello() in the expression
In both cases, it complains that it cannot resolve hello. However its in the classpath. I've also tried to right click on the report root and add utils.Hello/utils to the Java import directive. Neither of which seemed to pick up the class.
Any advice is greatly appreciated.
Your right expression might be like this:
<textFieldExpression><![CDATA[utils.Hello.hello()]]></textFieldExpression>
The working sample:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport ..>
<queryString>
<![CDATA[SELECT DISTINCT city FROM address ORDER BY city]]>
</queryString>
<field name="CITY" class="java.lang.String"/>
<detail>
<band height="20" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{CITY}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[utils.Hello.hello()]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
You can also add import instruction to the report. In this case the expression will be:
<textFieldExpression><![CDATA[Hello.hello()]]></textFieldExpression>
The working sample:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport ... whenNoDataType="AllSectionsNoDetail">
<import value="utils.Hello"/>
<title>
<band height="41">
<textField>
<reportElement x="188" y="11" width="100" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[Hello.hello()]]></textFieldExpression>
</textField>
</band>
</title>
</jasperReport>
Note: For both samples the jar file (with utils.Hello class) must be in classpath.
More info about using srciptlets you can find here.
You field type should be String , not utils.Hello

Categories

Resources