Using JAXB to undo / marshal <String> list - Inheritance
I built the following case. Interface for all JAXBLists:
public interface JaxbList<T> { public abstract List<T> getList(); } And the base implementation:
@XmlRootElement(name="list") public class JaxbBaseList<T> implements JaxbList<T>{ protected List<T> list; public JaxbBaseList(){} public JaxbBaseList(List<T> list){ this.list=list; } @XmlElement(name="item" ) public List<T> getList(){ return list; } } Just like the implementation for a list of URIs:
@XmlRootElement(name="uris") public class JaxbUriList2 extends JaxbBaseList<String> { public JaxbUriList2() { super(); } public JaxbUriList2(List<String> list){ super(list); } @Override @XmlElement(name="uri") public List<String> getList() { return list; } } And I use List as follows:
public JaxbList<String> init(@QueryParam("amount") int amount){ List<String> entityList = new Vector<String>(); ... enityList.add("http://uri"); ... return new JaxbUriList2(entityList); } I thought the output should be:
<uris> <uri> http://uri </uri> ... </uris> But this is something like this:
<uris> <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string"> http://uri </item> ... <uri> http://uri </uri> ... </uris> I think this has something to do with inheritance, but I don't understand ...
What is the problem? “How can I fix this?”
Thanks in advance!
Annotations are obtained by reflection. Annotations are tied to the type that he defined.
public class AnnotationTest { public static class A { @XmlElement(name="item") public void doIt() { } } public static class B extends A { @XmlElement(name="name") public void doIt() { } } public static void main(String[] args) { B b = new B(); Method m = b.getClass().getMethods()[0]; Annotation[] ann = m.getDeclaredAnnotations(); System.out.println( ann.length ); // prints 1 } } Thus, this behavior is not related to the reflection mechanism itself. It seems that the JAXB framework explicitly lists the annotation of the method in the class and superclasses. Surprisingly, this still works, but not in the way you would like.
Can't you just delete @XmlElement(name="item") in the base class?
EDIT
According to your comment (but still not sure if I understood everything correctly), I would suggest:
@XmlRootElement(name="list") public class JaxbBaseList<T> implements JaxbList<T>{ protected List<T> list; public List<T> getList(){ return list; } } public class JaxbPrimitiveList<T> extends JaxbList<T>{ protected List<T> list; @XmlElement( name="item" ) public List<T> getList(){ return list; } } @XmlSeeAlso( Uri ) public class JaxbUriList<Uri> extends JaxbList<Uri>{ protected List<Uri> list; @XmlElement( name="uri" ) public List<Uri> getList(){ return list; } }