オブジェクト XML マッパーを使用した XML のマーシャリング

導入

この章では、Spring のオブジェクト XML マッピングのサポートについて説明します。オブジェクト -XML マッピング(略して O-X マッピング)は、XML ドキュメントをオブジェクトに変換したり、オブジェクトから XML ドキュメントを変換したりする行為です。この変換プロセスは、XML マーシャリングまたは XML 直列化とも呼ばれます。この章では、これらの用語を同じ意味で使用します。

O-X マッピングのフィールドでは、マーシャラーはオブジェクト(グラフ)を XML に直列化する責任があります。同様に、アンマーシャラーは XML をオブジェクトグラフにデシリアライズします。この XML は、DOM ドキュメント、入力または出力ストリーム、SAX ハンドラーの形式をとることができます。

O/X マッピングのニーズに Spring を使用する利点のいくつかは次のとおりです。

設定が簡単

Spring の Bean ファクトリにより、JAXB コンテキスト、JiBX バインディングファクトリなどを構築する必要なく、マーシャラーを簡単に構成できます。アプリケーションコンテキストの他の Bean と同様に、マーシャラーを構成できます。さらに、多くのマーシャラーが XML 名前空間ベースの構成を使用できるため、構成がさらに簡単になります。

一貫したインターフェース

Spring の O-X マッピングは、Marshaller (Javadoc) Unmarshaller (Javadoc) の 2 つのグローバルインターフェースを介して動作します。これらの抽象化により、O-X マッピングフレームワークを比較的簡単に切り替えることができ、マーシャリングを行うクラスをほとんどまたはまったく変更する必要がありません。このアプローチには、ミックスアンドマッチアプローチ(たとえば、JAXB を使用して実行されるマーシャリングと XStream によって実行されるマーシャリング)を使用して XML マーシャリングを非侵入的な方法で実行できるという追加の利点があります。技術。

一貫した例外階層

Spring は、基になる O-X マッピングツールの例外から、XmlMappingException をルート例外とする独自の例外階層への変換を提供します。これらのランタイム例外は元の例外をラップするため、情報は失われません。

Marshaller および Unmarshaller

で記述されていたように導入、マーシャラーは XML にオブジェクトを直列化し、アンマーシャラーオブジェクトに XML ストリームをデシリアライズ。このセクションでは、この目的で使用される 2 つの Spring インターフェースについて説明します。

Marshaller を理解する

Spring は、org.springframework.oxm.Marshaller インターフェースの背後にあるすべてのマーシャリング操作を抽象化します。その主なメソッドは次のとおりです。

public interface Marshaller {

	/**
	 * Marshal the object graph with the given root into the provided Result.
	 */
	void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}

Marshaller インターフェースには、特定のオブジェクトを特定の javax.xml.transform.Result にマーシャリングする 1 つのメインメソッドがあります。結果は、基本的に XML 出力の抽象化を表すタグ付けインターフェースです。次の表に示すように、具体的な実装はさまざまな XML 表現をラップします。

結果の実装 XML 表現をラップします

DOMResult

org.w3c.dom.Node

SAXResult

org.xml.sax.ContentHandler

StreamResult

java.io.File, java.io.OutputStream, or java.io.Writer

marshal() メソッドは最初のパラメーターとしてプレーンオブジェクトを受け入れますが、ほとんどの Marshaller 実装は任意のオブジェクトを処理できません。代わりに、オブジェクトクラスは、マッピングファイルにマッピングされるか、アノテーションでマークされるか、マーシャラーに登録されるか、共通の基本クラスを持つ必要があります。O-X テクノロジーがこれをどのように管理するかを決定するには、この章の後のセクションを参照してください。

Unmarshaller を理解する

Marshaller と同様に、次のリストに示す org.springframework.oxm.Unmarshaller インターフェースがあります。

public interface Unmarshaller {

	/**
	 * Unmarshal the given provided Source into an object graph.
	 */
	Object unmarshal(Source source) throws XmlMappingException, IOException;
}

このインターフェースには、指定された javax.xml.transform.Source (XML 入力抽象化)から読み取り、読み取ったオブジェクトを返す 1 つのメソッドもあります。Result と同様に、Source は 3 つの具体的な実装を持つタグ付けインターフェースです。次の表に示すように、それぞれが異なる XML 表現をラップします。

ソース実装 XML 表現をラップします

DOMSource

org.w3c.dom.Node

SAXSource

org.xml.sax.InputSource, and org.xml.sax.XMLReader

StreamSource

java.io.File, java.io.InputStream, or java.io.Reader

2 つの個別のマーシャリングインターフェース(Marshaller および Unmarshaller)がありますが、Spring-WS のすべての実装は両方を 1 つのクラスに実装します。これは、1 つのマーシャラークラスを接続し、applicationContext.xml でマーシャラーとアンマーシャラーの両方として参照できることを意味します。

XmlMappingException を理解する

Spring は、基になる O-X マッピングツールからの例外を、XmlMappingException をルート例外として独自の例外階層に変換します。これらのランタイム例外は元の例外をラップするため、情報は失われません。

さらに、MarshallingFailureException と UnmarshallingFailureException は、基になる O-X マッピングツールがそうしない場合でも、マーシャリング操作とアンマーシャリング操作を区別します。

O-X マッピングの例外階層を次の図に示します。

oxm exceptions

Marshaller および Unmarshaller の使用

Spring の OXM は、さまざまな状況で使用できます。次の例では、Spring が管理するアプリケーションの設定を XML ファイルとしてマーシャリングするために使用します。次の例では、単純な JavaBean を使用して設定を表します。

  • Java

  • Kotlin

public class Settings {

	private boolean fooEnabled;

	public boolean isFooEnabled() {
		return fooEnabled;
	}

	public void setFooEnabled(boolean fooEnabled) {
		this.fooEnabled = fooEnabled;
	}
}
class Settings {
	var isFooEnabled: Boolean = false
}

アプリケーションクラスは、この Bean を使用して設定を保存します。メインメソッドに加えて、このクラスには 2 つのメソッドがあります。saveSettings() は設定 Bean を settings.xml という名前のファイルに保存し、loadSettings() はこれらの設定を再度読み込みます。次の main() メソッドは、Spring アプリケーションコンテキストを構築し、これら 2 つのメソッドを呼び出します。

  • Java

  • Kotlin

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class Application {

	private static final String FILE_NAME = "settings.xml";
	private Settings settings = new Settings();
	private Marshaller marshaller;
	private Unmarshaller unmarshaller;

	public void setMarshaller(Marshaller marshaller) {
		this.marshaller = marshaller;
	}

	public void setUnmarshaller(Unmarshaller unmarshaller) {
		this.unmarshaller = unmarshaller;
	}

	public void saveSettings() throws IOException {
		try (FileOutputStream os = new FileOutputStream(FILE_NAME)) {
			this.marshaller.marshal(settings, new StreamResult(os));
		}
	}

	public void loadSettings() throws IOException {
		try (FileInputStream is = new FileInputStream(FILE_NAME)) {
			this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
		}
	}

	public static void main(String[] args) throws IOException {
		ApplicationContext appContext =
				new ClassPathXmlApplicationContext("applicationContext.xml");
		Application application = (Application) appContext.getBean("application");
		application.saveSettings();
		application.loadSettings();
	}
}
class Application {

	lateinit var marshaller: Marshaller

	lateinit var unmarshaller: Unmarshaller

	fun saveSettings() {
		FileOutputStream(FILE_NAME).use { outputStream -> marshaller.marshal(settings, StreamResult(outputStream)) }
	}

	fun loadSettings() {
		FileInputStream(FILE_NAME).use { inputStream -> settings = unmarshaller.unmarshal(StreamSource(inputStream)) as Settings }
	}
}

private const val FILE_NAME = "settings.xml"

fun main(args: Array<String>) {
	val appContext = ClassPathXmlApplicationContext("applicationContext.xml")
	val application = appContext.getBean("application") as Application
	application.saveSettings()
	application.loadSettings()
}

Application では、marshaller プロパティと unmarshaller プロパティの両方を設定する必要があります。次の applicationContext.xml を使用してこれを行うことができます。

<beans>
	<bean id="application" class="Application">
		<property name="marshaller" ref="xstreamMarshaller" />
		<property name="unmarshaller" ref="xstreamMarshaller" />
	</bean>
	<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</beans>

このアプリケーションコンテキストでは XStream を使用しますが、この章で後述する他のマーシャラーインスタンスを使用することもできます。デフォルトでは、XStream はそれ以上の構成を必要としないため、Bean 定義はかなり単純であることに注意してください。また、XStreamMarshaller は Marshaller と Unmarshaller の両方を実装しているため、アプリケーションの marshaller と unmarshaller プロパティの両方で xstreamMarshaller Bean を参照できることに注意してください。

このサンプルアプリケーションは、次の settings.xml ファイルを生成します。

<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>

XML 構成名前空間

OXM 名前空間のタグを使用して、マーシャラーをより簡潔に構成できます。これらのタグを使用可能にするには、最初に XML 構成ファイルのプリアンブルで適切なスキーマを参照する必要があります。次の例は、その方法を示しています。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:oxm="http://www.springframework.org/schema/oxm" (1)
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/oxm
		https://www.springframework.org/schema/oxm/spring-oxm.xsd"> (2)
1oxm スキーマを参照します。
2oxm スキーマの場所を指定します。

このスキーマにより、次の要素が利用可能になります。

各タグは、それぞれのマーシャラーのセクションで説明されています。ただし、例として、JAXB2 マーシャラーの構成は次のようになります。

<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>

JAXB

JAXB バインディングコンパイラーは、W3C XML スキーマを 1 つ以上の Java クラス、jaxb.properties ファイル、場合によってはいくつかのリソースファイルに変換します。JAXB は、アノテーション付きの Java クラスからスキーマを生成する方法も提供します。

Spring は、Marshaller および Unmarshaller で説明されている Marshaller および Unmarshaller インターフェースに従って、JAXB 2.0 API を XML マーシャリング戦略としてサポートします。対応する統合クラスは、org.springframework.oxm.jaxb パッケージにあります。

Jaxb2Marshaller を使用する

Jaxb2Marshaller クラスは、Spring の Marshaller および Unmarshaller インターフェースの両方を実装します。操作するにはコンテキストパスが必要です。contextPath プロパティを設定することにより、コンテキストパスを設定できます。コンテキストパスは、スキーマ派生クラスを含むコロンで区切られた Java パッケージ名のリストです。また、classesToBeBound プロパティを提供します。これにより、マーシャラーがサポートするクラスの配列を設定できます。次の例に示すように、Bean に 1 つ以上のスキーマリソースを指定することにより、スキーマ検証が実行されます。

<beans>
	<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>org.springframework.oxm.jaxb.Flight</value>
				<value>org.springframework.oxm.jaxb.Flights</value>
			</list>
		</property>
		<property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/>
	</bean>

	...

</beans>

XML 構成名前空間

jaxb2-marshaller 要素は、次の例に示すように、org.springframework.oxm.jaxb.Jaxb2Marshaller を構成します。

<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>

または、class-to-be-bound 子要素を使用して、マーシャラーにバインドするクラスのリストを提供できます。

<oxm:jaxb2-marshaller id="marshaller">
	<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>
	<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/>
	...
</oxm:jaxb2-marshaller>

次の表に、使用可能な属性を示します。

属性 説明 必須

id

マーシャラーの ID

いいえ

contextPath

JAXB コンテキストパス

いいえ

JiBX

JiBX フレームワークは、Hibernate が ORM に提供するものと同様のソリューションを提供します。バインディング定義は、Java オブジェクトと XML の変換方法のルールを定義します。バインディングを準備し、クラスをコンパイルした後、JiBX バインディングコンパイラーはクラスファイルを強化し、XML からまたはクラスへのクラスのインスタンスの変換を処理するコードを追加します。

JiBX の詳細については、JiBX Web サイト (英語) を参照してください。Spring 統合クラスは org.springframework.oxm.jibx パッケージにあります。

JibxMarshaller を使用する

JibxMarshaller クラスは、Marshaller および Unmarshaller インターフェースの両方を実装します。操作するには、マーシャリングするクラスの名前が必要です。これは、targetClass プロパティを使用して設定できます。オプションで、bindingName プロパティを設定することにより、バインディング名を設定できます。次の例では、Flights クラスをバインドします。

<beans>
	<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
		<property name="targetClass">org.springframework.oxm.jibx.Flights</property>
	</bean>
	...
</beans>

JibxMarshaller は単一のクラスに対して構成されます。複数のクラスをマーシャリングする場合、異なる targetClass プロパティ値で複数の JibxMarshaller インスタンスを構成する必要があります。

XML 構成名前空間

次の例に示すように、jibx-marshaller タグは org.springframework.oxm.jibx.JibxMarshaller を構成します。

<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>

次の表に、使用可能な属性を示します。

属性 説明 必須

id

マーシャラーの ID

いいえ

target-class

このマーシャラーのターゲットクラス

はい

bindingName

このマーシャラーが使用するバインディング名

いいえ

XStream

XStream は、オブジェクトを XML に直列化し、再び戻すためのシンプルなライブラリです。マッピングを必要とせず、クリーンな XML を生成します。

XStream の詳細については、XStream Web サイト (英語) を参照してください。Spring 統合クラスは org.springframework.oxm.xstream パッケージにあります。

XStreamMarshaller を使用する

XStreamMarshaller は設定を必要とせず、アプリケーションコンテキストで直接設定できます。XML をさらにカスタマイズするために、次の例に示すように、クラスにマップされた文字列エイリアスで構成されるエイリアスマップを設定できます。

<beans>
	<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
		<property name="aliases">
			<props>
				<prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
			</props>
		</property>
	</bean>
	...
</beans>

デフォルトでは、XStream は任意のクラスの非整列化を許可します。これにより、安全でない Java 直列化効果が生じる可能性があります。そのため、XStreamMarshaller を使用して外部ソース(つまり、Web)から XML を非整列化することはお勧めしません。これにより、セキュリティの脆弱性が生じる可能性があります。

XStreamMarshaller を使用して外部ソースから XML を非整列化することを選択した場合、次の例に示すように、XStreamMarshaller で supportedClasses プロパティを設定します。

<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
	<property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/>
	...
</bean>

そうすることで、登録されたクラスのみがアンマーシャリングの対象になります。

さらに、カスタムコンバーター (Javadoc) を登録して、サポートされているクラスのみを非整列化できるようにすることができます。サポートするドメインクラスを明示的にサポートするコンバーターに加えて、リストの最後のコンバーターとして CatchAllConverter を追加することもできます。その結果、優先度が低く、セキュリティ上の脆弱性が存在する可能性があるデフォルトの XStream コンバーターは呼び出されません。

XStream は XML 直列化ライブラリであり、データバインディングライブラリではないことに注意してください。名前空間のサポートは制限されています。その結果、Web サービス内での使用にはかなり適していません。