IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Services Web Java Discussion :

[CXF] Utilisation de XmlID / XmlIDREF et Polymorphisme


Sujet :

Services Web Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 113
    Points : 64
    Points
    64
    Par défaut [CXF] Utilisation de XmlID / XmlIDREF et Polymorphisme
    Bonjour,

    Je rencontre un problème pour générer mon flux Web-Service avec CXF lorsque j'utilise les annotations @XmlID et @XmlIDREF sur des classes dérivées.

    Imaginons les 5 classes suivantes (avec les accesseurs et constructeurs qui vont bien) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "A", namespace = "http://mon.exemple.fr/")
    @XmlSeeAlso({ B.class, C.class })
    public class A {
     
    	@XmlID
    	private String code;
     
    [...]
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "B", namespace = "http://mon.exemple.fr/")
    public class B extends A {
     
    [...]
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "C", namespace = "http://mon.exemple.fr/")
    public class C extends A {
     
    [...]
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "D", namespace = "http://mon.exemple.fr/")
    public class D {
     
    	@XmlIDREF
    	private A a;
     
    [...]
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "E", namespace = "http://mon.exemple.fr/")
    public class E {
     
    	@XmlElement(nillable = true)
    	private List<A> listeA;
     
    	@XmlElement(nillable = true)
    	private List<D> listeD;
     
    [...]
    }
    Imaginons que j'alimente cette structure de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    A a1 = new A(); 
    a1.setCode("1");
     
    A a2 = new B(); 
    a1.setCode("2");
     
    D d1 = new D(); 
    d1.setA(a1)
     
    D d2 = new D(); 
    d2.setA(a2)
     
    E root = new E(); 
    root.getListeA().add(a1);
    root.getListeA().add(a2);
    root.getListeD().add(d1); 
    root.getListeD().add(d1);
    j'obtiens le flux suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <root>
    	<a>
    		<code>1</code>
    	</a>
    	<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    			xmlns:ns4="http://monexemple.fr/"
    			xsi:type="ns4:B">
    		<code>2</code>
    	</a>
    	<d>
    		<a>1</a>
    	</d>
    	<d>
    		<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    				xmlns:ns4="http://monexemple.fr/"
    				xsi:type="ns4:B">
    			<code>2</code>
    		</a>
    	</d>
    </root>
    Lorsque j'envoie ce flux et que je veux le désérialiser vers les mêmes classes A, B, C, D et E, j'obtiens l'erreur suivante :
    org.apache.cxf.interceptor.Fault: Unmarshalling Error: unexpected element (uri:"", local:"code"). Expected elements are (none)
    at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:822)
    at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:643)
    at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:156)
    at org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:109)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
    [...]
    j'en déduit que CXF attend bien le flux que j'aimerais envoyer, à savoir plutôt quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <root>
    	<a>
    		<code>1</code>
    	</a>
    	<a xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    			xmlns:ns4="http://monexemple.fr/"
    			xsi:type="ns4:B">
    		<code>2</code>
    	</a>
    	<d>
    		<a>1</a>
    	</d>
    	<d>
    		<a>2</a>
    	</d>
    </root>
    Avez-vous une idée du problème svp ?

    Merci.

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Après quelques tests, je m'aperçois que le problème est sans doute lié à la version de JAXB que j'utilise.
    J'ai testé différentes versions de JAXB-impl et à partir de la version 2.2.6 je n'ai plus le même comportement. Mon flux est correctement généré (avec les références) mais j'ai une nouvelle erreur lors de l'unmarshalling côté serveur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: null
    Avec un debug pas à pas je m'aperçois que le problème d'origine est mal loggé. En fait, Jaxb semble essayer de d'insérer une objet de type D dans l'attribut "a" de mon objet de type D. Comme il rencontre un problème de type, il remonte une erreur.

    Pour info, j'ai essayé différentes versions de CXF (de 2.5.2 à 2.7.3) et différentes versons de JAXB (2.1.13 à 2.2.7) et je ne parviens pas comprendre l'origine du problème.

    Y'a-t-il des attentions particulières à porter sur les versions de JAXB à embarquer ?

    Merci.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Bon, au final j'ai résolu mon problème :

    1 - Les versions inférieures à 2.2.6 de jaxb-impl ne traitent pas correctement les @XmlId et @XmlIDREF lors du marshalling. J'ai donc ajouté une dépendance vers jaxb-impl-2.2.6 dans mon projet client.

    2 - JAXB semble gérer les @XmlID et @XmlIDREF avec une Map<Object, Object> prenant comme clé la valeur de la propriété qui porte le @XmlID. Or, cette map est la même pour tous les types d'objet. Si on a deux objets de types différents avec le même ID, il y a donc confusion.
    Cela explique la tentative de JAXB d'alimenter un propriété de type A avec un objet de type D.

    J'ai donc contourné le problème en ajoutant un accesseurs sur mes beans qui calcule un "xmlID" en concaténant l'ID du bean avec le nom de la classe pour garantir l'unicité. Je place l'annotation @XmlID sur cet accesseur et le tour est joué.

    La solution n'est pas très propre donc si certains ont une meilleurs idée, je suis preneur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [CXF] Utilisation d'un Client Dynamique
    Par Pi2 dans le forum Services Web
    Réponses: 3
    Dernier message: 27/12/2010, 11h39
  2. [utilisation de CXF] Ou existe-t-il un bon tutoriel ?
    Par caballero dans le forum Services Web
    Réponses: 2
    Dernier message: 06/02/2008, 15h52
  3. Réponses: 6
    Dernier message: 31/05/2007, 23h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo