Grails
  1. Grails
  2. GRAILS-1825

onLoad Closure fails to load and set properties on the domain object properly and predictably

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0-RC1
    • Fix Version/s: 1.0-RC2
    • Component/s: Persistence
    • Labels:
      None
    • Environment:
      jdk 1.6, Vista
    • Testcase included:
      yes

      Description

      Test case classes below:

      Loading the Foo produces the following output on the console:

      ============== identity: 1 ==============
      it: null
      owner: class Foo
      name: null
      owner.name: null
      transientName: null
      owner.transientName: null
      name: name does not exist
      transientName: name does not exist
      ============== identity: 2 ==============
      it: null
      owner: class Foo
      name: null
      owner.name: null
      transientName: null
      owner.transientName: null
      owner.name: owner.name does not exist
      owner.transientName: owner.name does not exist

      when both should be identical and read:

      it: class Foo [NOTE: I agree this is optional, but since 'it' isn't being used, why not?]
      owner: class Foo
      name: testing Foo [ident()]
      owner.name: testing Foo [ident()]
      transientName: testing Foo [ident()]
      owner.transientName: testing Foo [ident()]
      owner.name: testing Foo [ident()]
      owner.transientName: testing Foo [ident()]

      The View output is as follows:

      Foo (1)

      • name: name does not exist
      • transientName: null

      Foo (2)

      • name: testing foo 2
      • transientName: owner.name does not exist

      when both lists should read:

      • name: testing foo [ident()]
      • transientName: testing foo [ident()]

      Note two things here:

      1) owner and the default scope reference to the enclosing class are not the same [NOTE: is this a Groovy bug, since owner is supposed operate similarly to this?]

      2) In either case, the Foo Object is not initialized properly, and there exists no predictable way to set attributes on a domain object in the onLoad Closure

      To use the test case, the usual new project, put the files in all the right places, and point your browser at

      http://localhost:8080/test/foo/testChanges

      Test case:

      class Foo {

      String name

      String transientName

      static transients = ['transientName']

      def onLoad = {
      println '============== identity: ' + ident() + ' =============='
      println 'it: ' + it?.class
      println 'owner: ' + owner.class

      println 'name: ' + name
      println 'owner.name: ' + owner.name

      println 'transientName: ' + transientName
      println 'owner.transientName: ' + owner.transientName

      if (ident() == 1) {
      name = name ? name : 'name does not exist'
      transientName = name
      if (!transientName)

      { transientName = 'transientName does not exist' }

      println 'name: ' + name
      println 'transientName: ' + transientName
      }
      else {
      owner.name = owner.name ? owner.name : 'owner.name does not exist'
      owner.transientName = owner.name
      if (!owner.transientName)

      { owner.transientName = 'transientName does not exist' }

      println 'owner.name: ' + owner.name
      println 'owner.transientName: ' + owner.transientName
      }
      }
      }

      class FooController {

      def scaffold = Foo

      def index =

      {redirect(action: 'list') }

      def testChanges = {
      }
      }

      ===== testChanges.gsp ======

      <html>
      <head>
      <title>Testing serializing list changes</title>
      </head>
      <body>
      <%
      def foos = [Foo.get(1), Foo.get(2)]
      def i = 0
      %>
      <g:each var="foo" in="$

      {foos}

      ">
      <h1>Foo ($

      {foo.ident()}

      )</h1>
      <ul>
      <li>$

      {'name: ' + foo.name}

      </li>
      <li>$

      {'transientName: ' + foo.transientName}

      </li>
      </ul>
      <br/>
      </g:each>
      </body>
      </html>

      ===== BootStrap ======

      def init =

      { servletContext -> Foo foo = new Foo(name: 'testing foo 1') foo.save() foo = new Foo(name: 'testing foo 2') foo.save() }

        Activity

        Hide
        Graeme Rocher added a comment -

        There was a bug, but it has now been fixed. The output for your tests are:

        ==============  identity: 1 ==============
        it: null
        owner: class Foo
        name: testing foo 1
        owner.name: null
        transientName: null
        owner.transientName: null
        name: testing foo 1
        transientName: testing foo 1
        ==============  identity: 2 ==============
        it: null
        owner: class Foo
        name: testing foo 2
        owner.name: null
        transientName: null
        owner.transientName: null
        owner.name: owner.name does not exist
        owner.transientName: owner.name does not exist
        

        Note that you should not be using "owner" as this is not necessary the same as "this" particularily if we re-use the same declaration of the closure. This is why the properties that you test by refering to owner still return null

        Show
        Graeme Rocher added a comment - There was a bug, but it has now been fixed. The output for your tests are: ============== identity: 1 ============== it: null owner: class Foo name: testing foo 1 owner.name: null transientName: null owner.transientName: null name: testing foo 1 transientName: testing foo 1 ============== identity: 2 ============== it: null owner: class Foo name: testing foo 2 owner.name: null transientName: null owner.transientName: null owner.name: owner.name does not exist owner.transientName: owner.name does not exist Note that you should not be using "owner" as this is not necessary the same as "this" particularily if we re-use the same declaration of the closure. This is why the properties that you test by refering to owner still return null

          People

          • Assignee:
            Graeme Rocher
            Reporter:
            Evan Slatis
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development