JAXBに関して

AngularJSを使うとRestを作ることが多くなるので、
サーバーサイドのJava側の方も書きたいと思います。
今回は、JavaのJAXBに関して、書きたいと思います。
それで、RestやSOAPで、結果をXMLJSONで戻す時にJAXBを使うですが、
なにをしてくれるかと言うとですね。
XMLとかJSONなどをJavaクラスへマッピングしてくれるものになります。
例えば、こんなJSONを戻したいと思ったら

{'category' : [{'key' : '1000',  'value' : 'AAAAA'}, {'key' : '2000',  'value' : 'BBBBB'}]}

JAXBのクラスは、下記のような記述になります。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"category"})
@XmlRootElement(name = "categoryResouce")
public class CategoryResouce {
    protected List<CategoryList.Category> category;
    public List<CategoryList.Category> getCategory() {
        if (category == null) {
            category = new ArrayList<CategoryList.Category>();
        }
        return this.category;
    }
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {"key","value"})
    public static class Category {
        protected String key;
        protected String value;
        public String getKey() {
            return key;
        }
        public void setKey(String value) {
            this.key = value;
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }
}

Categoryクラスにkey,valueのプロパティを定義します。
それで、@XmlAccessorType(XmlAccessType.FIELD)の定義と、
@XmlTypeに、key,valueと言う名前を定義すると、JSONの下記の部分がマッピングされます。

{'key' : '',  'value' : ''}

また、このCategoryクラスを保持するクラスが必要になります。
やり方は、2種類あり、
親クラスを作成して、Categoryクラスをネストさせ、
親クラスのプロパティにCategoryクラスのインスタンスを保持できるようにするか、
別クラスを作って、プロパティにCategoryクラスのインスタンスを保持できるようにする方法があります。
ネストクラスの方がらくなので、ネストクラスがおすすめです。
複数存在する場合は、Categoryクラスのリストを保持するように作ります。
外のクラスは、Categoryクラスのリストを保持するようにして、
@XmlTypeを使って、categoryと言う名前を定義します。
JSONJSONの下記の部分がマッピングされます。

{'category' : []}

これで、JSONXMLJavaクラスへマッピング可能になります。
このJAXBのクラスを今の様に一から書く方法とXMLファイルから自動生成する方法があります。
XMLファイルから生成する方法ですが、
自分の環境の場合、Apache Mavenを利用しているので、
まずは、Mavenのpom.xmlに下記の定義を追加します。

<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-xjc</artifactId>
	<version>2.2.7</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-impl</artifactId>
	<version>2.2.7</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-osgi</artifactId>
	<version>2.2.7</version>
</dependency>

これで、自動的に必要なライブラリがダウンロードされてくると思います。
それと、XMLファイルを配置するディレクトリとして、configディレクトリを作成します。
次に下のMavenコマンドで、build.xmlmaven-build.xmlmaven-build.propertiesを生成します。

mvn ant:ant

生成できたら、その中のbuild.xmlを下記のように編集します。

<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
	<classpath refid="build.classpath"/>
</taskdef>
<target name="xjc">
	<xjc destdir="src">
		<schema dir="config" includes="*.xsd"/>
	</xjc>
</target>

次にXMLファイルを作成します。
作成したら、先ほど作成したconfigディレクトリにファイルを置きます。
今回の場合は、下の様な定義なります。

<schema targetNamespace="http://chronos/system/gyao/service/resource_1"
	xmlns="http://www.w3.org/2001/XMLSchema"
	xmlns:tns="http://chronos/system/gyao/service/resource_1"
	xmlns:dv="http://chronos/system/gyao/service/resource_1"
	elementFormDefault="qualified">
	<element name="categoryResouce">
		<complexType>
			<sequence>
				<element name="category" maxOccurs="unbounded">
					<complexType>
						<sequence>
							<element name="key" type="string"/>
							<element name="value" type="string"/>
						</sequence>
					</complexType>
				</element>
			</sequence>
		</complexType>
	</element>
</schema>

これで、準備完了なので、antのxjcタスクを実行すると、JAXB対応のJavaクラスが生成されます。
あと、JAXB対応のRESTやSOAPなどのフレームワークで利用すれば、
簡単にJSONXMLのリクエストやレスポンスなどをなにもしないで、Javaクラスへ自動マッピングすることが
できると思います。
ちなみに、自分は、Restサービスの場合、Jerseyで、JAXBを使ってます。
なので、次回は、JerseyでのRestサービスに関して、書こうと思います。