動的呼び出しクライアント その3 −通信成功−
RPC方式の通信処理
Axis2では、SOAP通信処理をするために、サーバ側では MessageReceiver、クライアント側では ServiceClient というものを利用します。
ドキュメントに載っていないので分からなかったけど、Axis2にもRPC方式の通信方法が用意されているようですね。
axis2-codegen-0.95.jar に含まれるクラスなのですが、WSDLからJavaソースを自動生成のための jar だと思ってS2Axis2の開発環境から外していたために、そんなクラスがあるのに気付かなかったョ(-_-)
上記のクラスのソースを見てみると、OMElement でSOAPメッセージを送受信する部分をラップしているだけのようですね。同じ処理を、自前で半分ぐらい作ってしまいました・・・ハァ。
サーバ
さて、気を取り直して、サーバから見直しです。
デフォルトではメッセージ・レシーバーとして RawXMLINOutMessageReceiver(OMElementを送受信するためのもの)が利用されます。これを、サービスをデプロイする際に、 RPCMessageReceiver が利用されるように指定します。メッセージ・レシーバーはメソッド単位で指定できるのですが、今回はサービスとして公開するメソッド全てに指定しています。
AxisService service; // サービスを生成 MessageReceiver receiver = new RPCMessageReceiver(); Iterator ite = service.getOperations(); while(ite.hasNext() == true) { AxisOperation ope = (AxisOperation)ite.next(); ope.setMessageReceiver(receiver); }
AxisRpcConnector
リモートのサービスを呼び出す Connector は以下のような感じになります。
public class AxisRpcConnector extends TargetSpecificURLBasedConnector { protected AxisService service; public void setService(AxisService service) { this.service = service; } protected Object invoke(URL url, Method method, Object args) throws Throwable { EndpointReference targetEPR = new EndpointReference(url.toString()); Options options = new Options(); options.setTo(targetEPR); OMElement request = createRequest(url, method, args); ServiceClient client = new ServiceClient(); client.setOptions(options); OMElement response = client.sendReceive(request); Object returnTypes = new Object { method.getReturnType() }; Object returnValue = BeanUtil.deserialize(response, returnTypes); Object result; if (returnValue != null && returnValue.length == 1) { result = returnValue[0]; } else { result = returnValue; } return result; } private OMElement createRequest(URL url, Method method, Object[] args) { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace(SchemaGenerator.SCHEMA_TARGET_NAMESPACE, SchemaGenerator.SCHEMA_NAMESPACE_PRFIX); QName qName = new QName(method.getName()); OMElement request = BeanUtil.getOMElement(qName, args, null); request.setNamespace(omNs); return request; } }
RPCServiceClient を使って通信しようとしたら、ネームスペースが設定されていないという原因でエラーになるため、結局、使用できませんでした。まあ、RPCServiceClient でも上と同じような処理を行っているので、問題ないでしょう。
サービス/クライアント
長くなってきましたが、ここからが実際にS2Axis2を利用するところです。
サービス/クライアントとして、OMElementを使用しないクラスを用意します。
- Echoサービス(インタフェース )
public interface Echo { String echo(int id, String message); }
- Echoサービス(実装クラス)
public class EchoImpl implements Echo { public String echo(int id, String message) { return "[id = " + id + "] " + message; } }
- Echoクライアント
public void test() { Echo echo = (Echo) getComponent(Echo.class); int id = 1; String msg = "test message"; String expect = "[id = " + id + "] " + msg; String result = echo.echo(id, msg); assertEquals(expect, result); System.out.println(result); }
diconファイルは、その2で書いた内容とほぼ変わりません。
サーバ起動後、テストクラスであるEchoクライアントを実行すると・・・結果は以下のようになり、無事メッセージが返ってきました。S2Axis2での通信が成功です!!
[id = 1] test message