JSONBrokerのJava版クライアントを書いた
RubyクラスをJSONでアクセスできるWebサービス化するJSONBrokerのJava版クライアントを書いてみました。
サンプル
以下はクライアントを使ってjijiにアクセスし、レート情報を取得するサンプルです。
/** * レート情報を提供するサービス */ static interface RateService { /** * 指定期間のレート一覧を取得する * @param pair 通貨ペア * @param scale 4本値 * @param start 開始日時 * @param end 終了日時 * @return レート一覧 */ List<List<Double>> list( String pair, String scale, long start, long end ); } .... // サービスを作る。 RateService service = JsonRpcClient.create(RateService.class, new URL( "http://unageanu.homeip.net/jiji-demo/json/rate" )); // サービスのAPIを実行。 Calendar c = Calendar.getInstance( TimeZone.getTimeZone("JST") ); c.set(2009, 3, 1, 0, 0, 0); long start = c.getTimeInMillis()/1000; List<List<Double>> rates = service.list("EURJPY", "1h", start, start+24*60*60 ); for ( List<Double> rate : rates ) { System.out.println( rate ); }
実行結果です。何をやっているのかの詳細はこちらを参照。
[131.34, 131.07, 131.34, 130.69, 1238508000, 1238511600] [131.12, 131.44, 131.67, 130.85, 1238511600, 1238515200] [131.45, 131.43, 131.51, 131.21, 1238515200, 1238518800] [131.42, 131.27, 131.55, 131.26, 1238518800, 1238522400] [131.28, 131.61, 131.67, 131.26, 1238522400, 1238526000] [131.64, 131.48, 131.85, 131.39, 1238526000, 1238529600] [131.48, 131.13, 131.51, 131.07, 1238529600, 1238533200] [131.12, 130.96, 131.13, 130.83, 1238533200, 1238536800] [130.93, 131.16, 131.32, 130.93, 1238536800, 1238540400] [131.11, 131.67, 131.81, 131.0, 1238540400, 1238544000] [131.64, 130.18, 131.64, 129.99, 1238544000, 1238547600] [130.22, 130.85, 131.22, 130.22, 1238547600, 1238551200] [130.8, 130.65, 130.8, 130.4, 1238551200, 1238554800] [130.65, 130.36, 130.65, 130.19, 1238554800, 1238558400] [130.36, 130.13, 130.37, 129.89, 1238558400, 1238562000] [130.15, 130.31, 130.42, 129.97, 1238562000, 1238565600] [130.24, 130.38, 130.63, 130.05, 1238565600, 1238569200] [130.42, 130.12, 130.68, 129.93, 1238569200, 1238572800] [130.16, 130.56, 130.61, 130.0, 1238572800, 1238576400] [130.54, 131.09, 131.12, 130.46, 1238576400, 1238580000] [131.06, 131.24, 131.24, 130.96, 1238580000, 1238583600] [131.22, 130.93, 131.31, 130.89, 1238583600, 1238587200] [130.94, 130.69, 131.04, 130.61, 1238587200, 1238590800] [130.69, 130.7, 130.77, 130.5, 1238590800, 1238594400] [130.86, 130.7, 131.31, 130.7, 1238594400, 1238598000]
実装
ライブラリの実装は以下。タイプセーフ具合とか、いろいろ適当ですが。あとJSONICに依存しています。
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import java.util.Map; import net.arnx.jsonic.JSON; /** * JSON-RPC クライアント */ public class JsonRpcClient { /** * アクセスクライアントを作成する * @param <X> クライアントの型 * @param service クライアントインターフェイス * @param endpoint エンドポイントURL * @return アクセスクライアント */ @SuppressWarnings("unchecked") public static <X> X create( Class<X> service, URL endpoint ) { return (X) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class[] {service}, new JsonRpcInvocationHandler(endpoint) ); } private static final class JsonRpcInvocationHandler implements InvocationHandler { private URL endpoint; private JsonRpcInvocationHandler( URL endpoint ) { this.endpoint = endpoint; } @Override @SuppressWarnings("unchecked") public Object invoke ( Object proxy, Method method, Object[] args ) throws Throwable { StringBuilder sb = new StringBuilder("{"); sb.append( "\"method\":").append( method.getName() ).append( "," ); sb.append( "\"params\":").append( JSON.encode(args) ).append( "}" ); HttpURLConnection c = null; try { c = (HttpURLConnection) endpoint.openConnection(); c.setRequestMethod( "POST" ); c.setDoOutput(true); c.connect(); OutputStream out = null; try { out = c.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter( out, "UTF-8" ); osw.write( sb.toString() ); osw.flush(); } finally { if ( out != null ) out.close(); } InputStream in = null; try { in = c.getInputStream(); List<Object> list = (List<Object>) JSON.decode( in ) ; Map<String, Object> res = (Map<String, Object>) list.get(0); if ( res.get( "error" ) != null ) { throw new RuntimeException( String.valueOf( res.get( "error" ) ) ); } else { return res.get( "result" ); } } finally { if ( in != null ) in.close(); } } catch ( IOException e ) { throw e; } finally { if ( c != null ) c.disconnect(); } } } }
ちなみに、JavaScript版クライアントはこちら、ActionScript版クライアントはこちらにあります。