楽々Framework IIのClassLoader

ある案件で、ログイン時にログインユーザの情報をセッションに格納して、 全画面のフッターにログイン情報を表示する処理を入れていたのですが、実行するとClassCastExceptionが起きる。
Object obj = x_ssp.g_ss.getObject("key");
LoginInfo loginInfo = (LoginInfo)obj;  ここでClassCastExceptionが発生
調べてみると、楽々Framework IIではHOT deploy機能が実装されていて、そのために標準で用意されているクラスローダがあります。
ログイン時に実行されるクラスはこのクラスローダを使用しているのですが、
ServletクラスだけでなくProjectクラスはサーブレットコンテナのクラスローダによってロードされるようです。
フッターにログイン情報を表示する処理はまさにProjectクラスで行っていたため、発生していたようです。

これを回避するには、 SeiConfigのパラメータのJ2EEのクラスローダを有効にし、サーブレットコンテナのクラスローダを使用するか、 Projectクラスで楽々Framework IIのクラスローダを利用することで対応できるそうです。

試しにJ2EEのクラスローダを有効にする設定で実行してみたら、
例外も発生せずサーブレットコンテナのクラスローダでロードされていることが確認できました。

また、楽々Framework IIのクラスローダを利用する方法も試してみたのですが、
下記のコードのようにProjectクラスをロードしたクラスローダを使用してクラスをロードして、
リフレクションでそのクラスのメソッドにアクセスするという様な実装になりました。
Object obj = x_ssp.g_ss.getObject("Key");
ClassLoader classLoader = SeiClassLoader.getLoader(x_ssp);
Class clazz = classLoader.loadClass("LoginInfo");
//ログインユーザID
Method method = clazz.getMethod("getLoginUserId", null);
Object result = method.invoke(obj, new Object[]{});
上記コードでログインユーザIDを取得しましたが、それ以外にログインユーザ名、ログイン日時など、 そのほかの情報も必要な場合は同様にリフレクションを使用して各プロパティのgetterメソッドにアクセスする必要があります。

今回のようにログイン情報を格納しているだけのObjectのアクセスに、リフレクションを使用せずに対応したい場合オブジェクトのディープコピーでもいいかもしれません。
下記のコードのように、オブジェクトのディープコピーで対応した場合は、クラスローダを意識する必要もなく、コピーしたLoginInfoに普通にアクセスできました。
Object obj = x_ssp.g_ss.getObject("Key");
 
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
p_oos.writeObject(obj);
p_oos.close();
 
byte[] bytes = bos.toByteArray();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
LoginInfo loginInfo = (LoginInfo) ois.readObject();
ois.close();
二つの方法を試してみた結果、楽々Framework IIのクラスローダを利用して対応する方法や、
オブジェクトのコピーで対応する場合は、それぞれの知識が必要となるため、
J2EEのクラスローダを使用する方が、SeiConfig.xmlのプロパティを1つ追加するのみで、クラスローダに悩まされることも無く良いと思います。

ただし、このパラメータを使用すると楽々で実装されているHOT deploy機能は使用できなくなりますが、 代わりにアプリケーションサーバのHOT deploy設定が有効にできる環境であれば、
そちらのHOT deploy機能が使用できるので特に問題ないと思います。