Pro Grammer
Pro Grammer

Reputation: 31

Passing dataSet to SubReport in Jasper

I have a Student object contain a list of Courses and i need to display Student List with the list of courses of each student in a report.

Student Class

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private String email;
    private List<Course> courseList;
}

Course class

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Course {
    private String name;
    private String location;
    private BigDecimal price;
}

StudentGenerator To generate PDF

@Component
public class StudentGenerator {
    public ResponseEntity<byte[]> getMyPdf() throws ParseException, FileNotFoundException, JRException {
        List<Student> students = getStudents(); // Student Factory
        
        Map<String, Object> parameters = new HashMap<>();
        
        parameters.put("title", "MY REPORT");
        JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(students, false);
        JasperReport compileReport = JasperCompileManager.compileReport(
                new FileInputStream("myFile.jrxml"));
        JasperPrint jasperPrint = JasperFillManager.fillReport(compileReport, parameters, beanCollectionDataSource);
        byte data[] = JasperExportManager.exportReportToPdf(jasperPrint);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "inline; filename=my_pdf.pdf");

        return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(data);
    }
}

In Jasper I create My Main Report

enter image description here

To Link My SubReport to Main Report, I added In SubReport Data Source Expression the expression :

enter image description here

And Finally, i added course fields in SubReport :

enter image description here

But When i run the project, i got this error that i don't understand:

java.lang.ClassNotFoundException: net.sf.jasperreports.compilers.ReportExpressionEvaluationData
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
    at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
    at java.base/java.lang.Class.forName(Class.java:467) ~[na:na]
    at java.base/java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:778) ~[na:na]
    at net.sf.jasperreports.engine.util.ContextClassLoaderObjectInputStream.resolveClass(ContextClassLoaderObjectInputStream.java:89) ~[jasperreports-6.7.0.jar:6.6.0]
    at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2045) ~[na:na]

I got the error only when i add the SubReport !

Many Thanks for any help

Upvotes: 0

Views: 1213

Answers (1)

Mateus Bodanese
Mateus Bodanese

Reputation: 37

this error is happening because you are passing the subreport to the TITLE variable.

The most common way to pass a subreport via java to jasper is by variable, so I recommend doing it this way.

JasperReport jasperMasterReport = JasperCompileManager.compileReport(master);
JasperReport jasperSubReport = JasperCompileManager.compileReport(sub);

Map<String, Object> map = new HashMap<String, Object>();

map.put("SUBREPORT_DIR",  jasperSubReport);
JasperPrint print  = JasperFillManager.fillReport(jasperMasterReport, map, buildDatasource(data));

in your jasper wait the sub this way

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false"/>

<subreport>
            <reportElement positionType="Float" x="1" y="0" width="553" height="20" uuid="dcb4de43-b64f-4e50-a4b1-5ad31a1cd9a2"/>
            <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JsonDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("carga.ordens")]]></dataSourceExpression>
            <subreportExpression><![CDATA[$P{SUBREPORT_DIR}]]></subreportExpression>
</subreport>

this way the map will send its jasper (already compiled) to the variable SUBREPORT_DIR

how your expression editor will look

expression editor

how your datasource

datasource expression

in my case i use jsondatasource, but you can adapt to your demand

Upvotes: 1

Related Questions