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

2

1

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?

Triumvirate answered 18/5, 2017 at 11:58 Comment(8)
Error evaluating expression for source text: $F{product}.getName() - Do you have public getter for name field? Looks like you are using my sample :)Achaea
You should post the small jrxml to reproduce the problemAchaea
Hello Sir @AlexK, Big thanks for your great sample, this helped me a lot. I did as you presented, only I found a problem if I retrieved product. Yes, I have public getter for name field. I made changes on my question, could you please take a look: I shared the file sample.jrxml ? Thanks a lot Sir.Triumvirate
Consider using BigDecimal instead of double. https://mcmap.net/q/37337/-why-not-use-double-or-float-to-represent-currencyCavour
Hello Sir @DaveJarvis, thanks a lot for your reply but my problem isn't with price, the report is generated with success once I talk about price . Only I found problem when I want to retrieve Product which has name with String type.Triumvirate
@Sinda: I did not mean to imply the problem was with price. I meant to imply that you should review the code base to make sure that prices are not being stored as doubles because that'll cause other problems down the road.Cavour
Hello Sir @DaveJarvis, I change the type of price from double to BigDecimal, but I obtain the same exception.Triumvirate
Thanks a lot Sir @AlexK for your kindness, but if you never mind could you please tell me if my jrxml contains error, why it worked as well with all the fields and failed if I want to retrieve the product's name associated to an order ?. I have a doubt that the cause comes from the file pom.xml of my project. I made change on my question. If you never mind Sir could you please take a look. Big thanks Sir.Triumvirate
A
2

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.

Achaea answered 20/5, 2017 at 11:26 Comment(1)
Hello Sir @AlexK, thanks a lot Sir for your help as well as your kindness. You make me soo happy. And I'm soo sorry to waste your time. Really, I found another solution to retrieve the name of product (On the class Order I made String name instead of Product product, then I made same changes on the class OrderFactory, So the mein gives the desired result however it isn't optimised). Thereby, Big Big thanks Sir. You're honestly the best of the best on StackOverFlow. Greetings.Triumvirate
A
0

If anybody else is looking for a solution to this, I had a slightly different setup and so had a slightly different solution (same root problem though).

My setup included -

  1. My main project with all of the classes/subclasses I needed in my report.

  2. A separate project with the bean factory used to load the objects for the report.

  3. A data adapter pointing to the factory method in #2 (no jar file).

  4. Included project 1 and 2 in each others' build paths.

I was able to fix it by moving the factory class/method from project 2 into project 1 and deleting project 2 altogether. I was using the eclipse plugin, but this didn't work until I restarted eclipse.

Aplomb answered 3/10, 2018 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.