Reputation: 31
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
To Link My SubReport to Main Report, I added In SubReport Data Source Expression the expression :
And Finally, i added course fields in SubReport :
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
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
how your datasource
in my case i use jsondatasource, but you can adapt to your demand
Upvotes: 1