Search code examples
javagrailsjasper-reportsireportgrails-plugin

How to use jasperreports subreports with grails jasper plugin?


I would like to use subreports with grails jasper plugins, I followed the manual at this url (http://www.grails.org/plugin/jasper). Here is my code :

Domain Book :

class Book {

  static belongsTo = Library

    Library library

    String title
    String author
    String publisher
    String category

    static constraints={
        title()
        author()
        publisher()
        category()
    }
}

Domain Library :

class Library {

  static hasMany = [ books : Book ]

  String name
  String adresse
  Date dateMaturity

    static constraints = {
    }

        String toString()
    {
        return name
    }
}

In my BookController, I have :

def createReport = {
    def books = Book.list()
    chain(controller:'jasper',action:'index',model:[data:books],params:params)
}

In my LibraryController, I have :

def createReport = {
    def library = Library.list()
    chain(controller:'jasper',action:'index',model:[data:library],params:params)
}

My jasper part is :

I have a SubReport file : books.jasper (get a list of books).
Also a MasterReport : library.jasper (get a list of library).

In my MasterReport(library), I added subreport, I would like, for each library, show list of books it contains ; here is my library code :

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
...
<field name="books" class="java.util.Collection"/>
...
<subreport isUsingCache="true">
<reportElement x="0" y="25" width="437" height="100"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{books})]]></dataSourceExpression>
<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "books.jasper"]]>
</subreportExpression>
</subreport>

And I have this error :

Error 500: Executing action [index] of controller [JasperController] in plugin [jasper] caused exception: net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression : Source text : new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{books})
Exception Message: failed to lazily initialize a collection of role: bookshelf.Library.books, no session or session was closed

Thank you for help.


Solution

  • Jasper reports just expects the list of objects. It doesn't understand GORM queries. So the way we do is by creating a separate list of objects which we name as 'View Objects' and then send them to jasper reports instead of domain classes.

     class LibraryVO {
       List books
       String name
       String adresse
       Date dateMaturity
      }
    
     class bookVO {
      String title
        String author
        String publisher
        String category
      }
    

    You can initializ the list like

     List data=[]
    
     LibraryVo libVo= new LibraryVO(...) // inalise it here
     libVo.books = [new BookVO(),new BookVO()]
    
     data << libVO
    

    And pass the list to jasper controller

    (chain(controller:'jasper',action:'index',model:[data:data],params:params).