WAS 小ワザ集

第32回:Application Anti Pattern(8) HttpSessionに入れたオブジェクトを外部から変更する

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: WAS 小ワザ集

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:WAS 小ワザ集

このシリーズの続きに乞うご期待。

Anti Pattern

アプリケーションはHttpSessionに変更可能なオブジェクトを格納していました。あるサーブレットの中で,すでに格納されているこのオブジェクトの内容を変更する操作が実装されていました。この操作は,「オブジェクトをHttpSessionからgetAttributeメソッドで取り出す」「オブジェクトの内容を変更する」という処理が実装されていましたが,「変更したオブジェクトをsetAttributeメソッドで再格納する」という処理は実装されていませんでした。

 
AccessTime accessTime = (AccessTime)session.getAttribute(ATTRIB_NAME_ACCESSTIME);
accessTime.setLastAccessTime(System.currentTimeMillis());

Result

このアプリケーションは,単一のアプリケーションサーバーで実行されている時には問題を起こしませんでした。しかしHttpSessionを複数サーバーで共有しているクラスター環境で使用した場合に問題が発生しました。サーバー障害でFailoverしたとき,あるいは運用の都合でサーバーが停止されたとき,引き継ぎ先のサーバーでHttpSessionから取り出したオブジェクトには,引き継ぎ前に実行された変更内容が反映されていませんでした。

Best Practice

複数のWASアプリケーションサーバーでHttpSessionを共有している場合には,HttpSession外でオブジェクトを変更したとしても,その変更内容は他のアプリケーションサーバーに反映されません。変更を行った場合には,かならずsetAttributeメソッドでオブジェクトを更新する必要があります。

上記のコードは,正しくは以下のようなコードに変更する必要があります。

 
AccessTime accessTime = (AccessTime)session.getAttribute(ATTRIB_NAME_ACCESSTIME);
accessTime.setLastAccessTime(System.currentTimeMillis());
session.setAttribute(ATTRIB_NAME_ACCESSTIME, accessTime);

JSPファイル内で<jsp:useBean>タグでsessionスコープからオブジェクトを取得している場合も,オブジェクトの内容を変更する処理を行った場合には,かならずsetAttributeを呼び出してオブジェクトの更新をHttpSessionに通知してください。

 
<jsp:useBean id="pageHistory" class="com.ibm.jp.PageHistoryBean" scope="session" />
<%  pageHistory.setLastAccessPageID("JSID0023");
    session.setAttribute("pageHistory", pageHistory); %>

また、このようなトラブルを避けるためにも,HttpSessionには可能な限り変更不能なオブジェクト(Immutableなオブジェクト)のみを格納することをおすすめします。JavaのStringクラスやIntegerやDoubleなどのラッパークラスのインスタンスは,代表的な変更不能オブジェクトです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=WebSphere
ArticleID=957315
ArticleTitle=WAS 小ワザ集: 第32回:Application Anti Pattern(8) HttpSessionに入れたオブジェクトを外部から変更する
publish-date=12132013