WebサービスII (第7回) 2007年11月7日 植田龍男
この時間の目標 JAX-WS 2.0 のアーキテクチャのまとめ クライアント側のクラスの働き SOAPメッセージとメッソッド呼び出し
復習:Webサービスの構築開始 import javax.jws.*; @WebService public class Hello { public String sayHello( String name ) { return “Hello,” + name; }
Java SE 6:Javaの側から構築 実装クラスを「ごく普通の Java」のプログラ ムとして書く ( POJO = Plain Old Java Object ) Webサービスのアノテーションを付ける (最低限なら @WebService のみ) サーバに渡す サーバ(Glassfish ver 2)の側で自動生成
自動生成(wsgenツール) javac hello/Hello.java wsgen -cp . hello.Hello hello.jaxws 以下に sayHello.java, sayHelloResponse.java sayHello.class sayHelloResponse.class (HelloService.wsdl, HelloServiceTypes.xsd)
サーバ側のまとめ サービスの実装クラス( Hello ) メソッド呼び出しの引数と返り値のクラス メソッド名(sayHello) プロパティ args0, args1,… メソッド名+Response(sayHelloResponse) プロパティ _return WSDL – 公開のURL ( Schema定義は分離したファイルに格納)
管理画面でのWSDLの確認
管理画面でサービスの確認(3)
管理画面でサービスの確認(4)
クライアントプログラムの準備 自動生成ツール wsimport wsimport HelloService.wsdl または Hello.class, HelloService.class, ObjectFactory.class SayHello.class, SayHelloResponse.class
クライアント側の構成 サービスのインタフェース( Hello ) サービスのインスタンスを取り出す「サービ ス」のクラス ( HelloService ) メソッドの引数と返り値のクラス ( sayHello, sayHelloResponse ) JAXBでインスタンス生成に必要なクラス ObjectFactory ( XML => Java で必要)
生成されたクラスの正体は? ツール javap (単純な逆アセンブラ) javap Hello interface Hello javap HelloService class extends javax.xml.ws.Service javap sayHello class sayHello javap sayHelloResponse class sayHelloResponse
WSDL のどこにクラスの情報? sayHello, sayHelloResponse <definitions> <types> include schema </types> : クラスの内容はJAXBによって完全に復元 サーバ側と「同じクラス」がクライアント側にも 存在すると考えてよい (データとしてやり取りされるクラスも同様)
WSDLのどこに情報が?(2) Hello インタフェース <definitions> : <portType> <operation>メソッド定義</operation> </portType> サーバ側の実装の情報は存在しない
WSDLのどこに情報が HelloService クラス Helloインタフェースの情報 + javax.xml.ws.Service クラス 拡張部分は 自身のコンストラクタ getHelloPort() メソッド -- Helloを実装したインスタンスを得る
クライアントプログラムの作成 public class HelloClient { public static void main ( String[] args ) { HelloService service = new HelloService(); Hello hello = service.getHelloPort(); String message =hello.sayHello( "Tatsuo" ); System.out.printf ( message ); }
Hello hello の謎 hello は Helloを実装したクラス 「代理オブジェクト」として振る舞うクライア ント側のクラス hello.sayHello( “Tatsuo” ); // サービスを呼び出す でも、どこに存在? (クラスファイルは生成されていない?) 以前のWebサービスでは HelloStab.class
クラス名を強引に調べてみると Hello hello = service.getHelloPort(); System.out.println( hello.getClass().getName() ); Proxy16 のような不思議な名前が出力 指定されたインタフェースを元に動的に生 成されるクラス
SOAPとは? XMLの形式でメッセージを交換 中立なデータ形式(事実上の標準) システム、言語、アプリケーション非依存 ver 1.0 http://www.w3.org/2000/xp/Group/ ver 1.2 http://www.w3.org/TR/2003/REC- soap12-part1-20030624/ メッセージが「構造」を持つ データ構造の定義は XML Schema で
そもそも SOAP とは何の略? SOAP(Simple Object Access Protocol) 登場当時の認識 現在:広範囲の応用範囲を支える基礎技術 「SOAP は SOAP」
SOAP のメッセージの構造 <SOAP-ENV:Envelope xmlns:SOAP-ENV= “ http://schemas.xmlsoap.org/soap/envelope/”> <SOAP-ENV:Header> </SOAP-ENV:Header> <SOAP-ENV:Body> <mymessage> Hello </mymessage> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
SOAPMessageの例(Hello) <SOAP-ENV:Envelope xmlns:SOAP-ENV= "http://schemas.xmlsoap.org/soap/envelope/ "> <SOAP-ENV:Body> <sayHello> <arg0>Tomoharu</arg0> </sayHello> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
SOAPMessageの例(Hello) <SOAP-ENV:Envelope xmlns:SOAP-ENV= "http://schemas.xmlsoap.org/soap/envelope/ "> <SOAP-ENV:Body> <sayHelloResponse> <return>Hello,Tomoharu</return> </sayHelloResponse> </SOAP-ENV:Body>
Java SE 6 : javax.xml.soap SOAPMessage クラス SOAPのメッセージを表す(送受信とも) getSOAPHeader(), getSOAPBody(), addAttachment(), getAttachment() など、メッセージ操作のメソッド群 SOAPConnection クラス 通信を実行 call() メソッド SOAPMessage response = sc.call( SOAPMessage request, Object url );
Java SE 6 : javax.xml.soap いずれもFactoryのパターンで利用 MessageFactory mf = MessageFactory.newInstance(); SOAPMessage request = mf.createMessage( new MimeHeaders(), new FileInputStream( source ) ); SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance() SOAPConnection connection = scf.createConnection();
サンプルソース(1) import java.io.*; import javax.xml.soap.*; public class SOAPTest { public static void main( String[] args ) { String url = "http://localhost:8080/HelloService/hello"; String source = "hello.xml";
サンプルソース(2) MessageFactory mf = MessageFactory.newInstance(); SOAPMessage request = mf.createMessage( new MimeHeaders(), new FileInputStream( source ) );
サンプルソース(3) SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); SOAPConnection connection = scf.createConnection(); SOAPMessage response = connection.call( request, url ); response.writeTo( System.out ); }