2011-03-17 28 views
13

he un archivo de enlace como estearchivo de enlace JAXB: XmlAdapters y nombre del paquete

<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <jxb:bindings schemaLocation="example.xsd" node="/xs:schema"> 
    <jxb:schemaBindings> 
     <jxb:package name="example" /> 
    </jxb:schemaBindings> 
    <jxb:globalBindings> 
     <jxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" 
      parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" 
      printMethod="javax.xml.bind.DatatypeConverter.printDateTime" /> 
     <jxb:javaType name="java.util.Calendar" xmlType="xs:date" 
      parseMethod="javax.xml.bind.DatatypeConverter.parseDate" 
      printMethod="javax.xml.bind.DatatypeConverter.printDate" /> 
     <jxb:javaType name="java.util.Calendar" xmlType="xs:time" 
      parseMethod="javax.xml.bind.DatatypeConverter.parseTime" 
      printMethod="javax.xml.bind.DatatypeConverter.printTime" /> 
    </jxb:globalBindings> 

    </jxb:bindings> 
</jxb:bindings> 

La clase de esquema se generan en el "ejemplo" (correcto), pero los XmlAdapters en "org.w3._2001.xmlschema " (incorrecto). ¿Cómo puedo arreglar esto?

+0

¿Alguna vez descubrió cómo solucionar esto? – Matt

Respuesta

7

Tuve este problema también, lo resolví usando this.

+0

No lo he probado aún, pero como la sugerencia está en la guía (no) oficial de JAXB, creo que este es el camino a seguir. Thnaks. – Puce

+0

El enlace ahora conduce a github donde no se encuentra ese anclaje. Buen ejemplo de por qué las respuestas de solo enlace no valen nada. – Scorpio

10

El paquete org.w3._2001.xmlschema se crea aquí porque XJC tiene que generar una clase que se extienda a javax.xml.bind.annotation.adapters.XmlAdapter, que a su vez llama a su parse/print métodos estáticos. Por alguna razón, los pone en este paquete, en lugar de en algún lugar más útil.

No ha dicho, que la aplicación JAXB que utilice, pero el JAXB RI tiene una extensión a la personalización de unión javaType que le permite especificar una subclase de XmlAdapter directamente, en lugar de parseMethod/printMethod pares. Esto elimina la necesidad de generar la clase de puente sintético XmlAdapter. Consulte el RI docs para saber cómo hacer esto.

Imagino que EclipseLink/Moxy tiene algo similar a esto, pero no estoy seguro si el XJC que viene con Java6 es capaz de hacerlo (Sun parece haber eliminado la mitad de las cosas útiles de RI cuando lo trajeron en el JRE).

+0

estoy usando Java SE 6 u24 y la siguiente Maven plugin: \t \t \t \t \t org.jvnet.jaxb2.maven2 experto-jaxb2-plugin 0.7.5 Así que creo que es JAXB 2.1 – Puce

+0

Estoy bien con los adaptadores generados (ya que solo se usan internamente), pero los quiero en el mismo paquete que las otras clases generadas. – Puce

+0

Si quisiera usar un adaptador personalizado escrito a mano. ¿Sería esto posible con JAXB 2.1? Tal vez al definir una extensión para el plugin Maven de alguna manera (las extensiones personalizadas son compatibles, lo usé antes). También quiero definir la personalización en un archivo de enlace externo en lugar de en el XSD (el enlace que proporcionó muestra cómo hacerlo directamente en un XSD). ¿Cómo puedo hacer esto con un archivo XJB y Maven? – Puce

7

Para los usuarios de Apache CXF, la forma más limpia es utilizar la opción -p que ofrece wsdl2java.

-p [WSDL-espacio de nombres =] PackageName

Especifica cero, o más, nombres de paquetes a utilizar para el código generado. Opcionalmente especifica el espacio de nombres WSDL para el mapeo del nombre del paquete.

En nuestro caso

-p http://www.w3.org/2001/XMLSchema=org.acme.foo

Si utiliza el cxf-codegen-plugin, a continuación, sólo tiene que añadir otro par de <extraarg>.

<plugin> 
    <groupId>org.apache.cxf</groupId> 
    <artifactId>cxf-codegen-plugin</artifactId> 
    <version>${cxf.version}</version> 
     [...] 
    <extraarg>-p</extraarg> 
    <extraarg>http://www.w3.org/2001/XMLSchema=org.acme.foo</extraarg> 
     [...] 
</plugin> 

No hay necesidad de un targetNamespace señalando el espacio de nombres XSD reservado y no hay necesidad de cajón de sastre paquete jaxb vinculante.

+2

me salvó la vida :) –

+0

me salvó la vida también. – mithrop

+0

Tenga en cuenta que si tiene varios WSDL y especifica el mismo paquete para todos ellos, puede seguir teniendo problemas debido a nombres anónimos ("Adapter org.w3._2001.xmlschema.Adapter4 no es aplicable al tipo de campo java". lang.Integer ", que es lo que me llevó aquí). Sin embargo, si especifica un paquete _different_, resuelve el problema, pero luego tiene varias copias de los mismos adaptadores en diferentes paquetes (posiblemente con diferentes nombres), lo que no se siente terriblemente elegante.Usé la solución de John Zhang a continuación (pero copiando los adaptadores autogenerados anteriormente como punto de partida). – DarthPablo

4

La mejor forma de utilizar GlobalBinding es especificar un adaptador explícito en lugar de utilizar este par de análisis/impresión.Por ejemplo, en lugar de lo siguiente:

<jaxb:javaType name="java.lang.Long" xmlType="xs:long" 
         parseMethod="com.mypackage.myclass.parseLong" 
        printMethod="com.mypackage.myclass.print"/> 

En su lugar, usted debe:

<xjc:javaType name="java.lang.Long" xmlType="xs:long" 
        adapter="com.mypackage.LongAdapter"/> 

Recuerde agregar espacio de nombres para xjc:

xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
      jxb:extensionBindingPrefixes="xjc" 

El LongAdapter clase sería así:

public class LongAdapter 
extends XmlAdapter<String, Long> 
{ 


public Long unmarshal(String value) { 
    return your_util_class.parseLong(value); 
} 

public String marshal(Long value) { 
    return your_util_class.print(value); 
} 

} 

De esta forma, dado que especificó explícitamente clases de adaptador, jaxb no generará adaptadores predeterminados con el nombre de paquete predeterminado org.w3._2001.xmlschema.

Es muy importante evitar el uso del nombre de paquete predeterminado org.w3._2001.xmlschema. Tomando un ejemplo, si tiene un proyecto A y un proyecto B, y ambos tienen algunos esquemas y enlaces. En la forma antigua, ambos generan adaptadores con exactamente los mismos nombres completos calificados, p. org.w3._2001.xmlschema.Adapter1. Sin embargo, este adaptador podría ser para Long en el proyecto A y para Integer en el proyecto B. Entonces, digamos que tiene un proyecto C en sentido descendente utilizando A y B. Ahora el problema se pone desagradable. Si C necesita usar el Adaptador1, no puede predecir que el utilizado es de A para Largo o de B para Entero. Entonces, su aplicación C podría funcionar bien en algún momento, pero tal vez falle de manera extraña en algunas otras situaciones. Si esto sucede, el tipo de excepción sería como:

org.w3._2001.xmlschema.Adapter1 is not applicable to the field type java.lang.Double... 

La solución mencionada por Roy Truelove no parece trabajar cuando lo probé en mi entorno con Maven-jaxb2-plugin incluso si la teoría es correcta.

Cuestiones relacionadas