2010-09-07 19 views
16

Hay una respuesta de marcador de posición en the unofficial guide con un enlace a un artículo que (a mí) parece no tener relación alguna.¿Por qué JAXB a veces se asigna a JAXBElement?

Uso XJC para generar mis clases JAXB y, aunque la mayoría de ellas se correlacionan entre sí como se esperaba, algunos elementos se asignan al JAXBElement<Foo>. Esto es muy molesto para los gráficos con ciclos, donde a veces el nodo padre de un elemento Foo será JAXBElement<Foo>, que no tiene una propiedad principal, rompiendo el ciclo.

Puedo pensar en varias soluciones, pero sería mucho mejor si alguien pudiera explicarme este comportamiento. ¿Por qué JAXB a veces asigna un elemento <Foo> al JAXBElement<Foo> en lugar de Foo?

+0

Consulte http://stackoverflow.com/questions/3639313/xsd-formatting-elementcomplextype-vs-complextype-element/3639375#3639375 para obtener una explicación – skaffman

+0

@skaffman: ¿Eh? No veo cómo se relaciona su respuesta con si xjc elige 'JAXBElement ' sobre 'Foo'. –

+1

@Chris: Porque está determinado en parte por la elección de tipos anónimos o tipos de nombres en el esquema de origen. – skaffman

Respuesta

10

JAXBElement se utiliza para conservar el nombre del elemento/espacio de nombres en casos de uso en los que no hay suficiente información en el modelo de objetos. La ocurrencia más común es con grupos de sustitución:

sustituyendo Grupo:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org" 
    xmlns="http://www.example.org" 
    elementFormDefault="qualified"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="anElement"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="anElement" type="xs:string"/> 

    <xs:element name="aSubstituteElement" type="xs:string" substitutionGroup="anElement"/> 

</xs:schema> 

generará:

package org.example; 

import javax.xml.bind.JAXBElement; 
import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { 
    "anElement" 
}) 
@XmlRootElement(name = "root") 
public class Root { 

    @XmlElementRef(name = "anElement", namespace = "http://www.example.org", type = JAXBElement.class) 
    protected JAXBElement<String> anElement; 

    public JAXBElement<String> getAnElement() { 
     return anElement; 
    } 

    public void setAnElement(JAXBElement<String> value) { 
     this.anElement = ((JAXBElement<String>) value); 
    } 

} 

sin sustitución Grupo:

Si se quita la grupo de sustitución:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org" 
    xmlns="http://www.example.org" 
    elementFormDefault="qualified"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="anElement"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:element name="anElement" type="xs:string"/> 

</xs:schema> 

se generará la siguiente clase:

package org.example; 

import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { 
    "anElement" 
}) 
@XmlRootElement(name = "root") 
public class Root { 

    @XmlElement(required = true) 
    protected String anElement; 

    public String getAnElement() { 
     return anElement; 
    } 

    public void setAnElement(String value) { 
     this.anElement = value; 
    } 

} 

También puede obtener una JAXBElement cuando unmarshal, comparar los siguientes ejemplos:

+0

Gracias, los grupos de sustitución están de hecho donde esto está sucediendo. Entonces, ¿es entonces un error que en 'afterUnmarshal (Unmarshaller u, Object parent)' estas clases sustituibles están pasando su propio JAXBElement como su 'parent'? Especialmente porque no parece haber una forma de obtener el elemento padre real del JAXBElement. –

+0

Esto parece ser un error en Metro JAXB (la implementación de referencia, incluida en Java SE 6). En la implementación de MOXy JAXB (http://www.eclipse.org/eclipselink/moxy.php) el objeto padre correcto se pasa al método afterUnmarshal. –

0

¿Para evitar mapear a JAXBElement? Lo he hecho cosas que funcione para mí:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
      xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      jaxb:extensionBindingPrefixes="xjc" 
      jaxb:version="2.0"> 

    <xs:annotation> 
     <xs:appinfo> 
      <jaxb:globalBindings generateValueClass="false"> 
      <xjc:simple /> 
      </jaxb:globalBindings> 
     </xs:appinfo> 
    </xs:annotation> 

</xs:schema> 

Guardar este archivo en el archivo xml y suministro de archivos como vinculantes.

Referencia Link

generar clases JAXB usando Eclipse no se olvide de dar a los archivos de unión creados con XML arriba, y marca "Permitir extensiones de proveedores" de la siguiente manera:

enter image description here

Con los cambios Puedo Obtener deshacerse de JAXBElement en las clases generadas xjc para convertir xsd a las clases generadas JAXB.

Cuestiones relacionadas