Gradle DSL does not catch pojos in NamedDomainObjectContainer correctly

When there’s a pojo as property of a NamedDomainObjectContainer’s content type, build fails with:
groovy.lang.MissingPropertyException

Expected Behavior

A configuration example in Gradle DSL looks like:
units { unit1 { locationHash = 'aS223SDfcs22300gopWWA' students { student1 { efficiencyRate = 0.76 tutor { firstName = "James" lastName = "Bond" flags = [ '03-01-2008': "Interview report", '03-01-2009': "First drill report" ] } } student2 { efficiencyRate = 0.54 } } } // other units }

  • units is a container of Unit objects (NamedDomainObjectContainer)
  • students is a container of Student objects inside Unit. Each student object has a Tutor object.
  • To catch configuration of Tutor objects, this method is used inside Student:
    void tutor(Action<Tutor> configureAction) { configureAction.execute(tutor) }

This configuration is supposed to be mapped to the corresponding groovy structure (described above). But build fails to do so with groovy.lang.MissingPropertyException: Could not set unknown property 'firstName' for Student ... of type Student at org.gradle.internal.metaobject.AbstractDynamicObject.setMissingProperty(AbstractDynamicObject.java:115) at org.gradle.internal.metaobject.ConfigureDelegate.setProperty(ConfigureDelegate.java:107).
It is as if the build thinks properties of Tutor are under Student which is not correct.
Adding the supposedly unknown properties (Tutor properties) under Student hides the issue, but that’s not what I want.

Current Behavior

groovy.lang.MissingPropertyException: Could not set unknown property 'firstName' for Student ... of type Student.
It is as if the build thinks properties of Tutor are under Student which is not correct.
Adding the supposedly unknown properties (Tutor properties) under Student hides the issue, but that’s not what I want.

Context

Trying to catch Gradle DSL configuration into Groovy pojos:

  • units is a container of Unit objects (NamedDomainObjectContainer<Unit>)
  • students is a container of Student objects inside Unit. Each student object has a Tutor object.
  • To catch configuration of Tutor objects, this method is used inside Student:
    void tutor(Action<Tutor> configureAction) { configureAction.execute(tutor) }

Your Environment

Gradle version 4.3.1
Groovy version 2.4.12