Let us imagine 3 classes: A, B extends A, and C extends A, all representing tags without attributes or inner elements. And now a fouth class X containg the ElementUnion:
@ElementUnion({
@Element(name="b", type=B.class, required=false),
@Element(name="c", type=C.class, required=false)
})
protected A a;
It seems clear that if the inner tag of X tag is b, the attribute a should be an instance of B. For example, for the code:
X x = new X(new B());
Object retrievedObject = null;
serializer.write(x, tmpFile);
System.out.println("Written Object: " + x);
retrievedObject = serializer.read(X.class, tmpFile);
System.out.println("Retrieved Object: " + retrievedObject);
The expected output is:
Written Object: X [a=B []]
Retrieved Object: X [a=B []]
The problem seems to happen due deserialization, because the XML file seems correct:
<x>
</x>
However if A is a class (not an interface) and A has a converter, then the output is (independently of whether B has also a converter or not):
Written Object: X [a=B []]
Retrieved Object: X [a=A []]
Which is wrong, because the attribute a should only be of type B or C according to the type attriubute of the annotation ElementUnion. This does not happen with interfaces because they cannot be instantiated.
In addition, if there are no converters, but we set matchers, the output becomes:
Written Object: X [a=B []]
Retrieved Object: X [a=null]
Which should also be wrong, although it does not violate the contract.
I attach a sample code so you can play with it and see the results.
Note, I have a problem showing the XML, but it is correct: inside the tag x there is a tag b as expected. Anyway, you can try it in the code.