I have this relationship:
User{
...
hasMany = [tags: Tag]
}
Tag{
...
}
Some where in my service I have this code:
List<Tag> tags = user.tags
But this does not work, I am getting this error:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[com.app.ext.Tag : 1]' with class
'org.hibernate.collection.PersistentSet' to class 'java.util.List' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.util.List(com.app.ext.Tag)
at ConsoleScript15.run(ConsoleScript15:6)
If I change my code to:
ArrayList<Tag> tags = user.tags
It works as expected! though ArrayList
is subclass of List
.
Any explanation?
Grails version: 2.3.0
Take a look at Groovy's casting rules.
When value which you try to cast is collection, constructor of the type you want to cast to is invoked. So, for ArrayList
it implicitly invokes:
ArrayList<Tag> tags = new ArrayList(users.tags)
For List
it would be something like new List(users.tags)
which is incorrect since List
is interface.
The snippet below shows the same problem:
Set<String> mySet = new HashSet<>(['A', 'B'])
ArrayList<String> myList = mySet; // works okay
List<String> myList = mySet; // fails with GroovyCastException
But you can explicitly cast to ArrayList
:
List<String> myList = mySet as ArrayList;