動的呼び出しクライアント その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