TIBCOSoftware / jasperreports

JasperReports® - Free Java Reporting Library
https://community.jaspersoft.com/downloads/community-edition/
GNU Lesser General Public License v3.0
1.07k stars 404 forks source link

Issue with Java Records Not Supported by JRBeanCollectionDataSource #486

Closed StanchevDimitar closed 1 month ago

StanchevDimitar commented 1 month ago

Description:

I encountered an issue using Java records with JRBeanCollectionDataSource in JasperReports (version 7.0.1).

Problem: Java records do not work with JRBeanCollectionDataSource because they lack standard JavaBean-style getters (e.g., getXyz() methods). Instead, records use component methods, which JasperReports cannot detect using reflection. When I pass a record class to JRBeanCollectionDataSource, it throws the following exception:

Caused by: java.lang.NoSuchMethodException: Unknown property 'xyz' on class 'class com.contract.dto.DTOClass'
    at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1270)
    at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:809)
    at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:885)
    at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:464)
    at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getBeanProperty(JRAbstractBeanDataSource.java:155)

Steps to Reproduce: 1) Define a record in Java: public record DTOClass(String xyz){}

2) Attempt to pass the record as a data source using JRBeanCollectionDataSource:

DTOClass recordClass = new DTOClass("xyz");
JRBeanCollectionDataSource collection= new JRBeanCollectionDataSource(List.of(recordClass));

3) The exception occurs because JasperReports uses standard JavaBean conventions and the record's component methods.

Expected Behavior:

JRBeanCollectionDataSource should be able to handle Java records or there should be a documented alternative approach to working with records.

Workaround: 1) Convert records into a standard JavaBean class before passing them to JasperReports. 2) Map record fields into Map<String, Object> and use the map as the data source.

However, these workarounds defeat the purpose of using records for concise data representation.

Suggested Solution: It would be great if JasperReports could provide out-of-the-box support for Java records, either by:

1) Supporting component methods in record classes for reflection. 2) Allowing a custom data source that directly handles records.

Environment: JasperReports version: 7.0.1 Java version: 21 Spring Boot version: 3.3.4

teodord commented 1 month ago

Hi,

I am not sure why you assumed JRBeanCollectionDataSource should work with Java records. Its name is very clear and states upfront what the underlying data should be: a collection of Java beans.

A JasperReports data source supporting Java records would in turn have a self-explanatory name such as JRJavaRecordsCollectionDataSource or something similar.

Since we don't have such data source implementation, I can only assume you are asking us to implement one. Reporting the issue as a problem with the existing bean data source implementations does not make much sense to me and if we leave it here as a bug report, I would have to reject it as "not applicable".

With Java records feature being introduced in Java 14 and with our project still being compatible with Java 1.8, such feature could not be implemented in the core library, but most likely in an optional extension that requires at least Java 14.

We are open to contributions, so if are familiar with this Java feature, please help if you can.

Thank you, Teodor