30歳過ぎから工学 vol.2

http://d.hatena.ne.jp/j130s/ から移行しました.オープンソースロボットソフトウェア技術者兼主夫. 高校・大学学部文系-->何となくソフトウェア開発業-->退職・渡米,テキサス州でシステムズ工学修士取得,しかし実装の方が楽しいと気付き縁があったロボティクス業界で再就職.現在 Texas 州内の産業用オートメーションのスタートアップに Georgia 州から遠隔勤務.

Java で REST (はてなグラフ自動更新プログラム作りました)

# はてなグラフのユーザは日本語読める人のみと思われるため, 今日は日本語です.
はてなグラフはてなグラフAPI 経由で更新するプログラムを Java で書きました. はてなグラフAPI 自体の使いこなしについてはコメントすべきほどのことはありませんでしたが, WSSE 認証機能を Java で実装する場合特有と思われるハマり処が 2箇所あったのでメモしておきます.

  • そもそも Java で WSSE認証 を実施する方法がわからない

はてなのサイトに perl, ruby しかサンプルコードが無かったです. java でやろうとするのは稀有なんでしょうか.
これはハマったというほどではなく, ここに載っているコードを利用させて頂くことで難なく解決. ただし今回は はてなグラフの仕様により http の post の実施が要るので, 後に示すように post を行うメソッドを追加します.

  • グラフ名が日本語の場合, 期待しない(文字化けしたような名前の)グラフが新規作成されてしまう

原因ははてなグラフ側ではなく, 上述の WSSE認証モジュール が内部で利用する Jakarta.commons の httpclient で, 日本語を post すると文字化けるという既知の現象のようです.
暫定回避策としては, single-byte で命名したグラフのみ使うという運用にすることも考えつきます. しかしこの問題もここに載っている方法で恒久的に解決しました.



以上2点の問題点を解決する HttpClient のコード(部分)を貼ります

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

public class WsseHttpClient extends HttpClient {
	private static final String CHARSET_UTF8 = "UTF-8";

	public WsseHttpClient() {
		super();
	}

	private HttpMethodBase executeMethod(HttpMethodBase method,
			String username, String password) throws HttpException, IOException {

		method.addRequestHeader("X-WSSE", this.getWsseHeaderValue(username,
				password));
		super.executeMethod(method);
		System.out.println("\t" + super.getClass().getName()
				+ "#executeMethod: " + method.getStatusLine().toString());
		System.out.println(method.getResponseBodyAsString());
		return method;
	}

	public HttpMethodBase post(String url, NameValuePair[] namVals,
			String username, String password) throws HttpException, IOException {
		PostMethod postMethod = new PostMethod(url);
		postMethod.addParameters(namVals);		
		// DO: set charset. according to
		//  http://blog.livedoor.jp/mikuriyahiroto/archives/50832779.html
		postMethod.getParams().setContentCharset(CHARSET_UTF8);
		this.executeMethod(postMethod, username, password);
		return postMethod;
	}

	public HttpMethodBase get(String url, String username, String password)
			throws HttpException, IOException {
		GetMethod getMethod = new GetMethod(url);
		this.executeMethod(getMethod, username, password);
		return getMethod;
	}

	protected final String getWsseHeaderValue(String username, String password) {
        // 以下ページの実装と同じ
        // http://yohei-y.blogspot.com/2005/04/java-atomapi.html 
	}
}