# Why does containter's dsl object return null for properties?

**URL:** <https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429>\
**Category:** Old Forum Archive\
**Created:** [October 15, 2013, 12:24pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429 "2013-10-15T12:24:00Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 12:24pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/1 "2013-10-15T12:24:00Z")

</div>

Hi everyone,

I’m working on custom gradle plugin and I’d like to be able to use the containers to allow creating of custom configuration like so:

```gradle
myExtenstion {
 myContainers {
  container1 {
   property1 'value1'
  }
      container2 {
    property1 'value2'
  }
 }
 }

```

Created a custom plugin with the container and extensions on the project. See below.

```gradle
class MyPlugin implements Plugin {
    @Override
    void apply(Project project) {
     project.extensions.create('myExtension', MyExtensionContainer)
         project.myExtension.extensions.myContainers = project.container(MyExtension)
   project.myExtension.extensions.myContainers.all { myExtension ->
            println myExtension.name // display correct values 'container1' and 'container2'
            println myExtension.property1 // always display null instead of 'value1' and 'value2'
            project.tasks.create("${myExtension}Task") {
                property1 = myExtension.property1
            }
        }
        }
}

```

Extension

```gradle
class MyExtension {
     def name
     def property1
       MyExtension(name) {
        this.name = name
    }
}

```

Container:

```gradle
class MyExtensionContainer {
}

```

I can see that the tasks and the name are set correctly based on defined DSL but other property1 always returns null.

Should the property1 be set based on defined DSL or to I am using incorrect API to setup above configuration?

---

<div class="post-metadata">

**Author:** ![Opal](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/opal/32/219_2.png) [@Opal](https://discuss.gradle.org/u/Opal)\
**Post date:** [October 15, 2013, 12:46pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/2 "2013-10-15T12:46:00Z")

</div>

Here’s an [example](http://www.gradle.org/docs/current/userguide/custom_plugins.html#N1635B) how to use containers and extensions. Have You already checked it?

---

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 4:38pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/3 "2013-10-15T16:38:00Z")

</div>

Thanks for the link. I checked the example and based on it I tried to implement similar logic that I posted above. But Still no luck.

```gradle
apply plugin: DocumentationPlugin
  publisher {
   info {
       name 'Publisher'
   }
   books {
       quickStart {
           title = 'Quick Start'
           sourceFile = file('src/docs/quick-start')
       }
       userGuide {
         }
       developerGuide {
         }
   }
}
  task books << {
    publisher.books.each { book ->
        println "$book.name -> Title: $book.title, Source File: $book.sourceFile"
    }
}
  class DocumentationPlugin implements Plugin<Project> {
    void apply(Project project) {
        def publisher = project.extensions.create('publisher', Publisher)
        publisher.extensions.create('info', PublisherInfo)
        def books = project.container(Book)
        books.all { book ->
            println "$book.name -> Title: $book.title, Source File: $book.sourceFile"
            // expect to create tasks for books and setup these tasks based on the book properties
            sourceFile = project.file("src/docs/$name")
        }
        publisher.extensions.books = books
    }
}
class PublisherInfo {
   def name
}
  class Publisher {
  }
  class Book {
    final String name
    String title
    File sourceFile
      Book(String name) {
        this.name = name
    }
}

```

In above code I am trying to create set of the tasks and configure them based on DSL. I can create them based on the name however can’t configure them as properties for the Books are null. They are only available when tasks run which in my case is to late.

Output that I am getting:

```gradle
quickStart -> Title: null, Source File: null
userGuide -> Title: null, Source File: null
developerGuide -> Title: null, Source File: null
:books
developerGuide -> Title: null, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/developerGuide
quickStart -> Title: Quick Start, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/quick-start
userGuide -> Title: null, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/userGuide

```

Output that I love to have:

```gradle
quickStart -> Title: Quick Start, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/quick-start
userGuide -> Title: null, Source File: null
developerGuide -> Title: null, Source File: null
:books
developerGuide -> Title: null, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/developerGuide
quickStart -> Title: Quick Start, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/quick-start
userGuide -> Title: null, Source File: /Volumes/Data/Tools/Gradle/temp/src/docs/userGuide

```

---

<div class="post-metadata">

**Author:** ![Opal](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/opal/32/219_2.png) [@Opal](https://discuss.gradle.org/u/Opal)\
**Post date:** [October 15, 2013, 4:52pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/4 "2013-10-15T16:52:00Z")

</div>

As far as I see it works fine. Title for the book is printed where it’s set as well as sourceFile. What else You need?

---

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 6:21pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/5 "2013-10-15T18:21:00Z")

</div>

Thanks for quick replay I think my last example was really unfortunate and didn’t present what I am trying to achieve. Hopefully this one will present the problem that I am struggling with.

```gradle
apply plugin: DocumentationPlugin
  publisher {
    info {
        name 'Publisher'
    }
    books {
        quickStart {
            title = 'Quick Start'
        }
        userGuide {
            title = 'User Guide'
        }
        developerGuide {
            title = 'Developer Guide'
        }
    }
}
  class DocumentationPlugin implements Plugin<Project> {
    void apply(Project project) {
        def publisher = project.extensions.create('publisher', Publisher)
        def publisherInfo = publisher.extensions.create('info', PublisherInfo)
        def books = project.container(Book)
        books.all { book ->
            println "Creating task $book.name -> Title: $book.title, "
            project.tasks.create("displayBook${book.name.capitalize()}", DisplayBook) {
                publisherName = publisherInfo.name
                title = book.title
            }
        }
        publisher.extensions.books = books
    }
}
class PublisherInfo {
    String name
}
  class Publisher {
  }
  class Book {
    final String name
    String title
      Book(String name) {
        this.name = name
    }
}
  class DisplayBook extends DefaultTask {
      String publisherName
    String title
      @TaskAction
    def displayBook() {
        println "$name -> Title: $title, Publisher : $publisherName"
    }
}

```

I am trying to create a task that will use DSL to sets itself. Based on the DSL also it will create a list of the tasks. If you run following code you will get following list of the tasks:

```gradle
displayBookDeveloperGuide
displayBookQuickStart
displayBookUserGuide

```

Now this is what I am struggling with and what I am expecting to get after running e.g. displayBookDeveloperGuide

```gradle
// Expected
 displayBookDeveloperGuide -> Title: Developer Guide, Publisher : Publisher

```

But what I am actually getting is:

```gradle
// This is what happens title is not set
 displayBookDeveloperGuide -> Title: null, Publisher : Publisher

```

Hopefully this example presents the problem better.

---

<div class="post-metadata">

**Author:** ![Opal](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/opal/32/219_2.png) [@Opal](https://discuss.gradle.org/u/Opal)\
**Post date:** [October 15, 2013, 7:17pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/6 "2013-10-15T19:17:00Z")

</div>

No idea why this is not working. I wonder if the structure isn’t too complicated 😕 And what exactly You want to achieve…

---

<div class="post-metadata">

**Author:** ![Peter\_Niederwieser](https://avatars.discourse-cdn.com/v4/letter/p/9f8e36/32.png) [@Peter\_Niederwieser](https://discuss.gradle.org/u/Peter_Niederwieser)\
**Post date:** [October 15, 2013, 10:15pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/7 "2013-10-15T22:15:00Z")

</div>

‘books.all’ fires whenever a new book has been added to the container, but before the book has been configured. You need to take additional measures to defer configuration of the task, such as ‘doFirst {}’, convention mapping, or a similar technique. As this is a common question, you should find more on this on the forums and on Stack Overflow.

---

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 11:03pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/8 "2013-10-15T23:03:00Z")

</div>

Thanks for update Peter and Opal.

I just got this working with convention mapping but it requires changing tasks to work with getters. It is not a problem but one have to remember to access properties through getters.

Also noticed that if I defer tasks creation to the ‘project.afterEvaluate’ method everything works correctly. I haven’t seen this being suggested anywhere.

Is there any particular reason why it is not being suggested as an option ?

Example below:

```gradle
apply plugin: DocumentationPlugin
    publisher {
    info {
        name 'Publisher'
    }
    books {
        quickStart {
            title = 'Quick Start'
        }
        userGuide {
            title = 'User Guide'
        }
        developerGuide {
            title = 'Developer Guide'
        }
    }
}
  class DocumentationPlugin implements Plugin<Project> {
    void apply(Project project) {
        def publisher = project.extensions.create('publisher', Publisher)
        def publisherInfo = publisher.extensions.create('info', PublisherInfo)
        def books = project.container(Book)
          project.afterEvaluate({
            println "After evaluation"
            books.all { book ->
                println "Creating task $book.name -> Title: $book.title, "
                project.tasks.create("displayBook${book.name.capitalize()}", DisplayBook) {
                    publisherName = publisherInfo.name
                    title = book.title
                }
            }
        })
        publisher.extensions.books = books
    }
}
class PublisherInfo {
    String name
}
  class Publisher {
  }
  class Book {
    final String name
    String title
      Book(String name) {
        this.name = name
    }
}
  class DisplayBook extends DefaultTask {
      String publisherName
    String title
      @TaskAction
    def displayBook() {
        println "$name -> Title: ${title}, Publisher : ${publisherName}"
    }
}

```

---

<div class="post-metadata">

**Author:** ![Peter\_Niederwieser](https://avatars.discourse-cdn.com/v4/letter/p/9f8e36/32.png) [@Peter\_Niederwieser](https://discuss.gradle.org/u/Peter_Niederwieser)\
**Post date:** [October 15, 2013, 11:07pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/9 "2013-10-15T23:07:00Z")

</div>

> Also noticed that if I defer tasks creation to the project.afterEvaluate method everything works correctly. I haven’t seen this being suggested anywhere. Is there any particular reason why it is not being suggested as an option ?

It’s often suggested as an option, but like other options, it has its limitations. For example, you can run into problems when one property depends on another property set in ‘afterEvaluate’, because you can’t control the order of ‘afterEvaluate’ callbacks. Also it’s difficult to test.

---

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 11:11pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/10 "2013-10-15T23:11:00Z")

</div>

Great thanks for update, than I will go with the option of using convention mapping.

---

<div class="post-metadata">

**Author:** ![Peter\_Niederwieser](https://avatars.discourse-cdn.com/v4/letter/p/9f8e36/32.png) [@Peter\_Niederwieser](https://discuss.gradle.org/u/Peter_Niederwieser)\
**Post date:** [October 15, 2013, 11:13pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/11 "2013-10-15T23:13:00Z")

</div>

Note that convention mapping isn’t considered a public API. That said, currently all available options have their drawbacks. Fortunately, a new solution is in the works.

---

<div class="post-metadata">

**Author:** ![Kamaz](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kamaz/32/1182_2.png) [@Kamaz](https://discuss.gradle.org/u/Kamaz)\
**Post date:** [October 15, 2013, 11:31pm UTC](https://discuss.gradle.org/t/why-does-containters-dsl-object-return-null-for-properties/7429/12 "2013-10-15T23:31:00Z")

</div>

That’s good to know. Will keep checking for new solution 🙂
