Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
1.6.3, 1.6.4
-
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.