web-dev-qa-db-ja.com

JAXBContext.newInstanceのバリエーション

クラスのnewInstanceメソッドのさまざまな形式で実験していますJAXBContext(Oracleに付属するデフォルトのSun JAXB実装を使用していますJDK 1.7)。

具体的なクラスとObjectFactoryクラスをnewInstanceメソッドに渡すだけでいいのかどうかはわかりません。私は純粋にXMLファイルの解析にJAXBを使用していることに注意する必要があります。つまり、XML-> Java方向のみです。

ここに私のポイントを示す絶対に最小限のコードがあります:

xsdファイル

<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
    xmlns          ="http://www.w3.org/2001/XMLSchema"
    xmlns:a        ="http://www.example.org/A"
    targetNamespace="http://www.example.org/A">
    <element name="root" type="a:RootType"></element>

    <complexType name="RootType">
       <sequence>
           <element name="value" type="string"></element>
       </sequence>
    </complexType>
</schema>

上記のXSDの場合、次のJAXBInstance.newInstance呼び出しは、サンプルa.xmlファイルを解析できるコンテキストの作成に成功します。

  • jc = JAXBContext.newInstance( "example.a");
  • jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
  • jc = JAXBContext.newInstance(example.a.RootType.class、example.a.ObjectFactory.class);

ただし、example.a.RootType.classのみを渡すと、実行時にjavax.xml.bind.UnmarshalExceptionで失敗します。

jc = JAXBContext.newInstance(example.a.RootType.class); // this fails at runtime.

誰かが光を当てることはできますか?私がこれらのJAXBContext :: newInstanceのバリエーションを実験している理由は、私が この問題 につまずいたからです。オブジェクトファクトリではなく個々のクラスに基づいたJAXBコンテキスト」。サンプルa.xmlおよび[〜#〜] jaxb [〜#〜]JavaコードI am投稿の最後にフォローを使用します。

使用されるサンプルa.xml

<?xml version="1.0" encoding="UTF-8"?>
<a:root xmlns:a="http://www.example.org/A"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.example.org/A A.xsd">
    <a:value>foo</a:value>
</a:root>

JAXB解析コード

public static void main (String args[]) throws JAXBException, FileNotFoundException {
    JAXBContext jc = null;
    message("using package context (press any key:)");
    jc = JAXBContext.newInstance("example.a");
    work(jc); // SUCCEEDS

    message("using Object factory (press any key):");
    jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
    work(jc); // SUCCEEDS

    message("using class enumeration (press any key):");
    try {
        jc = JAXBContext.newInstance(example.a.RootType.class);
        work(jc);  // FAILS
    } catch (javax.xml.bind.UnmarshalException e) {
        e.printStackTrace();
    }

    message("using class enumeration and Object factory too (press any key):");
    jc = JAXBContext.newInstance(example.a.RootType.class, example.a.ObjectFactory.class);
    work(jc); // SUCCEEDS

}

private static void work(JAXBContext jc) throws JAXBException, FileNotFoundException {
    Unmarshaller u = jc.createUnmarshaller();
    RootType root = ((JAXBElement<RootType>)u.unmarshal( new FileInputStream( "a.xml" ))).getValue();
    System.out.println( root.getValue() );
}
19

XMLスキーマから生成されたJAXBモデル

XMLスキーマから生成されたモデルからJAXBContextを作成するときは、生成されたクラスのパッケージ名で常に実行することをお勧めします。

JAXBContext jc = JAXBContext.newInstance("example.a");

newInstanceパラメーターを受け取るClassLoaderメソッドを使用することをお勧めします。これにより、Java SEからJava EE環境に移動するときの悲しみが軽減されます。

JAXBContext jc = JAXBContext.newInstance("example.a", example.a.ObjectFactory.class.getClassLoader());

パッケージ名にJAXBContextを作成すると、JAXB implは、XMLスキーマからモデルを生成したと想定し、ObjectFactoryクラスを取り込みます。これは、この名前の@XmlRegistryアノテーションが付けられたクラスを常に生成するためです。

Javaモデルから開始

これは、クラスを取るnewInstanceメソッドの使用を人々に勧めるときです。 JAXBContextをJAXBクラスからブートストラップするとき、ObjectFactoryというクラスについて特別なことはありません。 ObjectFactoryの役割は、@XmlRegistryアノテーションが付けられたどのクラスでも実行できるため、自動的に検索されることはありません。これが、ObjectFactoryを明示的に参照するときにユースケースが機能し、そうでないときに失敗した理由です。

16
bdoughan