Trying to load up some fixture data in Play! 1.2.4 with SnakeYAML. Object type is Map<enum, Integer>
. Error I am getting on Fixtures.loadModels("quest.yml") is "Cannot load fixture quests.yml: java.lang.String cannot be cast to java.lang.Enum".
Code snippets-
Constants.java
public enum STATS {
CREATIVITY, ENTHUSIASM, ...
}
Quest.java
@ElementCollection
@MapKeyEnumerated(EnumType.STRING)
public Map<Constants.STATS, Integer> reward;
quest.yml
Quest(sirlin):
reward:
CREATIVITY: 1
As you can see, I've specified that I want to use the String value of the enum STATS with @MapKeyEnumerated annotation. I'm not sure how to change format of yml definition to get this working correctly. Any ideas?
Well, I have found a 'solution' for play 1.2.4, it's ugly, but it works.
The first thing I found was this test case, that shows how it is you should do it:
map:
!!org.pacakge.EnumClass 'CLUBS': 1
!!org.pacakge.EnumClass 'DIAMONDS': 2
That would give a map with enums as keys.
But it doesn't work as it gives this exception:
Can't construct a java object for tag:yaml.org,2002:models.Plazos; exception=Class not found: org.pacakge.EnumClass
But then I found this and this. The problem happens because the Yaml parser (snakeyaml) creates its own ClassLoader in order to parse a .yml file. The structure of the Play! framework uses its own ClassLoader. The solution would be to replace this
Yaml y = new Yaml();
with this
Yaml y = new Yaml(new CustomClassLoaderConstructor(playClassLoader));
but, of course, that is being done inside the play.test.Fixtures
class, so what was my solution? Well, copy that class into your project and replace in the method loadModels
this line:
Yaml yaml = new Yaml();
with this one:
Yaml yaml = new Yaml(new CustomClassLoaderConstructor(Play.classloader));
And that will make it work.