JavaとPythonをXML-RPCで結ぶ

最近、自分の扱うプログラムの数が増えてきました。Java、Python、Jython、Perl、Rubyって感じでしょうか。メインはもっぱらJavaなわけですが。前よりは結構いろいろなことができるようになってきたわけですが、一つの言語でやりたいことが完結するとは限りません。例えば

  • ほげほげしたいライブラリはJavaに、むにゃむにゃ(?)したいライブラリはPerlに
  • 計算部分はJavaで、出力部分はRuby on Railsで*1

などとやりたいときがあるでしょう。素人*2目にもよくないということが分かってしまいます。というか自分が今やってみたいというところです。

前にPerlからJavaプログラムを動かすみたいなことをやってみたことがあるのですが、かっこよくない気がします。なぜならば、以前のやり方だとライブラリを持っている言語から結果をファイルに書いて、そのファイルを使いたい側の言語で読み取って使う…みたいなことを前はやっていたからです。これだと処理がきちんと終わっていないときにファイルを開いてしまうかもしれません。というわけでできれば避けたい。

そんなときに以前Lingrにて、XML-RPCのことを教えてもらったことをふと思い出しました。当初*3は「XML-RPCって何だ?!」って感じで全然分からなかったし、当時の僕には需要がなかったのでほったらかしにしておきましたw。しかし、どうやらその需要が満たされたようなので、XML-RPCについて触ってみることにしました。

インターネット上でリモートプロシージャコールを実行するためのプロトコル。SOAPの基となった仕様。

クライアントがXML形式のテキストで記述された型付の引数をサーバ側アプリケーションに渡し、サーバが返り値を同じくXML形式のテキストで返すという動作をする。

XML-RPCとは - はてなキーワード

ということで詳しいことはあんまり分かってないのですが、どうやらサーバー側とクライアント側でXML形式のものをやり取りするようなものらしいということが分かりました。なるほど、サーバーとのやりとりみたいな感じだったら、さっきのファイルみたいなことは起こらない感じですね。

で、とりあえずJavaが一番慣れているので、JavaにてXML-RPCのサーバーとクライアントを実装してみることにしてみました。コードはここを参照しました。

クライアント側

import java.util.Vector;
import java.util.Hashtable;
import java.io.IOException;

import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

public class XMLRPCClient {
	public static void main(String[] args) {
		String url = "http://localhost:8084";
		String methodName ="Members.memberInfo";
		String name = "yasuhisa";
		Vector params = new Vector();
		params.add(name);
		try {
			XmlRpcClient client = new XmlRpcClient(url);
			try {
				Hashtable result = (Hashtable) client.execute(methodName,params);
				System.out.println("Name:" + result.get("name"));
				System.out.println("Age:" + new Integer(20));
				System.out.println("Birth:" + result.get("birth"));
			} catch (XmlRpcException e) {
				e.printStackTrace();
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}

サーバー側1

import org.apache.xmlrpc.WebServer;

public class StandAloneServer{
	public static void main(String[] args) {
		int port = 8084;
		WebServer server = new WebServer(port);
		server.addHandler("Members", new MembersHandler());
		server.start();
	}
}

サーバー側2

import java.util.Vector;
import java.util.Hashtable;
import java.util.Date;
import org.apache.xmlrpc.XmlRpcHandler;
public class MembersHandler implements XmlRpcHandler {
	public Object execute(String method, Vector params) throws Exception {
		if (!method.equals("Members.memberInfo")) {
			throw new Exception("I do not have the method:" + method);
		}
		String name = (String) params.get(0);
		if (!name.equals("yasuhisa")) {
			throw new Exception(name + " not found!");
		}
		Hashtable table = new Hashtable();
		table.put("name", name);
		table.put("age",Math.random());
		table.put("birth", new Date());
		return table;
	}
}

これで初めてのXML-RPCは終了。でも、Java同士で通信してても面白くないので、これとPythonで通信してみましょう。

import xmlrpclib

server_url = 'http://localhost:8084'
server = xmlrpclib.Server(server_url)
info=server.Members.memberInfo("yasuhisa")
for str,val in info.iteritems():
    print str,val

Pythonのコードを動かすとこんな感じに。

age 0.841595450538
name yasuhisa
birth 20070421T01:31:11

簡単なコードなのですが、何しろ始めてだったため動くまでにえらく苦労しましたorz。しかし、こういうのは一回動かし方が分かるといろいろ応用してできるようになるのでどうにかなるでしょう。XMLと名前にも入っているからXMLパースしたりするのかと思っていたのですが、コードを書くときにはXMLを見なくてもよさそうですね*4

*1:Railsは現在まだ使ったことがありませんが。

*2:当然僕のことですが。。。

*3:2月くらい

*4:仕様調べたりするときには見ないといけないでしょうが。