3.6.2 ディスパッチベースの実装例
Application Serverでサポートしているjavax.xml.ws.Dispatchインタフェース,JAX-WS 2.2仕様,JAXB 2.2仕様,およびSAAJ 1.3仕様などのAPIを使用して開発してください。
(1) ディスパッチベースのWebサービスクライアントの実装例
ディスパッチベースのWebサービスクライアントの実装例を次に示します。
package com.example.sample.client; import javax.xml.namespace.QName; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPBodyElement; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPMessage; import javax.xml.ws.Dispatch; import javax.xml.ws.Service; import javax.xml.ws.soap.SOAPBinding; public class TestClient { public static void main( String[] args ) { QName port = new QName( "http://sample.com", "AddNumbersImplPort" ); SOAPBody soapBody = null; // サービスを生成する Service service = Service.create( new QName("http://sample.com", "UserInfoPort") ); // サービスにポートを追加する service.addPort( port, SOAPBinding.SOAP11HTTP_BINDING, "http://localhost:80/dispatch_provider/UserInfoService" ); // ディスパッチを生成する Dispatch<SOAPMessage> dispatch = service.createDispatch( port, SOAPMessage.class, Service.Mode.MESSAGE ); SOAPMessage request = null; try{ // 要求メッセージを SAAJ 1.3仕様のAPIを使用して生成していく request = MessageFactory.newInstance().createMessage(); SOAPBody reqSoapBody = request.getSOAPBody(); SOAPElement soapElement = null; // SOAPボディに要素を追加 SOAPBodyElement requestRoot= reqSoapBody.addBodyElement( new QName( ... ) ); soapElement = requestRoot.addChildElement( new QName( ... ) ); soapElement.addTextNode( ... ); // 添付ファイルを追加する File attachment = new File( ... ); FileDataSource fds = new FileDataSource( attachment ); AttachmentPart apPart = request.createAttachmentPart( new DataHandler( fds ) ); request.addAttachmentPart(apPart); } catch( SOAPException e ){ // 例外処理 } // 作成した要求メッセージを指定し,ディスパッチを利用してWebサービスを呼び出す SOAPMessage response = dispatch.invoke( request ); try{ // 応答メッセージについて必要な処理を行う SOAPBody resSoapBody = response.getSOAPBody(); ... } catch( SOAPException e ){ // 例外処理 } } }
プロバイダ実装クラスから送信されたSOAPフォルトをWebサービスクライアントの実装で利用する場合は,try-catchブロック内でinvoke()メソッドを呼び出し,javax.xml.ws.soap.SOAPFaultException例外を取得します。SOAPフォルトも,javax.xml.ws.soap.SOAPFaultException例外から取得できます。実装例を次に示します。
package com.example.sample.client; import javax.xml.namespace.QName; ... import javax.xml.ws.soap.SOAPBinding; import javax.xml.ws.soap.SOAPFaultException; public class TestClient { public static void main( String[] args ) { ... try{ // 要求メッセージを SAAJ 1.3仕様のAPIを使用して生成していく ... } catch( SOAPException e ){ // 例外処理 } SOAPMessage response = null; try{ // 作成した要求メッセージを指定し,ディスパッチを利用してWebサービスを呼び出す response = dispatch.invoke( request ); } catch( SOAPFaultException e ){ // SOAPフォルトを取得する処理 SOAPFault fault = e.getFault(); // 取得した SOAPフォルトに対して必要な処理を行う String faultCode = fault.getFaultCode(); ... } try{ // 応答メッセージについて必要な処理を行う ... } catch( SOAPException e ){ e.printStackTrace(); } } }
(2) 参照されるエンドポイントアドレス
接続するWebサービスのURL(エンドポイントアドレス)は,メッセージコンテキストのjavax.xml.ws.service.endpoint.addressプロパティで指定および変更できます。エンドポイントアドレスを指定・変更する例については,「3.6.1(5)(c) ポートのメソッドを呼び出す」を参照してください。
(3) サービスクラスおよびディスパッチの再利用
サービスクラスおよびディスパッチの生成には処理コストが掛かるので,一度生成したサービスクラスおよびディスパッチは再利用することをお勧めします。ポートを追加したりディスパッチを生成したりするためにサービスクラスを複数回生成する必要はありません。同様に,ディスパッチのinvokeメソッドを複数回呼び出すためにディスパッチを複数回取得する必要はありません。ただし,複数スレッドでディスパッチを共有する場合,共有するディスパッチの要求コンテキストのプロパティに対する設定は,複数スレッドが動作する前に実行してください。複数スレッドの動作中にプロパティに対する設定を行うと,通信が失敗したり,不正なSOAPメッセージが送信されたりすることがあります。なお,ディスパッチは要求コンテキスト以外,スレッドセーフです。
WebサービスクライアントをサーブレットやEJBなどで実装する場合は,それぞれの初期化メソッドでサービスクラスおよびディスパッチを取得し,再利用することをお勧めします。ディスパッチの要求コンテキストのプロパティに対する変更も,それぞれの初期化メソッドで実行してください。