2009-05-05 11 views
10

JAXBアノテーションでマークアップされた既存のドメインオブジェクトをマーシャリングおよびアンマウントするために、JAXBのイントロスペクションを使用しようとしています。ほとんどのものは期待どおりに動作しますが、私はかなりシンプルなクラスを直列化するのにはかなり問題があります。このクラスは、豆の数に@XmlElementとして使用され、のようなものに見えている:私は成功しません、次の操作を実行しようとしていJAXBマーシャリングとジェネリックス

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

を、JAXBはまだComparableインタフェースと怒っています。

のような豆ゲッターの利回り例外の戻り値の型として範囲とDoubleRangeの両方を使用して
public class DoubleRange extends Range<Double> {} 

:私はほとんどの場合、リスト<でT >実現

 
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 

と< T、U >だけ仕事の地図JAXB仕様にはBeanで遭遇したときにこれらのタイプの特別な規定があるため、JAXBイントロスペクションエンジンに伝えたいことを非汎用フィールドで再実装する必要はありません。

答えて

5

次の操作を行うことにより(JAXBのXmlAdapterのを使用していない)、カスタムアダプタを書くことができ、以下:

1)の要素のすべての種類を受け入れ、JAXB注釈 を持っており、あなたが望むように(それらを処理するクラスを宣言し、私のたとえば私は

@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)あなたの-整列化されるように、クラスの代わりにEのこのクラスを使用)文字列にすべてを変換する

NOTES

  • もちろん、これはではなく、複雑な(ネストされた)データ構造の場合はとなります。
  • これをもう一度アンマーシャリングする方法を考える必要があります、もっと難しいかもしれません。 場合、それはあまりにもトリッキーだ、私より優れた提案を待つ。
+0

JAXBが動揺して、カスタムマーシャリングコードをたくさん避ける理由について、いくつかの洞察を得ようとしています(私はヒットすると確信していますこれは将来のある時点で、これは潜在的に非常に複雑なオブジェクト上にある)。しかし、これは技術的には解決策であり、他に誰も優れた人がいなければ、数日後にそのようにマークします。ありがとう=) –

0

Simple XML Serializationのようなものを試してください。@Elementや@ElementListなどのいくつかのアノテーションを持つXML要素のジェネリック型がサポートされています。プログラミングモデルは非常に似ていますが、JAXBよりも簡単です。

-1

endにあるEの消去がComparableであるように見えます。インターフェイスを処理できない場合は、Objectを試すことができますが、それも(今またはそれ以降のいずれかで)それが不平を言うことを願っています。可能であれば、Rangeを抽象化し、それをそれぞれの具体的なものに特化することができますE。 JAXBについてもっと知っておく必要があります。

+0

DoubleRangeクラスが消去問題を解決すると仮定して正しくありませんか?私はゲッターをpublic Double getEnd()とpublic Double getStart()で再定義しようとしましたが、同じエラーが発生しました。それはタイプのためにあまりにも深く見ているようだ。 –

+0

IIRC、JAXBは、getterとsetterを参照するか、フィールドを(より良い)表示できます。後者の場合は、フィールドを特殊クラスに移動し、getStart/getEnd abstractを作成する必要があります。おそらく、抽象クラスにJAXBエンコード可能なアノテーションを付けるべきではありません。私は実際にあなたが話すことができるかもしれないので、この分野の専門家ではありません。 –

1

)について

public class Range<**E extends Number**> implements Serializable { ... 
  • 数は、私はJAXBはデフォルトを知っている賭けるクラス

  • どのように番号のマーシャリング/アンマーシャリング規則

  • 特定のタイプに非整列化するため

I は、ここで説明するように、あなたはXmlAdapterのものが必要です。これが働かない理由JAXB inheritance, unmarshal to subclass of marshaled class

+0

良い提案ですが、残念ながらJAXBはアンマーシャリングを行うときにjava.lang.Numberをインスタンス化しようとします。<そしてNumberはComparableではありませんが、 –

+0

XmlAdapterが必要です。編集された回答を参照してください。 –

0

は実際に、それは私には非常に明確ではありません。 JAXBは特定のサブタイプを正しく解決できなければならないようです:このタイプはルートタイプではありません(あなたの説明通りではありません)。つまり、それはちょうど豆です。そのため、Tを直接型に置き換えたBeanの場合は、(例のように)型をバインドするためにサブクラス化を使用するgenericバージョンiffも必要です。

おそらく、実装上のバグでしょうか?

関連する問題