2

I try to use Jaspersoft iReport to create Report from my POJO and export it to PDF.

My POJO looks like this:

class Topic {
    String topicName
    int topicPoints;
    DateRange dateRange;
    List<Post> posts;
}

class DateRange {
    LocalDate begin;
    LocalDate end;
}

class Post {
    String postName;
    int postPoints;
}

I found solution with JRBeanCollectionDataSource, so I created list with one element (my POJO).

ArrayList<Topic> list = new ArrayList<>();
list.add(topic);
JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(list);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, "C:/jasper/test.pdf");

I have no problems with exporing simple data like Strings, Integers etc.

e.g. this exports fine.

class Topic {
    String topicName
    Integer topicPoints;
}

With just: Drag & Drop fields topicName (with "java.lang.String") and topicPoints (with "java.lang.Integer")

But how can I put on my reports nested fields inside dateRange or inside posts?

I see there is field class like java.lang.Object or java.util.List, but how can I define fields inside this Object or List?

My ideal solution would've create report like:

My example

UPDATE:

class Topic {
    String topicName
    int topicPoints;
    DateRange dateRange;
    List<Post> posts;
}

class DateRange {
    LocalDate begin;
    LocalDate end;
}

class Post {
    String postName;
    int postPoints;
    List<User> users;
}

class User {
    String userName;
    int userPoints;
}

And what in case when it will be even more nested?

degath
  • 1,530
  • 4
  • 31
  • 60

1 Answers1

2

In jrxml you can define the structured fields (for nested objects) like this:

<field name="dateRange" class="my.package.DateRange">
    <property name="com.jaspersoft.studio.field.label" value="dateRange"/>
</field>
<field name="posts" class="java.util.List">
    <property name="com.jaspersoft.studio.field.label" value="posts"/>
</field>

And then use values from nested objects like $F{dateRange}.getBegin().


But in your case it seems that you have always one topic and iterate posts for it. Then it would be better to:

  • pass topic as a parameter: parameters.put("topic", topic)
  • create DataSource for posts: JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(topic.getPosts())
  • define parameter topic in the report: <parameter name="topic" class="my.package.Topic"/>
  • in report render topic values using parameter expression: $P{topic}.getTopicName()
  • define fields for Post in the report
  • in report render post values using fields (i.e. $F{postName}) in the detail band - JasperReport will automatically iterate all posts and render them

Update (to answer the updated part of the question): To render values of type Collection (List) you can use subreports - see here: Creating Subreport within list in iReport It means that you will create subreport to render user values.

Or you can use table to render users with subDataSet created from users list:

<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
    <datasetRun subDataset="usersDataSet">
        <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{users})]]></dataSourceExpression>
    </datasetRun>
    ...
</jr:table>

And you must also define the subDataset for the table:

<subDataset name="usersDataSet">
    <field name="userName" class="java.lang.String">
        <fieldDescription><![CDATA[userName]]></fieldDescription>
    </field>
    <field name="userPoints" class="java.lang.Integer">
        <fieldDescription><![CDATA[userPoints]]></fieldDescription>
    </field>
</subDataset>
cgrim
  • 4,890
  • 1
  • 23
  • 42
  • Thanks, let me digest it, and if everything will be fine I'll accept answer ASAP. – degath Oct 11 '18 at 11:32
  • Can you explain me what is this class="my.package.Topic"? Is this a path in my project to this folder or what? I think I do not have connected iReport and project together I do report separetly. Am I doing it wrong? – degath Oct 11 '18 at 11:47
  • 1
    It is full `Topic` class name with it's package (`my.package.Topic` is only example - I don't know your correct package ;-)). You can create jar with all those POJO classes and add it into iReport class path by **Tools** --> **Options** --> **Classpath** --> **Add JAR** – cgrim Oct 11 '18 at 11:59
  • 1
    You can also create factory class with static method which will create `Collection` with some mock data and include that class also in the jar with POJO classes. In iReport you can then register it as a JavaBean DataSource and use it for testing (better preview of the report). For more details you can look here for example: https://community.jaspersoft.com/blog/how-set-javabean-set-datasource-ireports-along-working-sample – cgrim Oct 11 '18 at 12:21
  • seems like I understand much more now. If you could update your answer with idea what to do if it will be double nested list. I'll obiously accept answer after that. :) – degath Oct 11 '18 at 12:55
  • 1
    Answer updated - I hope it will help to you. – cgrim Oct 11 '18 at 16:03