2010-09-18 15 views
2

Quand je marshall une instance de cette classe ...@XmlRootElement et <T étend Serializable> jette IllegalAnnotationExceptions

@XmlRootElement 
public static class TestSomething<T extends Serializable> { 

    T id; 

    public T getId() { 
     return id; 
    } 

    public void setId(T id) { 
     this.id = id; 
    } 
} 

... l'exception suivante est lancée ...

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions 
java.io.Serializable is an interface, and JAXB can't handle interfaces. 
    this problem is related to the following location: 
     at java.io.Serializable 
     at public java.io.Serializable TestSomething.getId() 
     at TestSomething 
java.io.Serializable does not have a no-arg default constructor. 
    this problem is related to the following location: 
     at java.io.Serializable 
     at public java.io.Serializable TestSomething.getId() 
     at TestSomething 

Comment puis-je éviter cela (sans changer le paramètre de type à quelque chose comme <T>)?

Répondre

0

Here est un guide d'utilisation des interfaces avec JAXB. JAXB a besoin de classes concrètes, car il doit les instancier lors du marshaling à partir de XML. Et si T n'est pas une classe concrète, elle ne peut pas être instanciée.

+0

J'ai déjà trouvé ce guide, mais cela ne m'aide pas beaucoup. Quand je mets @XmlAnyElement à getId() et essaye de marshaler une instance de TestSomething je reçois com.sun.istack.SAXException2: impossible de marshaler le type "java.lang.Long" en tant qu'élément car il manque une annotation @XmlRootElement –

1

Vous devez utiliser une combinaison de @XmlElement et @XmlSchemaType:

import java.io.Serializable; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlSchemaType; 

@XmlRootElement 
public class TestSomething<T extends Serializable> { 

    T id; 

    @XmlElement(type=Object.class) 
    @XmlSchemaType(name="anySimpleType") 
    public T getId() { 
     return id; 
    } 

    public void setId(T id) { 
     this.id = id; 
    } 
} 

Si vous exécutez la commande suivante:

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 

public class Demo { 

    public static void main(String[] args) throws JAXBException { 
     JAXBContext jc = JAXBContext.newInstance(TestSomething.class); 

     TestSomething<Integer> foo = new TestSomething<Integer>(); 
     foo.setId(4); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(foo, System.out); 
    } 
} 

Vous obtiendrez:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<testSomething> 
    <id xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">4</id> 
</testSomething> 
+0

Est-il possible d'obtenir le champ 'id' dans un attribut plutôt que dans un élément séparé? J'essaie de sérialiser un objet similaire à l'OP, mais JAXB n'aime vraiment pas quand j'essaie d'utiliser '@ XmlAttribute'. Si nécessaire, je vais juste ouvrir une nouvelle question. –

+0

@Matt Ball - Le scénario ci-dessus fonctionnera avec @XmlAttribute si vous utilisez EclipseLink JAXB (MOXy) http://www.eclipse.org/eclipselink/moxy.php. Avec l'implémentation Metro JAXB, j'ai une exception. –

+0

J'ai essayé de passer de Metro à MOXy. Si '' alors j'obtiens les mêmes erreurs que l'OP, avec _ "@ XmlAttribute/@ XmlValue besoin de référencer un type Java qui mappe au texte en XML" _. Si c'est juste '' alors j'obtiens un NPE au fond des entrailles de JAXB (pile trace [ici] (https://gist.github.com/952370)). Le même NPE se produit avec Metro. Des idées? –

0

Ajout @XmlAnyElement dans le champ 'id' (avec l'annotation @XmlAccessorType(XmlAccessType.FIELD) au niveau de la classe) ou en ajoutant La même chose pour getter résoudra cela. (Mais il fait le type de l'élément xml any.)