JAXB 2のObjectFactoryクラスのポイントは何ですか?


98

私はJAXBを初めて使用し、JAXB 2.1.3のxjcを使用して、XMLスキーマから一連のクラスを生成しました。スキーマ内の各要素のクラスを生成することに加えて、ObjectFactoryクラスを作成しました。

要素を直接インスタンス化することを妨げるものは何もないようです、例えば

MyElement element = new MyElement();

一方、チュートリアルは好むようです

MyElement element = new ObjectFactory().createMyElement();

ObjectFactory.javaを見ると、次のことがわかります。

public MyElement createMyElement() {
    return new MyElement();
}

だから契約は何ですか?ObjectFactoryクラスを維持する必要があるのはなぜですか?変更されたスキーマから再コンパイルした場合も上書きされると思います。


意図した設計かどうかはわかりませんが、JAXBContextの作成に使用するのに理想的なクラスであるObjectFactoryを見つけました。そこでいくつかのクラスを列挙する必要があります。そうすると、JAXBはそれらのメソッドなどをたどるので、それらはルートのようなものになります。また、ObjectFactoryはすべての要素への参照を持っているため、ObjectFactory.classを使用して、関連するすべてのクラスでJAXBContextを作成するだけで十分です。
vbezhenar

回答:


68

下位互換性だけが理由ではありません。:-P

要素の内容がとることができる値に複雑な制約があるスキーマなど、より複雑なスキーマでは、実際のJAXBElementオブジェクトを作成する必要がある場合があります。それらは通常手作業で作成するのは簡単ではないので、create*メソッドはあなたのためにハードワークを行います。例(XHTML 1.1スキーマから):

@XmlElementDecl(namespace = "http://www.w3.org/1999/xhtml", name = "style", scope = XhtmlHeadType.class)
public JAXBElement<XhtmlStyleType> createXhtmlHeadTypeStyle(XhtmlStyleType value) {
    return new JAXBElement<XhtmlStyleType>(_XhtmlHeadTypeStyle_QNAME, XhtmlStyleType.class, XhtmlHeadType.class, value);
}

これは、<style>タグをタグに取得する方法です<head>

ObjectFactory factory = new ObjectFactory();
XhtmlHtmlType html = factory.createXhtmlHtmlType();
XhtmlHeadType head = factory.createXhtmlHeadType();
html.setHead(head);
XhtmlStyleType style = factory.createXhtmlStyleType();
head.getContent().add(factory.createXhtmlHeadTypeStyle(style));

の最初の3つの使用法はObjectFactory不必要と見なすことができますが(一貫性には役立ちます)、4番目の使用法はJAXBをはるかに使いやすくします。イメージングはnew JAXBElement毎回手書きで書かなければならない!


create *()が何か便利なことをするためにSchema要素が何であるか(またはどれほど複雑である必要があるか)の例/参照を与えることができますか?JAXBサンプルで参照しているスキーマの部分を見つけるのに問題があります。..私のスキーマは、より後で複雑になる場合は、それは確かに私のためにそれのハンドル部分に*作成するための素晴らしいだろうが、それは*作成であるとしても、自分自身でサブ要素を作成する気にしない
アンドリューColeson

XHTML 1.1とXHTML Modularization 1.1のtarballをダウンロードすると、「SCHEMA」という名前のディレクトリが見つかります。すべての.xsdファイルを同じディレクトリに配置します。一部の.xsdファイルはw3.org/2001/xml.xsdもインポートします。xjcを実行するたびにファイルをダウンロードしたくない場合は、場所を適切に調整する必要があります。[続き]
Chris Jester-Young

[続き] <head>のコンテンツを指定する.xsdの特定の部分は、この場合、xhtml11-model-1.xsdのxhtml.head.contentグループの下にあります。
クリスジェスター-ヤング

2
いずれにせよ、ObjectFactoryを使用する必要があると言って銃を頭に向けている人はいません(使用するのは便利ですが)。:-)
クリス・ジェスター-ヤング

ありがとう!私のスキーマはそれほど複雑ではないと思いますが、将来のために覚えておきます。:)私は何かが欠けている必要があることを知っていました。
Andrew Coleson、

39

@Chrisが指摘したように、スキーマをJavaに正確にマップできないため、JAXBがPOJOで機能しない場合があります。これらの場合、JAXBElement追加の型情報を提供するためにラッパーオブジェクトが必要です。

これが一般的である場所で私が遭遇した2つの具体的な例があります。

  • @XmlRootElementアノテーションを持たないクラスのオブジェクトをマーシャリングしたい場合。デフォルトでは、XJC @XmlRootElementは一部の要素に対してのみ生成し、他の要素に対しては生成しません。このための正確なロジックは少し複雑ですが@XmlRootElement「単純なバインディングモード」を使用してXJCに強制的にさらに多くのクラスを生成させることができます。

  • スキーマで置換グループを使用する場合。これはかなり高度なスキーマの使用法ですが、XJCはJAXBElementラッパーを多用することで置換グループをJavaに変換します。

したがって、JAXBElement(何らかの理由で)頻繁に使用するXJC生成のオブジェクトモデルでは、これらのJAXBElementインスタンスを構築する方法が必要です。生成されたものObjectFactoryは、それを行う最も簡単な方法です。自分で作成することもできますが、そうするのは不格好でエラーが発生しやすくなります。


追加の例をありがとう!
Andrew Coleson

2
うわー、それは勝利の答えです。+1
クリス・ジェスター=ヤング

complexTypeを参照する要素がある場合、annoxを使用してXmlRootElementを95%の時間として生成したいのですが、XmlRootElementが必要です(そうしたくないユースケースにヒットしていないため、100%のようになっています)。まだ)
ディーン・ヒラー

9

後方互換性、私は推測します...

http://weblogs.java.net/blog/kohsuke/archive/2005/08/a_story_of_migr.html

... ObjectFactory.createXYZはもうありません。これらのファクトリーメソッドの問題は、チェックされたJAXBExceptionをスローすることでした。これで、単純に新しいXYZ()を実行でき、try / catchブロックは不要になります。(私は知っている、私は知っている...これはそれらの「私たちが何を考えていたのか!」

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.