为什么在尝试从我的数据适配器检索 bean 时出现错误 (ClassCastException)?
Why do I get error (ClassCastException) when trying to retrive bean from my data adapter?
我使用 JasperSoft Studio 创建了一份报告。
我指的是这个有用的 post by Alex K
我想检索订单列表。 class Order 定义为 post:
public class Order {
private double price;
private int quantity;
private Product product;
// Getters & Setters
}
如果我想检索 价格 或 数量,报告生成成功。但是,一旦我检索到 product,就会显示:
详情:
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression for source text: $F{product}.getName()
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.fillReport(ReportControler.java:530)
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.access(ReportControler.java:505)
...
Caused by: java.lang.ClassCastException: ru.alex.Product cannot be cast to ru.alex.Product
at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:277)
... 14 more
文件 sample.jrxml 是:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.1.final using JasperReports Library version 6.3.1 -->
<!-- 2017-05-18T13:29:14 -->
<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="sample" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ade9e357-e2d0-42bb-ae0d-000b69f4e2e9">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="JavaBeanCollection - orders"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="product" class="ru.alex.Product">
<fieldDescription><![CDATA[product]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.Integer">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="price" class="java.lang.Double">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<title>
<band height="80" splitType="Stretch">
<staticText>
<reportElement x="70" y="49" width="100" height="30" uuid="a19f5b7c-21ed-4c00-a224-af5cf7ef27ec"/>
<text><![CDATA[price]]></text>
</staticText>
<staticText>
<reportElement x="170" y="49" width="100" height="30" uuid="772c4807-25f7-4e7a-8a10-eba5232b92c7"/>
<text><![CDATA[quantity]]></text>
</staticText>
<staticText>
<reportElement x="270" y="49" width="140" height="30" uuid="613da9ef-6a5a-45b2-8c8f-c3cd450e66ed"/>
<text><![CDATA[product]]></text>
</staticText>
</band>
</title>
<detail>
<band height="130" splitType="Stretch">
<textField>
<reportElement x="70" y="0" width="100" height="30" uuid="a594224b-c015-4dab-b52b-6e317e76cea3"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="170" y="0" width="100" height="30" uuid="b60503ca-f6bc-48dc-ad01-178d9befd805"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="270" y="0" width="140" height="30" uuid="480bfb2f-2831-4700-8adc-f818bbbf6592"/>
<textFieldExpression><![CDATA[$F{product}.getName()]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
JRBeanCollection如下:
public class MyImplementation implements JRDataSource {
// (...)
public static Collection<Order> getOrders() {
List<Order> orders = new ArrayList<Order>();
orders.add(new Order(1, "aa", new BigDecimal("1111.11"), 2, new Product("apples")));
orders.add(new Order(2, "bb", new BigDecimal("2222.22"), 10, new Product("oranges")));
return orders;
}
// (...)
}
请问异常的原因是什么?
这看起来像是 Jaspersoft Studio (JSS) 的错误。
我认为得到 ClassCastException 的原因(查看堆栈跟踪的这一部分:Caused by: java.lang.ClassCastException: ru.alex.Product cannot be cast to ru.alex.Product
)是使用两个 jar 个文件:
- 第一个 jar 是为数据提供者设置的;
- 第二个 - 通过项目的构建路径。
是的,它是同一个 jar 文件(物理上)与相同的 类。看起来像是在类路径中有多个 jar 的问题。
了解问题的根源后,我们可以很容易地解决这个问题。
我们的 bean 类 应该只保留一个 jar - 在 JSS 构建路径:
这意味着我们应该从数据适配器的属性中删除 jar。像这样:
之后最好重新启动 JSS.
为此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="Report with Bean" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="JavaBeanCollection - orders"/>
<field name="product" class="ru.alex.Product">
<fieldDescription><![CDATA[product]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.Integer">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="price" class="java.lang.Double">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<detail>
<band height="30" splitType="Stretch">
<textField>
<reportElement x="10" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="110" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="210" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{product}.getName()]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
我们在 JSS 成功收到报告:
在 Java 项目中一切正常(没有任何黑魔法),因为我们只有一个 jar bean 类 在类路径中。
如果其他人正在寻找解决方案,我的设置略有不同,因此解决方案也略有不同(尽管是同一个根本问题)。
我的设置包括 -
我的主要项目以及我在报告中需要的所有 classes/subclasses。
带有用于加载报告对象的 bean 工厂的单独项目。
指向#2 中工厂方法的数据适配器(无 jar 文件)。
在彼此的构建路径中包含项目 1 和 2。
我可以通过将工厂 class/method 从项目 2 移到项目 1 并完全删除项目 2 来修复它。我正在使用 eclipse 插件,但是直到我重新启动 eclipse 才起作用。
我使用 JasperSoft Studio 创建了一份报告。
我指的是这个有用的 post
我想检索订单列表。 class Order 定义为 post:
public class Order {
private double price;
private int quantity;
private Product product;
// Getters & Setters
}
如果我想检索 价格 或 数量,报告生成成功。但是,一旦我检索到 product,就会显示:
详情:
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression for source text: $F{product}.getName()
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.fillReport(ReportControler.java:530)
at com.jaspersoft.studio.editor.preview.view.control.ReportControler.access(ReportControler.java:505)
...
Caused by: java.lang.ClassCastException: ru.alex.Product cannot be cast to ru.alex.Product
at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:277)
... 14 more
文件 sample.jrxml 是:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.3.1.final using JasperReports Library version 6.3.1 -->
<!-- 2017-05-18T13:29:14 -->
<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="sample" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ade9e357-e2d0-42bb-ae0d-000b69f4e2e9">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="JavaBeanCollection - orders"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="product" class="ru.alex.Product">
<fieldDescription><![CDATA[product]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.Integer">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="price" class="java.lang.Double">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<title>
<band height="80" splitType="Stretch">
<staticText>
<reportElement x="70" y="49" width="100" height="30" uuid="a19f5b7c-21ed-4c00-a224-af5cf7ef27ec"/>
<text><![CDATA[price]]></text>
</staticText>
<staticText>
<reportElement x="170" y="49" width="100" height="30" uuid="772c4807-25f7-4e7a-8a10-eba5232b92c7"/>
<text><![CDATA[quantity]]></text>
</staticText>
<staticText>
<reportElement x="270" y="49" width="140" height="30" uuid="613da9ef-6a5a-45b2-8c8f-c3cd450e66ed"/>
<text><![CDATA[product]]></text>
</staticText>
</band>
</title>
<detail>
<band height="130" splitType="Stretch">
<textField>
<reportElement x="70" y="0" width="100" height="30" uuid="a594224b-c015-4dab-b52b-6e317e76cea3"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="170" y="0" width="100" height="30" uuid="b60503ca-f6bc-48dc-ad01-178d9befd805"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="270" y="0" width="140" height="30" uuid="480bfb2f-2831-4700-8adc-f818bbbf6592"/>
<textFieldExpression><![CDATA[$F{product}.getName()]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
JRBeanCollection如下:
public class MyImplementation implements JRDataSource {
// (...)
public static Collection<Order> getOrders() {
List<Order> orders = new ArrayList<Order>();
orders.add(new Order(1, "aa", new BigDecimal("1111.11"), 2, new Product("apples")));
orders.add(new Order(2, "bb", new BigDecimal("2222.22"), 10, new Product("oranges")));
return orders;
}
// (...)
}
请问异常的原因是什么?
这看起来像是 Jaspersoft Studio (JSS) 的错误。
我认为得到 ClassCastException 的原因(查看堆栈跟踪的这一部分:Caused by: java.lang.ClassCastException: ru.alex.Product cannot be cast to ru.alex.Product
)是使用两个 jar 个文件:
- 第一个 jar 是为数据提供者设置的;
- 第二个 - 通过项目的构建路径。
是的,它是同一个 jar 文件(物理上)与相同的 类。看起来像是在类路径中有多个 jar 的问题。
了解问题的根源后,我们可以很容易地解决这个问题。
我们的 bean 类 应该只保留一个 jar - 在 JSS 构建路径:
这意味着我们应该从数据适配器的属性中删除 jar。像这样:
之后最好重新启动 JSS.
为此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="Report with Bean" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="JavaBeanCollection - orders"/>
<field name="product" class="ru.alex.Product">
<fieldDescription><![CDATA[product]]></fieldDescription>
</field>
<field name="quantity" class="java.lang.Integer">
<fieldDescription><![CDATA[quantity]]></fieldDescription>
</field>
<field name="price" class="java.lang.Double">
<fieldDescription><![CDATA[price]]></fieldDescription>
</field>
<detail>
<band height="30" splitType="Stretch">
<textField>
<reportElement x="10" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{quantity}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="110" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="210" y="0" width="100" height="30"/>
<textFieldExpression><![CDATA[$F{product}.getName()]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
我们在 JSS 成功收到报告:
在 Java 项目中一切正常(没有任何黑魔法),因为我们只有一个 jar bean 类 在类路径中。
如果其他人正在寻找解决方案,我的设置略有不同,因此解决方案也略有不同(尽管是同一个根本问题)。
我的设置包括 -
我的主要项目以及我在报告中需要的所有 classes/subclasses。
带有用于加载报告对象的 bean 工厂的单独项目。
指向#2 中工厂方法的数据适配器(无 jar 文件)。
在彼此的构建路径中包含项目 1 和 2。
我可以通过将工厂 class/method 从项目 2 移到项目 1 并完全删除项目 2 来修复它。我正在使用 eclipse 插件,但是直到我重新启动 eclipse 才起作用。