[java][ruby] JRubyからJavaのHttpClientを使う

今日、railsで作ってるサーバへの疎通確認をしてもらってたんですが、サーバとクライアントのどちらに問題があるのかわからなかったので、問題を切り分けるためにクライアント側で使うライブラリでちゃんとアクセスできるかどうか確認することにしました。

クライアントはJavaのhttpclientを使っているので、僕としては当然JRubyで使うわけです。書いたコードはこんな感じです。

localhostに対してGET /foo.json で得られたbarを POST /bazのパラメータとして使って送信してます

# -*- coding: utf-8 -*-

require 'java'
require 'rubygems'
require 'json'

# カレントディレクトリのlib以下に使用するjarを置いてください。
# jarは http://hc.apache.org/downloads.cgi のBinary とかからゲット可能です。
Dir['./lib/*.jar'].each{|f| require f}

import "java.io.BufferedReader"
import "java.io.InputStreamReader"
import "java.net.URLEncoder"
import "java.util.ArrayList"

import "org.apache.http.client.entity.UrlEncodedFormEntity"
import "org.apache.http.client.methods.HttpPost"
import "org.apache.http.client.methods.HttpGet"
import "org.apache.http.entity.StringEntity"
import "org.apache.http.impl.client.DefaultHttpClient"
import "org.apache.http.message.BasicNameValuePair"
import "org.apache.http.protocol.HTTP"

client = DefaultHttpClient.new

req = HttpGet.new("http://localhost/foo.json")
res = client.execute(req)
puts "status_code: #{res.getStatusLine.toString}"
rd = BufferedReader.new(InputStreamReader.new(res.getEntity.getContent))
lines = []
while line = rd.readLine
  lines << line
end
res_obj = JSON.parse(lines.join) # このJSONのparseはRubyのgemである"json"を使って行っています。
bar = res_obj['bar']

# GET /foo.json で得られたbarを POST /bazのパラメータとして使う

req = HttpPost.new("http://localhost/baz")
values = ArrayList.new(1)
values.add(BasicNameValuePair.new("bar", bar))
req.setEntity(UrlEncodedFormEntity.new(values, HTTP::UTF_8))

res = client.execute(req)
puts "status_code: #{res.getStatusLine.toString}"
rd = BufferedReader.new(InputStreamReader.new(res.getEntity.getContent))
while line = rd.readLine
  puts line
end

難しいRubyの文法を使わなかったのでJavaでクライアント側の実装をやってる人に読んでもらえたのが良かったです。

でも通信自身とは関係ない部分で、さりげなくJSON.parseとかRubyのライブラリを組み合わせて使っています。

rvmさえインストールされていれば、

$ rvm install jruby
$ rvm jruby
$ gem install json

で上記に必要なインストールは完了するはず。

あとは上のファイルの名前を java_httpclient_example.rb とするなら

$ jruby -S java_httpclient_example.rb

とかで実行できちゃいます。コンパイル不要です。

ちょっとだけJavaのライブラリを触るときにはこんな感じでやれると楽だなーと久しぶりに実感しました。