Search code examples
javajasper-reportsclasscastexceptionjaspersoft-studio

Why do I get error (ClassCastException) when trying to retrive bean from my data adapter?


I created a report using JasperSoft Studio.

I'm referencing to this helpful post Jaspersoft Studio: How to use Collection of Java Beans in data adapter by Alex K

I'd like to retrieve a list of orders. The class Order is defined as in the post:

public class Order {
    private double price;
    private int quantity;
    private Product product;

    // Getters & Setters
}

The report is generated with success if I'd like to retrieve price or quantity. But, once I retrieve product this is displayed:

Error at JSS

Details:

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$20(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

The file sample.jrxml was:

<?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>

The JRBeanCollection is the following:

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;
        }
    // (...)
}

Could you please tell me what is the reason for the exception?


Solution

  • It looks like a bug of Jaspersoft Studio (JSS).

    I think that the reason of getting ClassCastException (look at this part of stacktrace: Caused by: java.lang.ClassCastException: ru.alex.Product cannot be cast to ru.alex.Product) is using of two jar files:

    • the first jar was set for a data provider;
    • second one - via project's build path.

    Yes, it is the same jar file (physically) with the same classes. Looks like the issue of having multiple jar at classpath.

    After understanding the root of the problem we can fix this issue very easy.

    We should stay only one jar with our bean classes - at JSS build path: Build path at JSS

    It means that we should remove the jar from data adapter's properties. Like this:

    Data adapter dialog

    After this it is better to restart JSS.

    For this 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>
    

    we are getting report at JSS successfully:

    Report at JSS


    Everything working fine (without any black magic) at Java project, because we have only single jar with our bean classes at classpath.