Pregunta

Estoy intentando utilizar la introspección de JAXB para ordenar y descomponer 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 serializar una clase bastante simple.Esta clase se utiliza como @XmlElement en varios beans y tiene un aspecto similar al siguiente:

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;
    }
}

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

public class DoubleRange extends Range<Double> {}

El uso de Range y DoubleRange como tipos de retorno para el bean getter produce 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

Me doy cuenta de que en la mayoría de los casos List<T> y Map<T, U> solo funcionan 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 a la introspección JAXB? ¿Motor sin tener que volver a implementar el rango con campos no genéricos?

¿Fue útil?

Solución

Puede escribir un adaptador personalizado (sin usar XmlAdapter de JAXB) haciendo lo siguiente:

1) declara una clase que acepta todo tipo de elementos y tiene anotaciones JAXB y los maneja como lo desee (en mi ejemplo, convierto todo a String)

@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) usa esta clase en lugar de E en tu clase que se va a ordenar

NOTAS

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

Otros consejos

¿Qué tal

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

  • Apuesto a que JAXB conoce las predeterminadas reglas de clasificación / descifración de Número

Para desmarcar a un tipo específico, necesita XmlAdapter como I descrito aquí: herencia JAXB, unmarshal a la subclase de la clase marshaled

Pruebe 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.

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

¿Entonces quizás podría ser un error en la implementación?

Entonces parece que el problema es el borrado de E en start y end es Comparable.Si no puede manejar interfaces, puedes intentarlo. Object, pero espero que también se queje de eso (ahora o más adelante).Posiblemente podrías hacer Range abstraerlo y especializarlo para cada caso específico. E.Debería saber más sobre JAXB.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top