Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-3723

EMC weirdness: adding properties and setProperty/getProperty in common

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.6.3, 1.6.4
    • 1.6.5, 1.7-beta-2
    • None
    • None
    • 64bit Linux, Sun JVM 1.6.0-14

    Description

      I observed some weird behaviour if a property is added to a class by EMC and getProperty/setProperty are also handled by EMC:

      class Dummy {
         def name
      }
      
      Dummy.metaClass.id = 1
      
      Dummy.metaClass.getProperty = { name ->
         def metaProperty = delegate.metaClass.getMetaProperty(name)
         // do some other stuff here...
         println "getting $name"
         return metaProperty?.getProperty(delegate)
      }
      
      Dummy.metaClass.setProperty = { name, value ->
         def metaProperty = delegate.metaClass.getMetaProperty(name)
         // do some other stuff here....
         println "setting $name"
         metaProperty?.setProperty(delegate,value)
      }
      
      // setting & getting "normal" properties works
      def d= new Dummy(name:"I am Dummy")
      assert "I am Dummy", d.name
      
      // setting & getting "injected" properties fail
      d.id = 123  // fails with groovy.lang.GroovyRuntimeException: Cannot set read-only property: id
      println d.id // fails with groovy.lang.GroovyRuntimeException: Cannot read write-only property: id
      

      In case of a "normal" property ("name"), metaProperty is a groovy.lang.MetaBeanProperty. For a injected property ("id") it's a ThreadManagedMetaBeanProperty. The trouble is IMHO that the constructors of ThreadManagedMetaBeanProperty do not pass its customized setter/getter using setSetter() and setGetter() to its parent object. Is there any reason why ThreadManagedMetaBeanProperty stores these values locally? To solve this, I use the following ugly workaround:

      Dummy.metaClass.getProperty = { name ->
         def metaProperty = delegate.metaClass.getMetaProperty(name)
         // do some other stuff here...
         println "getting $name"
         if (metaProperty instanceof ThreadManagedMetaBeanProperty) {
             return metaProperty.getGetter().invoke(delegate,
      MetaClassHelper.EMPTY_ARRAY);
         } else {
             return metaProperty.getProperty(delegate)
         }
      }
      
      Dummy.metaClass.setProperty = { name, value ->
         def metaProperty = delegate.metaClass.getMetaProperty(name)
         // do some other stuff here...
         println "setting $name $value"
         if (metaProperty==null) return false
      
         if (metaProperty instanceof ThreadManagedMetaBeanProperty) {
             return metaProperty.getSetter().invoke(delegate, value)
         } else {
             return metaProperty.setProperty(delegate,value)
         }
      }
      

      This has been discussed in the mailing list: http://www.nabble.com/EMC%3A-adding-properties-and-setProperty-getProperty-in-common-td25262367.html
      Roshan already fixed this locally.

      Attachments

        Activity

          People

            roshandawrani Roshan Dawrani
            darthvader Stefan Armbruster
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: