I found this problem when I use Morphia in scala. It checks the fields of a class by reflection, and get necessary type information for mapping.
But if I use traits, and define some collection fields, the generic type information will be lost, which cause Morphia can’t get enough information, and throw exceptions.
See my code:
trait HasTags {
@Reference
var tags: java.util.List[Tag] = new java.util.ArrayList[Tag]() // the generic type is Tag
}
class Question extends Entity with HasTags {
}
I compiled the scala file, and get some java class files. Then I use java decompiler to see the content of the java byte codes:
public class Question extends Entity implements HasTags {
@Reference
private java.util.List tags;
}
You can see there is no Tag here, so Morphia will fail.
I used scala 2.8.1. Is there any way to fix it?
UPDATE
@extempore said, maybe javap doesn’t display that Tag information.
But I used a program called Java Decompiler, not javap.
I tried this code:
class Question extends Entity with HasTags {
@Reference
var tags2: java.util.List[Tag] = new java.util.ArrayList()
}
And see the byte code in Java Decompiler, it displays:
public class Question extends Entity implements HasTags {
@Reference
private java.util.List tags;
@Reference
private java.util.List<models.Tag> tags2;
}
We can see the tags2 contains Tag, but tags doesn’t.
And the interface HasTags is:
public abstract interface HasTags extends ScalaObject
{
public abstract List<Tag> tags();
@TraitSetter
public abstract void tags_$eq(List<Tag> paramList);
}
We can see, the return value of method tags() is List<Tag>, but the field tags is not.
Since morphia get the information by fields, it can’t work correctly.
That’s how javap displays things. It doesn’t mean the signature isn’t present.
That’s how you know it is. You can also see it in the constant pool.