Tomcatによるクラスタリング実施時に気をつけること
2008年07月19日
List#subList(int, int)から返却される
RandomAccessSubListは
Serializableを実装していない。
RandomAccessSubListは
Serializableを実装していない。
現在のプロジェクトでは、
■Apache 2.0系
■Tomcat 5.5系
(Apache - Tomcatはmod_jkで連携)
の環境でモジュールを動かしている。
Apache、Tomcatはそれぞれ2台ずつのクラスタ構成を組んでおり、
Tomcatの"catalina-cluster.jar"を使用した
インメモリセッションレプリケーションを行っている。
<参考>[ThinkIT] 第1回:Tomcatによるクラスタリングの実現 (3/4)
今回の開発案件によるモジュール改修に伴って、上記の環境だと下記のような感じのエラーが出ていた。
(※エラーはここと自分の中のかすかな記憶から捏造したモノ。)
> (DeltaManager.java:813)- Unable to serialize delta request
>
> java.io.NotSerializableException: java.util.RandomAccessSubList
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1054)
> at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1332)
> at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1304)
> at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1247)
> at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1052)
> at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:278)
> at org.apache.catalina.cluster.session.DeltaRequest$AttributeInfo.writeExternal(DeltaRequest.java:300)
> at org.apache.catalina.cluster.session.DeltaRequest.writeExternal(DeltaRequest.java:217)
> at org.apache.catalina.cluster.session.DeltaManager.unloadDeltaRequest(DeltaManager.java:393)
> at org.apache.catalina.cluster.session.DeltaManager.requestCompleted(DeltaManager.java:782)
どうやら、セッションに"Serializable"を実装していないオブジェクトがセットされている為にセッションレプリに失敗しているようだ。
しかし、セッションに保存するようなデータオブジェクトは全てSerializableを実装した共通の基底クラスを継承して製造しているから問題は無いはず。。。
と思ってたら、ある機能の処理で、List#subList(int, int)メソッドを使用してその戻りをセッションに保存するロジックが追加されていた。
List#subList(int, int)から返却されるオブジェクトは、
"java.util.RandomAccessSubList"という"Serializable"を実装していないモノである為、上記のような事象がおきていたようだ。
ロジックを下記のような感じに修正する事で、問題は解決した。。。
【修正前】
// 何らかの処理結果としてListのオブジェクトを取得
List resultList = execute.getList();
// 処理結果のListオブジェクトの1件目~5件目のデータを取得
// (この時に"xxxList"に設定されるオブジェクトの型が
// "RandomAccessSubList")
List xxxList = resultList.subList(0, 5);
HttpSession session = request.getSession();
// セッションにxxxList("RandomAccessSubList")を設定
session.setAttribute("replicationObj", xxxList);
【修正後】
// 何らかの処理結果としてListのオブジェクトを取得
List resultList = execute.getList();
// 処理結果のListオブジェクトの1件目~5件目のデータを取得
// ("RandomAccessSubList"型のオブジェクトを
// "ArrayList"に生成しなおしてxxxListに設定)
List xxxList = new ArrayList(resultList.subList(0, 5));
HttpSession session = request.getSession();
// セッションにxxxList("ArrayList")を設定
session.setAttribute("replicationObj", xxxList);
<参考>javaのRandomAccessSubListについて -OKWave
やはり、M/UT時からローカル端末にクラスタ環境構築して確認する必要があったのかなぁ。。。
Posted by dameningen at 01:10│Comments(0)
│Javaとか?