4

BaseBeanExJAXB アノテーション付き Bean ( ) を拡張する Bean ( )を作成しBaseBeanました。はデータ構造のBaseBeanどこかのリストにあり、変更できません。ソフトウェアは、BaseBeanEx必要なときはいつでも明示的なキャストを行います。の代わりにObjectFactoryto createも書きました。これはすべて正常に機能しますが、呼び出されないメソッドを追加しました。BaseBeanExBaseBeanafterUnmarshalBaseBeanEx

これはバグですか、それとも仕様によるものですか? 後者の場合、エレガントな回避策はありますか?

デフォルトの JAXB エンジンを使用しています。

4

2 に答える 2

5

注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB 2(JSR-222)エキスパートグループのメンバーです。

afterUnmarshal呼び出されない理由は、メタデータがクラスBaseBeanEx上に構築されているためです。BaseBeanユースケースを機能させるには、JAXBimplに実際にのインスタンスにマップする必要があることを通知する必要がありますBaseBeanEx

オプション#1-アノテーションを使用したJAXB実装

注釈を使用して@XmlElement、フィールド/プロパティのタイプをオーバーライドできます。以下の例では、メソッドのシグネチャはですList<BaseBean>が、@XmlElementアノテーションはJAXB実装にプロパティをとして解釈する必要があることを通知しますList<BaseBeanEx>

package forum10174513;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Root {

    private List<BaseBean> baseBeans;

    @XmlElement(name="base-bean", type=BaseBeanEx.class)
    public List<BaseBean> getBaseBeans() {
        return baseBeans;
    }

    public void setBaseBeans(List<BaseBean> baseBeans) {
        this.baseBeans = baseBeans;
    }

}

オプション#2-MOXyの外部マッピングドキュメントの使用

BaseBeanはデータ構造のどこかのリストにあり、変更できません。

ドメインモデルを変更できず、JAXBプロバイダーとしてMOXyを使用している場合は、ドメインモデルを変更せずに、外部マッピングドキュメントを利用してメタデータを適用できます。

bindings.xml

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum10174513">
    <java-types>
        <java-type name="Root">
            <java-attributes>
                <xml-element 
                    java-attribute="baseBeans"
                    name="base-bean" 
                    type="forum10174513.BaseBeanEx"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

デモ

JAXBContext以下は、外部マッピングドキュメントを活用するをブートストラップする方法を示すコードです。現在、外部マッピングドキュメントを介してのみ参照されるクラスにイベントメソッドが登録されないというバグがあります(http://bugs.eclipse.org/376876)。の作成に使用されるクラスのリストにこのクラスを明示的に含めることで、この問題を回避できますJAXBContext

package forum10174513;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum10174513/bindings.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class, BaseBeanEx.class}, properties);

        File xml = new File("src/forum10174513/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(xml);
    }

}

BaseBean

package forum10174513;

public class BaseBean {
}

BaseBeanEx

package forum10174513;

import javax.xml.bind.Unmarshaller;

public class BaseBeanEx extends BaseBean {

    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        System.out.println("AFTER UNMARSHAL WAS CALLED");
    }

}

出力

以下は、デモコードを実行して生成された出力です。

AFTER UNMARSHAL WAS CALLED
AFTER UNMARSHAL WAS CALLED

詳細については

于 2012-04-16T14:31:55.043 に答える
1

あなたはそれを正しく綴りましたか?メソッド名は「afterUnmarshal」(1 つの「L」) です。 仕様

アップデート:

もう少し考えてみると、jaxb はカスタム サブクラスを認識していないため、コールバックを認識できない可能性があります。JAXBContext のセットアップ中に JAXB がすべてのクラスを調べると仮定します。その時点で、JAXB はカスタム サブクラスではなくベース Bean クラスしか認識していないため、コールバック メソッドを見つけることはありません。

2つの考え。「外部コールバック」メカニズムを使用できます(カスタムクラスに必要なことを行う別のイベントハンドラーを使用します)。または、コールバック メソッドを使用して基本 Bean クラスを生成 (または後で追加) することもできます。その後、JAXB はおそらくメソッドを認識して呼び出し、カスタム サブクラスでオーバーライドできます。

于 2012-04-16T13:16:19.713 に答える