If you use @Canonical and you define a first-class object with def , as you do with startDate , the annotation generates the following constructors:
@Canonical class MyClass { def startDate def additionalProperties = [:] def void propertyMissing(String name, value) { additionalProperties[name] = value } }
Created constructors:
public MyClass() public MyClass(java.lang.Object) public MyClass(java.util.LinkedHashMap) public MyClass(java.lang.Object,java.lang.Object)
In the @Canonical documentation you can see the following limitation:
Groovy normal map-style naming conventions will not be available if the first property has a LinkedHashMap type or if there is one Map, AbstractMap, or HashMap property
Due to public MyClass(java.util.LinkedHashMap) you cannot use tuple-constructor and you will get MissingPropertyException .
Surprisingly, if you define your first object (note that I say first ) with type instead of using def , the @Canonical annotation does not add public MyClass(java.util.LinkedHashMap) and then your tuple-constructor works, see the following code :
@Canonical class MyClass { java.util.Date startDate def additionalProperties = [:] def void propertyMissing(String name, value) { additionalProperties[name] = value } }
Now created constructors:
public MyClass() public MyClass(java.util.Date) public MyClass(java.util.Date,java.lang.Object)
Since there is no public MyClass(java.util.LinkedHashMap) , the restriction does not apply, and you make a call to tuple-constructor .
In addition, I want to say that since this solution works, I canโt argue why ... I read the @Canonical documentation again and again, and I donโt see the part that describes this behavior, so I donโt , why this works, I also make some attempts, and I'm a little confused only when the first def element is created public MyClass(java.util.LinkedHashMap) , i.e.:
@Canonical class MyClass { def a int c }
The first object defined as def ...
public MyClass() public MyClass(java.lang.Object) public MyClass(java.util.LinkedHashMap)
Now, if I change the order:
@Canonical class MyClass { int c def a }
Now, at first, not def and public MyClass(java.util.LinkedHashMap) not generated:
public MyClass() public MyClass(int) public MyClass(int,java.lang.Object)
Hope this helps,