2010-03-15 4 views
4

J'ai construit le cas suivant. Une interface pour tous JAXBLists:Utilisation de JAXB pour démaraître/marshaler une liste <String> - Héritage

public interface JaxbList<T> { 
public abstract List<T> getList(); 
} 

et une implémentation de base:

@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; 
    } 
} 

En plus d'une mise en œuvre pour une liste des 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; 
    } 
} 

Et j'utilise la liste de la manière suivante:

public JaxbList<String> init(@QueryParam("amount") int amount){ 

     List<String> entityList = new Vector<String>(); 
     ... 
     enityList.add("http://uri"); 
    ... 
     return new JaxbUriList2(entityList); 
    } 

Je pensais que la sortie doit être:

<uris> 
<uri> 
http://uri 
</uri> 
... 
</uris> 

Mais il est quelque chose comme ceci:

<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> 

Je pense qu'il a quelque chose à voir avec l'héritage, mais je ne comprends pas ...

Quel est le problème? - Comment puis-je le réparer?

Merci d'avance!

Répondre

2

Les annotations sont obtenues par réflexion. L'annotation est liée au type qu'il est défini dans.

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 
    } 
} 

donc ce comportement est dû au mécanisme de réflexion lui-même. Il semble que le framework JAXB liste explicitement l'annotation sur la méthode dans la classe et les super classes. Étonnamment, cela fonctionne toujours, mais pas comme vous le souhaitez.

Vous ne pouvez pas simplement supprimer @XmlElement(name="item") dans la classe de base?

EDIT

Selon votre commentaire (mais toujours pas sûr si je comprends tout à juste titre), je suggère:

@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; 
    } 
} 
+0

Le problème est que le JaxbBaseList doit être utilisé pour les types de langue comme Long, Integer, String, etc. et que l'autre implémentation doit être utilisée pour d'autres types. Donc JaxbUriList2 est juste un exemple trompeur, mieux j'avais utilisé l'URI au lieu de String. alors nous avons besoin de l'annotation @XmlSeeAlso. J'ai donc besoin des deux classes telles qu'elles sont. JaxbBaseList pour les types de langage et tous les autres pour les implémentations avec l'annotation @XmlSeeAlso, par exemple: "@XmlSeeAlso (URI.class) public class JaxbUriList étend JaxbBaseList ". – gerry

+0

En ce qui concerne votre EDIT. D'accord, ça fonctionne. MAIS JaxbBaseList et JaxbPrimitiveList sont identiques, à l'exception de @XmlElement (name = "item") uniquement dans JaxbPrimitiveList. Cela ne suit pas les concepts DRY. Ouais, eh bien, pas le JaxbUriList non plus; mais il n'y a pas de solution à laquelle je puisse penser. Pour répéter, ma question est "Pourquoi le nom de l'annotation @XmlRootElement (name =" list ") est-il remplacé, mais pas le @XmlElement (name =" item ")? Et pourquoi la liste est-elle ajoutée deux fois: une fois comme 'item' et une fois comme 'uri'? " – gerry

+0

Je sais que ce n'est pas vraiment une réponse à votre question initiale.J'essayais juste de comprendre moi-même si c'était le mécanisme de réflexion ou JAXB qui était défectueux. En ce qui concerne votre question, c'est ainsi que JAXB est mis en œuvre et je crains que la réponse ne soit donc quelque chose comme «parce que c'est comme ça». Mais peut-être que quelqu'un viendra avec une réponse plus convaincante expliquant la logique et/ou les incohérences de la mise en œuvre de la JAXB. – ewernli