2012-01-04 16 views
7

He estudiado Blaise Doughan's answer to a question on this subject pero tengo otra pregunta.¿Qué información de paquete anoto con XmlJavaTypeAdapters?

XmlJavaTypeAdapters le permite enumerar un montón de anotaciones XmlJavaTypeAdapter, cada una de las cuales rige cómo JAXB asigna un tipo no enlazable a un tipo enlazable.

Puede usar esta anotación en el nivel del paquete. Al hacerlo, cada anotación XmlJavaTypeAdapter necesita su atributo type() completamente especificado.

No parece haber un requisito de que el paquete que se está anotando tenga algo que ver con el paquete de los tipos no enlazables que se están adaptando. Eso es conveniente y agradable.

Eso, sin embargo, me lleva a mi siguiente pregunta: si no hay relación entre el paquete anotado y el paquete del tipo que se está adaptando, ¿cómo descubre JAXB las anotaciones a nivel de paquete XmlJavaTypeAdapters? ¿Cómo, en otras palabras, sabe qué paquetes consultar para potenciales anotaciones de XmlJavaTypeAdapters? ¿Puedo hacer un paquete aleatorio en, digamos, un archivo .jar en el directorio del archivo .ear que contiene una clase única y descomunal package-info que está anotada con todos los adaptadores para todos mis tipos no enlazables?

Respuesta

7

Cuando el tiempo de ejecución JAXB carga una clase anotada JAXB, busca un package-info.java en el mismo paquete que esa clase, y lo comprueba para buscar anotaciones a nivel de paquete. Por lo tanto, aunque XmlJavaTypeAdapters no tiene que residir en el mismo paquete que los tipos "no vinculables", hace tiene que residir en el mismo paquete que los tipos "enlazables".

Por ejemplo, decir que tengo una clase JAXB anotado A, en el paquete X, que tiene una propiedad de tipo B en el paquete Y. Para enlazar la propiedad B, digamos que se requiere un adaptador de tipo. Ese adaptador se puede especificar en A, o se puede especificar en el package-info.java en el paquete X. El paquete Y es bastante arbitrario y no tiene ningún interés para el tiempo de ejecución de JAXB.

Espero que tenga sentido.

+0

muy útil; Gracias. ¿Se camina el gráfico desde allí? Es decir, supongamos que tengo un único tipo vinculable que alimentar a JAXB. Supongamos además que su paquete está anotado con 647 anotaciones 'XmlJavaTypeAdapter', cada una de las cuales especifica un tipo no enlazable y un adaptador para ese tipo. ¿Mi 'JAXBContext' ahora podría manejar los 647 tipos ahora adaptados? –

+0

@ Laird: Sí, siempre que (a) tenga la RAM para manejarlo, y (b) Todos los tipos vinculables estén en ese paquete. – skaffman

+0

Interesante. Sin embargo, parece extraño que tuviera que arrancar todo el proceso. Quiero decir, si puedo configurar una pila de adaptadores simplemente alimentando JAXB con un solo tipo, entonces espero que sea posible mejorar JAXB para que ese tipo único no sea necesario tampoco. Al igual, haz que JAXB mire de forma predeterminada un "paquete" 'package-info' en algún lugar para que el arranque inicial no sea necesario. De nuevo, gracias por tu ayuda. –

5

No parece ser un requisito de que el paquete que está siendo anotado tener nada que ver con el paquete de los tipos no pueden vincularse ser adaptados. Eso es conveniente y agradable.

Esto es correcto. Cuando se usa @XmlJavaTypeAdapter en el nivel de paquete, significa aplicar este adaptador a todas las propiedades del tipo especificado para las clases que residen en este paquete. Lo demostraré a continuación con un ejemplo.

forum8735737.bar.package-info

Para este paquete especificaremos un XmlAdapter que se aplicará a todos los campos/propiedades de tipo String dentro de este paquete.

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class) 
}) 
package forum8735737.bar; 

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

forum8735737.bar.StringAdapter

Nuestra XmlAdapter simplemente convertir todas las instancias de String a mayúsculas cuando cálculo de referencias:

package forum8735737.bar; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class StringAdapter extends XmlAdapter<String, String> { 

    @Override 
    public String unmarshal(String v) throws Exception { 
     return v; 
    } 

    @Override 
    public String marshal(String v) throws Exception { 
     if(null == v) { 
      return v; 
     } 
     return v.toUpperCase(); 
    } 

} 

forum8735737.bar.Bar

Bar representa un POJO en este paquete con una propiedad de tipo String:

package forum8735737.bar; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Bar { 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

forum8735737.foo.Foo

Foo representa un objeto de dominio con una propiedad de tipo String que existe en un paquete diferente. El XmlAdapter se registró para el paquete forum8735737.bar no serán aplicables a esta clase:

package forum8735737.foo; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo { 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

demostración

el siguiente código creará instancias de ambos Foo y Bar y reunir a XML:

package forum8735737; 

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

import forum8735737.bar.Bar; 
import forum8735737.foo.Foo; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Foo.class, Bar.class); 
     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     Foo foo = new Foo(); 
     foo.setName("Foo"); 
     marshaller.marshal(foo, System.out); 

     Bar bar = new Bar(); 
     bar.setName("Bar"); 
     marshaller.marshal(bar, System.out); 
    } 

} 

Salida

Aviso cómo el valor del elemento name dentro bar se ha convertido en mayúsculas:

<?xml version="1.0" encoding="UTF-8"?> 
<foo> 
    <name>Foo</name> 
</foo> 
<?xml version="1.0" encoding="UTF-8"?> 
<bar> 
    <name>BAR</name> 
</bar> 
Cuestiones relacionadas