如何修复将 JavaBean 作为报告参数传递的异常?

How to fix exception on passing JavaBean as parameter of report?

我需要放一些复杂的(任意的,pojo)对象来报告。为此,我尝试使用 parameter 标签,但它不起作用。我尝试 google 这个,但我创建了具有简单参数类型(例如 String 或 Long)或使用一些数据源的示例,但我认为我不需要它只用于 1 个对象。

我的 pojo 是:

public class CaseDescription {

private final Long id;
private final String logoPath;
private final String userName;
private final String location;

public CaseDescription(final Long id, final String logoPath, final String userName, final String location) {
    this.id = id;
    this.logoPath = logoPath;
    this.userName = userName;
    this.location = location;
}

public Long getId() {
    return this.id;
}

public String getLogoPath() {
    return this.logoPath;
}

public String getUserName() {
    return this.userName;
}

public String getLocation() {
    return this.location;
}

}

我的 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="cool_name" pageWidth="595" pageHeight="842" orientation="Landscape" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="13acf49e-4913-4d1b-bccc-113817ad15d1">
...
<parameter name="caseDescription" class="path.to.case.description.package.CaseDescription" isForPrompting="false"/>
...
<group name="Group1">
    ...
    <textField>
        <reportElement style="SubTitle" stretchType="ContainerBottom" x="0" y="30" width="451" height="29" forecolor="#000000" uuid="4636f2b9-3394-42cd-ac90-e34f582b2272"/>
        <textElement textAlignment="Left">
            <font size="22" isBold="false"/>
        </textElement>
        <textFieldExpression><![CDATA["Accused : " + $P{caseDescription.userName}]]></textFieldExpression>
    </textField>
    ...
</group>
...
</jasperReport>

我尝试通过以下代码生成文档:

final CaseDescription caseDescription = new CaseDescription(1L, "Some", "Gump", "Forrest");
Map<String, Object> parameters = new HashMap<>();
parameters.put("caseDescription", caseDescription);
JasperDesign jasperDesign = JRXmlLoader.load(resourceAsStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());
JasperExportManager.exportReportToPdfFile(jasperPrint, pathForSaving);

我得到了以下异常:

net.sf.jasperreports.engine.design.JRValidationException: Report design not valid : 
 1. Parameter not found : caseDescription.userName
at net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign(JRAbstractCompiler.java:280)
at net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:152)
at net.sf.jasperreports.engine.JasperCompileManager.compile(JasperCompileManager.java:357)
at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:617)

但是,如果我将 caseDescription.username 替换为 caseDescription,则此字段将使用 caseDescription.toString()caseDescription.getUserName() 之类的 Cahnge 也不起作用。谁能解释我做错了什么?

你应该像考虑 Java 对象一样考虑 JasperReports 的参数。

您需要调用对象的方法(class)。在您的情况下,您需要致电 public getter CaseDescription.getUserName().

您可以这样更改表达式:

<textField>
    <reportElement x="0" y="30" width="451" height="29"/>
    <textFieldExpression><![CDATA["Accused : " + $P{caseDescription}.getUserName()]]></textFieldExpression>
</textField>

或者像这样

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" ...>
...
    <import value="your.package.name.CaseDescription"/>
...
    <parameter name="caseDescription" class="java.lang.Object"/>
...
    <textField>
        <reportElement x="0" y="30" width="451" height="29"/>
        <textFieldExpression><![CDATA["Accused : " + ((CaseDescription) $P{caseDescription}).getUserName()]]></textFieldExpression>
    </textField>
...
</jasperReport>

注:

为了能够使用 class 的简单名称(不是完全限定的名称),您需要在 jrxml 文件中添加 <import value="your.package.name.CaseDescription"/>