Menu Close

第41章 未加工の XML メッセージの使用

概要

高レベルの JAX-WS API は、データを JAXB オブジェクトにマーシャリングすることで、開発者がネイティブ XML メッセージを使用しないように保護します。ただし、ネットワークを通過する未加工の XML メッセージデータに直接アクセスする方がよい場合があります。JAX-WS API は、未加工の XML へのアクセスを提供する 2 つのインターフェースを提供します。Dispatch インターフェースはクライアント側のインターフェースで、Provider インターフェースはサーバー側のインターフェースです。

41.1. コンシューマーでの XML の使用

概要

Dispatch インターフェースは、未加工メッセージを直接操作できるようにする低レベル JAX-WS API です。DOM オブジェクト、SOAP メッセージ、および JAXB オブジェクトなど、多くの型のメッセージやペイロードを受け入れて返します。これは低レベル API であるため、Dispatch インターフェースは高レベルの JAX-WS API が実行するメッセージの準備を一切実行しません。Dispatch オブジェクトに渡すメッセージまたはペイロードが適切に構築され、呼び出されるリモート操作に対して意味を持つことを確認する必要があります。

41.1.1. 使用モード

概要

Dispatch オブジェクトには、2 つの 使用モード があります。

Dispatch オブジェクトに指定する使用モードは、ユーザーレベルのコードに渡される情報の量を決定します。

メッセージモード

メッセージモード では、Dispatch オブジェクトは完全なメッセージと共に機能します。完全なメッセージには、バインディング固有のヘッダーおよびラッパーが含まれます。たとえば、SOAP メッセージを必要とするサービスと対話するコンシューマーは、Dispatch オブジェクトの invoke() メソッドに完全に指定された SOAP メッセージを提供する必要があります。invoke() メソッドも、完全に指定された SOAP メッセージを返します。コンシューマーコードは、SOAP メッセージのヘッダーおよび SOAP メッセージのエンベロープ情報を完了して読み取ります。

JAXB オブジェクトを使用する場合、メッセージモードは理想的ではありません。

Dispatch オブジェクトがメッセージモードを使用するように指定するには、Dispatch オブジェクトの作成時に値 java.xml.ws.Service.Mode.MESSAGE を提供します。Dispatch オブジェクトの作成の詳細は、「Dispatch オブジェクトの作成」を参照してください。

ペイロードモード

ペイロードモード (メッセージペイロードモードとも呼ばれる) では、Dispatch オブジェクトはメッセージのペイロードとのみ動作します。たとえば、ペイロードモードで動作している Dispatch オブジェクトは、SOAP メッセージのボディーとのみ動作します。バインディングレイヤーは、バインディングレベルのラッパーおよびヘッダーを処理します。invoke() メソッドから結果が返されると、バインディングレベルのラッパーとヘッダーはすでに取り除かれ、メッセージのボディーのみが残ります。

Apache CXF XML バインディングなどの特別なラッパーを使用しないバインディングを操作する場合は、ペイロードモードとメッセージモードで同じ結果が得られます。

Dispatch オブジェクトがペイロードモードを使用するように指定するには、Dispatch オブジェクトの作成時に値 java.xml.ws.Service.Mode.PAYLOAD を提供します。Dispatch オブジェクトの作成の詳細は、「Dispatch オブジェクトの作成」を参照してください。

41.1.2. データ型

概要

Dispatch オブジェクトは低レベルのオブジェクトであるため、これらはより高いレベルのコンシューマー API と同じ JAXB 生成の型を使用するようには最適化されていません。Dispatch オブジェクトは、以下の型のオブジェクトと連携します。

Source オブジェクトの使用

Dispatch オブジェクトは、javax.xml.transform.Source インターフェースから派生するオブジェクトを受け入れ、返します。Source オブジェクトは、任意のバインディングにより、またメッセージモードまたはペイロードモードのいずれでもサポートされます。

Source オブジェクトは、XML ドキュメントを保持する低レベルのオブジェクトです。各 Source 実装は、保存された XML ドキュメントにアクセスし、そのコンテンツを操作する手段を提供します。以下のオブジェクトは Source インターフェースを実装しています。

DOMSource
Document Object Model (DOM) ツリーとして XML メッセージを保持します。XML メッセージは、getNode() メソッドを使用してアクセスされる Node オブジェクトのセットとして保存されます。ノードは、setNode() メソッドを使用して更新または DOM ツリーに追加できます。
SAXSource
Simple API for XML (SAX) オブジェクトとして XML メッセージを保持します。SAX オブジェクトには、未加工のデータを保持する InputSource オブジェクトと、未加工のデータを解析する XMLReader オブジェクトが含まれます。
StreamSource
データストリームとして XML メッセージを保持します。このデータストリームは、他のデータストリームと同じ様に操作できます。

汎用 Source オブジェクトを使用するように Dispatch オブジェクトを作成する場合、Apache CXF はメッセージを SAXSource オブジェクトとして返します。

この動作は、エンドポイントの source-preferred-format プロパティーを使用して変更できます。Apache CXF ランタイムの設定に関する詳細は、パートIV「Web サービスのエンドポイントの設定」を参照してください。

SOAPMessage オブジェクトの使用

以下の条件が満たされる場合、Dispatch オブジェクトは javax.xml.soap.SOAPMessage オブジェクトを使用できます。

  • Dispatch オブジェクトが SOAP バインディングを使用している
  • Dispatch オブジェクトがメッセージモードを使用している

SOAPMessage オブジェクトは SOAP メッセージを保持します。これには、1 つの SOAPPart オブジェクトと 0 個以上の AttachmentPart オブジェクトが含まれます。SOAPPart オブジェクトには、SOAP メッセージの SOAP 固有部分が含まれます。これには、SOAP エンベロープ、SOAP ヘッダー、および SOAP メッセージボディーが含まれます。AttachmentPart オブジェクトには、アタッチメントとして渡されるバイナリーデータが含まれます。

DataSource オブジェクトの使用

以下の条件が満たされる場合、Dispatch オブジェクトは javax.activation.DataSource インターフェースを実装するオブジェクトを使用できます。

  • Dispatch オブジェクトが HTTP バインディングを使用している
  • Dispatch オブジェクトがメッセージモードを使用している

DataSource オブジェクトは、URL、ファイル、および バイトアレイなどのさまざまなソースからの MIME 型のデータを操作するメカニズムを提供します。

JAXB オブジェクトの使用

Dispatch オブジェクトは、未加工のメッセージに対応できる低レベル API であることが意図されていますが、これらの API により JAXB オブジェクトを操作することもできます。JAXB オブジェクトを操作するには、使用中の JAXB オブジェクトをマーシャリングおよびアンマーシャリングできる JAXBContext を Dispatch オブジェクトに渡す必要があります。Dispatch オブジェクトの作成時に JAXBContext が渡されます。

JAXBContext オブジェクトによって認識される任意の JAXB オブジェクトを、パラメーターとして invoke() メソッドに渡すことができます。返されたメッセージを JAXBContext オブジェクトによって認識される JAXB オブジェクトにキャストすることもできます。

JAXBContext オブジェクト作成の詳細は、「39章JAXBContext オブジェクトの使用」を参照してください。

41.1.3. Dispatch オブジェクトの操作

手順

Dispatch オブジェクトを使用してリモートサービスを呼び出すには、以下のシーケンスを実行する必要があります。

  1. Dispatch オブジェクトを 作成します
  2. リクエストメッセージを 作成します
  3. 適切な invoke() メソッドを呼び出します。
  4. 応答メッセージを解析します。

Dispatch オブジェクトの作成

Dispatch オブジェクトを作成するには、以下を実行します。

  1. Dispatch オブジェクトが呼び出しを行うサービスを定義する wsdl:service 要素を表す Service オブジェクトを作成します。「Service オブジェクトの作成」を参照してください。
  2. 例41.1「createDispatch() メソッド」に表示される Service オブジェクトの createDispatch() メソッドを使用して、Dispatch オブジェクトを作成します。

    例41.1 createDispatch() メソッド

    publicDispatch<T>createDispatchQNameportNamejava.lang.Class<T>typeService.ModemodeWebServiceException

    注記

    JAXB オブジェクトを使用している場合、createDispatch() のメソッド署名は publicDispatch<T>createDispatchQNameportNamejavax.xml.bind.JAXBContextcontextService.ModemodeWebServiceException です。

    表41.1「createDispatch() のパラメーター」で、createDispatch() メソッドのパラメーターを説明します。

    表41.1 createDispatch() のパラメーター

    パラメーター説明

    portName

    Dispatch オブジェクトが呼び出しを行うサービスプロバイダーを表す wsdl:port 要素の QName を指定します。

    type

    Dispatch オブジェクトによって使用されるオブジェクトのデータ型を指定します。「データ型」を参照してください。JAXB オブジェクトを操作する場合、このパラメーターは JAXB オブジェクトのマーシャリングおよびアンマーシャリングに使用される JAXBContext オブジェクトを指定します。

    mode

    Dispatch オブジェクトの使用モードを指定します。「使用モード」を参照してください。

例41.2「Dispatch オブジェクトの作成」に、ペイロードモードで DOMSource オブジェクトと連携する Dispatch オブジェクトを作成するコードを示します。

例41.2 Dispatch オブジェクトの作成

package com.fusesource.demo;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class Client
{
public static void main(String args[])
  {
    QName serviceName = new QName("http://org.apache.cxf", "stockQuoteReporter");
    Service s = Service.create(serviceName);

    QName portName = new QName("http://org.apache.cxf", "stockQuoteReporterPort");
    Dispatch<DOMSource> dispatch = s.createDispatch(portName,
                                                  DOMSource.class,
                                                  Service.Mode.PAYLOAD);
    ...

リクエストメッセージの構築

Dispatch オブジェクトを操作する場合、リクエストは最初から構築する必要があります。開発者は、Dispatch オブジェクトに渡されるメッセージが対象のサービスプロバイダーが処理できるリクエストに一致することを確認する必要があります。これには、サービスプロバイダーによって使用されるメッセージに関する正確な知識と、要求されるヘッダー情報 (該当する場合) が必要です。

この情報は、メッセージを定義する WSDL ドキュメントまたは XML スキーマドキュメントによって提供されます。サービスプロバイダーは大幅に異なりますが、従うべきガイドラインがいくつかあります。

  • リクエストのルート要素は、呼び出される操作に対応する wsdl:operation 要素の name 属性の値に基づく。

    警告

    呼び出されるサービスが doc/literal ベアメッセージを使用する場合、リクエストのルート要素は、wsdl:operation 要素によって参照される wsdl:part 要素の name 属性の値に基づきます。

  • リクエストのルート要素は、namespace 認定である。
  • 呼び出されるサービスが rpc/literal メッセージを使用する場合、リクエストの最上位要素は namespace 認定ではない。

    重要

    最上位の要素の子は namespace 認定の場合があります。確認するためには、スキーマの定義を調べる必要があります。

  • 呼び出されるサービスが rpc/literal メッセージを使用する場合、最上位要素のいずれも null にすることはできない。
  • 呼び出されるサービスが doc/literal メッセージを使用する場合、メッセージのスキーマ定義によって要素のいずれかが namespace 認定であるかどうかが判断される。

サービスが XML メッセージをどのように使用するかの詳細は、WS-I の基本プロファイル を参照してください。

同期呼び出し

応答を生成する同期呼び出しを行うコンシューマーの場合は、例41.3「Dispatch.invoke() メソッド」に記載されている Dispatch オブジェクトの invoke() メソッドを使用します。

例41.3 Dispatch.invoke() メソッド

TinvokeTmsgWebServiceException

invoke() メソッドに渡される応答とリクエストの両方の型は、Dispatch オブジェクトの作成時に決定されます。たとえば、createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE) を使用して Dispatch オブジェクトを作成する場合、応答とリクエストの両方が SOAPMessage オブジェクトになります。

注記

JAXB オブジェクトを使用する場合、応答とリクエストの両方は、提供された JAXBContext オブジェクトがマーシャリングおよびアンマーシャリングできる任意の型にすることができます。また、応答とリクエストを異なる JAXB オブジェクトにすることもできます。

例41.4「Dispatch オブジェクトを使用した同期呼び出しの作成」に、DOMSource オブジェクトを使用してリモートサービスで同期呼び出しを行うコードを示します。

例41.4 Dispatch オブジェクトを使用した同期呼び出しの作成

// Creating a DOMSource Object for the request
DocumentBuilder db = DocumentBuilderFactory.newDocumentBuilder();
Document requestDoc = db.newDocument();
Element root = requestDoc.createElementNS("http://org.apache.cxf/stockExample",
                                          "getStockPrice");
root.setNodeValue("DOW");
DOMSource request = new DOMSource(requestDoc);

// Dispatch disp created previously
DOMSource response = disp.invoke(request);

非同期呼び出し

Dispatch オブジェクトは非同期呼び出しもサポートします。「40章非同期アプリケーションの開発」で説明されるより高いレベルの非同期 API と同様、Dispatch オブジェクトはポーリングアプローチとコールバックアプローチの両方を使用できます。

ポーリングアプローチを使用する場合、invokeAsync() メソッドは、応答が到達しているかどうかを確認するためにポーリングできる Response<t> オブジェクトを返します。例41.5「ポーリングの Dispatch.invokeAsync() メソッド」に、ポーリングアプローチを使用して非同期呼び出しを行うために使用されるメソッドの署名を示します。

例41.5 ポーリングの Dispatch.invokeAsync() メソッド

Response <T>invokeAsyncTmsgWebServiceException

非同期呼び出しへのポーリングアプローチの使用に関する詳細は、「ポーリングアプローチを使用した非同期クライアントの実装」を参照してください。

コールバックアプローチを使用する場合は、invokeAsync() メソッドは、応答が返される時に処理する AsyncHandler 実装を受け取ります。例41.6「コールバックを使用した Dispatch.invokeAsync() メソッド」に、コールバックアプローチを使用して非同期呼び出しを行うために使用されるメソッドの署名を示します。

例41.6 コールバックを使用した Dispatch.invokeAsync() メソッド

Future<?>invokeAsyncTmsgAsyncHandler<T>handlerWebServiceException

非同期呼び出しへのコールバックアプローチの使用に関する詳細は、「コールバックアプローチを使用した非同期クライアントの実装」を参照してください。

注記

同期 invoke() メソッドと同様に、応答の型およびリクエストの型は、Dispatch オブジェクトの作成時に決定されます。

一方向呼び出し

リクエストが応答を生成しない場合は、Dispatch オブジェクトの invokeOneWay() を使用してリモート呼び出しを行います。例41.7「Dispatch.invokeOneWay() メソッド」に、このメソッドの署名を示します。

例41.7 Dispatch.invokeOneWay() メソッド

invokeOneWayTmsgWebServiceException

リクエストのパッケージ化に使用されるオブジェクトの型は、Dispatch オブジェクトの作成時に決定されます。たとえば、createDispatch(portName, DOMSource.class, Service.Mode.PAYLOAD) を使用して Dispatch オブジェクトが作成されると、リクエストは DOMSource オブジェクトにパッケージ化されます。

注記

JAXB オブジェクトを使用する場合、応答とリクエストは、提供された JAXBContext オブジェクトがマーシャリングおよびアンマーシャリングできる任意の型にすることができます。

例41.8「Dispatch オブジェクトを使用した一方向呼び出しの作成」に、JAXB オブジェクトを使用してリモートサービスで一方向呼び出しを行うコードを示します。

例41.8 Dispatch オブジェクトを使用した一方向呼び出しの作成

// Creating a JAXBContext and an Unmarshaller for the request
JAXBContext jbc = JAXBContext.newInstance("org.apache.cxf.StockExample");
Unmarshaller u = jbc.createUnmarshaller();

// Read the request from disk
File rf = new File("request.xml");
GetStockPrice request = (GetStockPrice)u.unmarshal(rf);

// Dispatch disp created previously
disp.invokeOneWay(request);