ひがやすを技術ブログ

電通国際情報サービスのプログラマ

ThreadLocalを使いたい場合

コンポーネントから、HttpServletRequestなどにアクセスしたい場合もあるでしょう。そのような場合は、ThreadLocalを使って管理するのが一般的です。
しかし、このような管理クラスを作る場合に、シングルトンやstatic変数を使ってはいけません。グローバル変数はできるだけ避けなければなりません。それではどうすれば良いのでしょうか。
まず、くーすらしくRequestContextというインターフェースを定義します。


interface RequestContext {
HttpServletRequest getRequest();
void setRequest(HttpServletRequest request);
}
次は実装クラスです。

class RequestContextImpl extends RequestContext {
private ThreadLocal requests_ = new ThreadLocal();

HttpServletRequest getRequest() {
return (HttpServletRequest) requests_.get();
}
void setRequest(HttpServletRequest request) {
requests_.set(request);
}
}

このようにして、HttpServletRequestにアクセスしたいコンポーネントは、RequestContextをDIしてもらえばいいのです。テストのときには、ThreadLocalを使わないRequestContextの実装を使い、ThreadLocalの副作用を避けます。
staticなThreadLocalやシングルトンが良くないのは、あるテストで行ったことが別のテストに影響(副作用)を与えてしまうことです。
RequestContext、ResponseContextは次のSeasar2のリリースに含まれるかも。コンポーネントインスタンス管理をrequest,sessionごとに行うことに対する布石。


JSFもこうなってほしかったなぁ。> FacesContext
まさにシングルトンとThreadLocal。そのせいでテストがしにくいんですけど。