Pergunta

Eu estou tentando usar introspecção do JAXB para Marshall e unmashall algum domínio existente objetos marcados com anotações JAXB. A maioria das coisas funcionam conforme o esperado, mas estou tendo um pouco de dificuldade para obter uma classe bastante simples de serialize. Esta classe é usada como um @XmlElement de uma série de feijão e é algo como:

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

Eu tentei fazer o seguinte, sem sucesso, JAXB ainda está irritado com a interface Comparable.

public class DoubleRange extends Range<Double> {}

O uso de ambos Gama e DoubleRange como tipos de retorno para os rendimentos do getter feijão uma exceção 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

Eu percebo que na maioria dos casos List e Mapa único trabalho porque a especificação JAXB tem disposições especiais para esses tipos quando eles são encontrados em grãos, mas existe alguma maneira de transmitir o que eu quero o motor JAXB introspecção sem ter que gama Reimplementar com campos não-genéricos?

Foi útil?

Solução

Você poderia escrever um adaptador personalizado (não usando XMLAdapter do JAXB) fazendo o seguinte:

1) declarar uma classe que aceita todos os tipos de elementos e tem anotações JAXB e manipula-los como você deseja (no meu exemplo, eu converter tudo para 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) usar esta classe em vez de E em sua classe a-ser-marshalled

NOTAS

  • É claro que esta faria não trabalho para complexos (aninhados) estruturas de dados.
  • Você tem que pensar como desempacotar esta de volta, poderia ser mais complicado. E se é muito complicado, espera por uma proposta melhor do que o meu;)

Outras dicas

Como cerca

public class Range<**E extends Number**> implements Serializable { ...
  • Número é um class

  • Eu aposto JAXB sabe padrão triagem / unmarshalling regras para o número

Para unmarshalling de tipo específico, você precisa XMLAdapter como eu descrito aqui: JAXB herança, desempacotar a subclasse da classe empacotada

Tente algo como serialização XML simples ele vem com suporte para tipos genéricos em elementos XML com uma série de anotações tal como @Element e @ElementList. O modelo de programação é muito semelhante, mas mais simples do que JAXB.

Na verdade, não é muito claro para mim por que isso não iria funcionar. Parece que JAXB deve ser capaz de resolver subtipo específico corretamente: if (! E somente se) deste tipo não é o tipo de raiz (o que não é de acordo com sua descrição). Quero dizer, é apenas um feijão; por isso, se de feijão com T substituído com obras tipo direto, por isso deve versão genérica sse usando sub-classes para tipos de vinculação (como é feito no exemplo).

Por isso, talvez ele poderia ser um bug na implementação?

Portanto, parece que o problema é o apagamento de E em start e end é Comparable. Se ele não consegue lidar com interfaces de você poderia tentar Object, mas eu espero que reclama a isso também (agora ou mais tarde). Possivelmente você poderia fazer Range abstrato e especializar-lo para cada E específico. Eu deveria saber mais sobre JAXB.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top