2009-05-05 23 views
10

Estoy tratando de utilizar la introspección de JAXB para ordenar y desenmascarar algunos objetos de dominio existentes marcados con anotaciones JAXB. La mayoría de las cosas funcionan como se esperaba, pero estoy teniendo bastantes problemas para obtener una clase bastante simple para serializar. Esta clase se utiliza como un @XmlElement en un número de granos y se ve algo como:JAXB Marshalling and Generics

public class Range<E extends Comparable<E>> implements Serializable { 
    protected boolean startInclusive, endInclusive; 
    protected E  start, end; 

    public Range(){ 
      startInclusive = endInclusive = true; 
    } 

    public boolean contains(E value){...} 

    public E getEnd() { 
      return end; 
    } 

    public void setEnd(E end) { 
      this.end = end; 
    } 

    public boolean isEndInclusive() { 
      return endInclusive; 
    } 

    public void setEndInclusive(boolean endInclusive) { 
      this.endInclusive = endInclusive; 
    } 

    public E getStart() { 
      return start; 
    } 

    public void setStart(E start) { 
      this.start = start; 
    } 

    public boolean isStartInclusive() { 
      return startInclusive; 
    } 

    public void setStartInclusive(boolean startInclusive) { 
      this.startInclusive = startInclusive; 
    } 
} 

he tratado de hacer lo siguiente, sin éxito, JAXB todavía está enojado con la interfaz Comparable.

public class DoubleRange extends Range<Double> {} 

El uso de ambos Rango y DoubleRange como tipo de retorno para los rendimientos del getter frijol una excepción como:

 
java.lang.Comparable is an interface, and JAXB can't handle interfaces. 
    this problem is related to the following location: 
     at java.lang.Comparable 
     at protected java.lang.Comparable com.controlpath.util.Range.start 
     at example.util.Range 
     at example.util.DoubleRange 
     at public example.util.DoubleRange example.domain.SomeBean.getRange() 
     at example.domain.SomeBean 

Soy consciente de que en la lista de la mayoría de los casos <T> y mapa < T, U > única obra porque la especificación JAXB tiene disposiciones especiales para esos tipos cuando se encuentran en beans, pero ¿hay alguna manera de transmitir lo que quiero al motor de introspección JAXB sin tener que volver a implementar el rango con campos no genéricos?

Respuesta

5

Se podría escribir un adaptador personalizado (no usar XmlAdapter de JAXB) de la siguiente manera:

1) declarar una clase que acepta todo tipo de elementos y tiene anotaciones JAXB y los maneja como desee (en mi ejemplo convierto todo para cuerdas)

@YourJAXBAnnotationsGoHere 
public class MyAdapter{ 

    @XmlElement // or @XmlAttribute if you wish 
    private String content; 

    public MyAdapter(Object input){ 
    if(input instanceof String){ 
     content = (String)input; 
    }else if(input instanceof YourFavoriteClass){ 
     content = ((YourFavoriteClass)input).convertSomehowToString(); 
    }else if(input instanceof .....){ 
     content = ((.....)input).convertSomehowToString(); 
    // and so on 
    }else{ 
     content = input.toString(); 
    } 
    } 
} 

// I would suggest to use a Map<Class<?>,IMyObjToStringConverter> ... 
// to avoid nasty if-else-instanceof things 

2) utilizar esta clase en lugar de E en su clase a-ser-marshalled

NOTAS

  • Por supuesto, esto sería no trabajo para estructuras de datos complejas (anidadas).
  • Tienes que pensar cómo deshacer esto de nuevo, podría ser más complicado.Si que sea demasiado complicado, esperar a que una propuesta mejor que la mía;)
+0

Estoy tratando de obtener una idea de por qué JAXB está molesto y evitar una gran cantidad de código de clasificación personalizada (ya que estoy seguro de que voy a golpear esto de nuevo en algún momento en el futuro, potencialmente en un objeto mucho más complejo). Pero esto técnicamente ES una respuesta, y lo marcaré como tal en unos días si nadie más tiene uno mejor. Gracias =) –

0

Probar algo como Simple XML Serialization viene con soporte para tipos genéricos en elementos XML con varias anotaciones como @Element y @ElementList. El modelo de programación es muy similar, pero más simple que JAXB.

-1

lo que parece que el problema es el borrado de E en start y end es Comparable. Si no puede manejar las interfaces, puede probar Object, pero espero que se queje también (ahora o más adelante). Posiblemente pueda hacer Range abstracto y especializarlo para cada E específico. Debería saber más sobre JAXB.

+0

¿Soy incorrecto al suponer que la clase DoubleRange resolvería el problema del borrado? Intenté redefinir los getters como public Double getEnd() y public Double getStart() pero obtuve el mismo error. Parece que está mirando demasiado profundamente para los tipos. –

+0

IIRC, JAXB puede observar los captadores y el colocador o (mejor) los campos. En este último caso, deberá mover el campo a la clase especializada y hacer que getStart/getEnd sea abstracto. Posiblemente, la clase abstracta no debe ser anotada como JAXB codificable. No soy realmente un experto en esta área, ya que es posible que pueda decir ... –

1

¿Qué tal

public class Range<**E extends Number**> implements Serializable { ... 
  • número es un clase

  • apuesto JAXB sabe por defecto reglas de clasificación/descalificación para el número

Para unmarshalling de tipo específico, es necesario XmlAdapter como describen a continuación: JAXB inheritance, unmarshal to subclass of marshaled class

+0

Buena sugerencia, desafortunadamente JAXB intenta crear instancias de java.lang.Number al desmarcar>.

+0

De lo que necesita XmlAdapter, consulte la respuesta editada –

0

En realidad, no es del todo claro por qué esto no funcionaría. Parece que JAXB debería poder resolver el subtipo específico correctamente: si (¡y solo si!) Este tipo NO es el tipo de raíz (que no es según su descripción). Quiero decir, es solo un frijol; así que si bean reemplaza T con trabajos de tipo directo, también debería hacerlo la versión genérica iff usando subclases para vincular tipos (como se hace en el ejemplo).

Entonces, ¿podría ser un error en la implementación?