Using a dynamic object as an extension doesn't work

I am trying to create an extension with dynamic object with getProperty(name), but it doesn’t work for me. My intent is to use a self-explaining properties for string values/constants, so they are not hard-coded and their usage is consistent across all build scripts.

class DynamicPropertyObject{
    def storage
           DynamicPropertyObject() {
        storage = [:]
    }
          DynamicPropertyObject(initialStorage) {
        storage = initialStorage;
    }
          void setProperty(String name, value) {
        storage[name] = value
    }
          def getProperty(String name) {
        storage[name]
    }
}
  class MsBuildPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
                  project.extensions.create("msBuild", DynamicPropertyObject,
             [ "arch": new DynamicPropertyObject(['x86' : 'win32', 'x64':'x64']),
              "config": new DynamicPropertyObject(['debug' : 'Debug', 'release':'Release']),
              "target": new DynamicPropertyObject(['build' : 'build', 'clean':'clean']) ]);
                          }
 }
  apply plugin: MsBuildPlugin
    ext.testMe = new DynamicPropertyObject(
            [ "arch": new DynamicPropertyObject(['x86' : 'win32', 'x64':'x64']),
              "config": new DynamicPropertyObject(['debug' : 'Debug', 'release':'Release']),
              "target": new DynamicPropertyObject(['build' : 'build', 'clean':'clean']) ]);
             println "testMe.arch.x86:" + testMe.arch.x86 //works fine
      println "msBuild.arch.x86:" + msBuild.arch.x86
   // doesn't work

It fails with following error.

* Where:
Build file 'D:\Projects\gradle\dynaProp\build.gradle' line: 44
  * What went wrong:
A problem occurred evaluating root project 'dynaProp'.
> Could not find property 'arch' on DynamicPropertyObject_Decorated@163b254.

Is there some restriction so Extension must be just POGO/POJO? If yes, some hint how can I achieve that effect w/o creation of special class for each node in hierarchy is welcome.

Thanks, Bronislav

Try to use ‘project.extensions.add’ and instantiate ‘DynamicPropertyObject’ yourself. You could also pass a plain map.

Gradle’s dynamic object protocol is slightly different to Groovy’s. This is an area where that is the case.

Instead of implementing getProperty()/setProperty(), you should implement propertyMissing().

http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

Thanks for the prompt response. I appreciate it. I thought that all extension.add() methods are deprecated. Now I can see one overload is still available. :slight_smile:

Luke it’s great you shed some light on it and I hopefully understand it now. I other case I would just ask another question, because I like to understand how things work.

Thanks, Bronislav

I thought that all extension.add() methods are deprecated.

We deprecated some methods called ‘add’ that were actually creating things.

I’m not quite sure if you are asking for more detail on the issue with getProperty() etc. or not.

Luke, if you can provide some brief details it would be great. I just don’t want you teach me a Groovy and things I should know :-). It seems that getProperty() is somehow provided by Gradle, so an Extension object is somehow wrapped.

I also wonder why the class is DynamicPropertyObject_Decorated@163b254 and not just DynamicPropertyObject.

Thanks, Bronislav

When you create an extension (or other types of DSL objects such as tasks etc) Gradle creates a subclass dynamically at runtime with extra features. That’s why you get that class name, it’s the name of the subclass.