Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Populations of abstract classes are not listed in index #43

Open
amador-duran-toro opened this issue May 7, 2020 · 0 comments
Open

Comments

@amador-duran-toro
Copy link

amador-duran-toro commented May 7, 2020

In Grails 4.0.3 and Grails 3.3.11, if you have an inheritance hierarchy with an abstract superclass, e.g.

package mypackage

abstract class A {
  String name
  // ...
  // properties
  // ...
}
package mypackage

class B extends A {
  String b
  // ...
  // properties
  // ...
}
package mypackage

class C extends A {
  String c
  // ...
  // properties
  // ...
}

And you populate the concrete classes in Bootstrap.groovy, e.g.

package mypackage

class BootStrap {

    def init = { servletContext ->
        A.withTransaction { status ->
            def listOfB = []
            (1..25).each { i ->
                listOfB << new B(name:"b${i}",b:"${i}st")
            }

            B.saveAll( listOfB )

            def listOfC = []
            (1..25).each { i ->
                listOfC << new C(name:"c${i}",c:"${i}nd")
            }

            C.saveAll( listOfC )
        }
    }
    def destroy = {
    }
}

If you use scaffolding, the index page for A shows an empty list instead of a paginated list of 50 objects (25 B objects and other 25 C objects).

Apart from that, it shows a new button that generates a java.lang.InstantiationException when clicked because it tries to instantiate an abstract class.

A quick and dirty workaround for this problem is the following:

  1. Generate views for the abstract class (only index.gsp is relevant)
  2. Edit the generated index.gsp in the following way:
  • Comment the new button code
<!-- no create button -->
<!--
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
-->
  • Comment the <f:table> element and add the following code
<!-- new arguments for f:table -->
<g:set var="collection" value="${mypackage.A.list(params)}" />
<g:set var="domainClass" value="${grailsApplication.getDomainClass('mypackage.A')}" />
<g:set var="domainProperties" value="${domainClass.getConstrainedProperties().keySet()}" />
<!-- old f:table -->
<!-- <f:table collection="${aList}" /> -->
<!-- new f:table -->
<f:table collection="${collection}" properties="${domainProperties}" />            

With respect to <f:table> attributes:

  • The aList variable originally passed to <f:table> is null.
  • Do not include domainClass="mypackage.A", it generates a java.lang.InstantiationException.
  • The properties attribute must be present and contain the list of properties of the abstract class only. If it is not present, and objects of classes A and B appear in the same pagination, a org.springframework.beans.NotReadablePropertyException is thrown because <f:table> tries to read properties of class B on objects of class C and viceversa.

Apart from that, the create and edit pages are still available for A. I have generated-all for A and tried to delete those methods from the generated controller, but my knowledge of Grails is limited and I am having lots of errors with that, so I went back to scaffolding (which is my main reason for using Grails).

I think that Grails should not show empty lists for abstract classes in scaffolding, but I do not know if that behaviour is inside the scaffolding controller, the <f:table> tag, or harcoded in _table.gsp.

I also think that Grails should not generate create and update methods in the scaffolding controllers for abstract classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant