シリアライズ

ひがさんだけにメールするのもなんなのでこっちに。


シリアライズ可能にするには、Serializableをimplするのが手っ取り早いです。


オブジェクトをシリアライズして、デシリアライズすると、
クラスローダーが違ってもClassCastExceptionが発生しません。
(簡単に言うとファイルに保存してるのと一緒)


なので、S2やS3は、ObjectOutputStream、ObjectInputStreamを使ってシリアライズ・デシリアライズしてます。


S2だと、この辺に失敗すると、元のクラスローダーでロードされたオブジェクトをそのまま返すので、ClassCastExceptionになります。
S3は最新だと例外投げるようになってます。


だけど、シリアライズ、デシリアライズの間で、クラス構造が変わると、デシリアライズできません。(例外になる)
privateフィールドが増えただけでです。
だから、何も考えないでSerializableをimplすんじゃねーボケみたいなことが書いてある本もあります。(タイトルは覚えてないけど)
理由は、privateフィールドも含めて互換性を保つ必要が出るから。


で、それをうまい事やるのがkimu-reloadableのSessionFilter。ObjectOutputStream、ObjectInputStreamに頼らずに、
自前でシリアライズ、デシリアライズをやってるから。もちろんその分遅くなる。


でも、セッションに値をセットする時は、Serializableが基本。
あと、互換云々は置いといて、開発中行き当たりばったりなコード書いてるとクラス構造変わるしみたいな??


ここで、セッションの中のクラスが変わるのも保障するのか、保障しないで再起動してもらうのか、
というカバー範囲があって、今のところS2もS3もカバーされてない。


基本S2Dxo作ったときと同じやり方してるんだけど、自前シリアライズ、デシリアライズの難しさを書いておく。
・プロパティーじゃなくて、フィールドで見る必要がある
・当たり前だけど、親クラスに同じフィールド名がある場合も個別に保存する必要がある
・ListやMapのフィールドに値が入ってたら、それらも保障しないと(さらにその先も)
・デシリアライズ時に、デフォルトコンストラクタがないこともある
・循環参照してたり
と結構メンドクセー(一応、kimu-reloadableは全部対応してるけど)
で、その間でフィールドが増えてたり減ってたりなどなどは無視。


とりあえず、どこまでカバーするかって話はあるんだけど、S3は例外になるので、今のところS2よりは分かりやすいはず。(おいらはコード書いてないけどw)
まとめると、S2もS3もここは再起動がいるよってこと。


2009/03/20追記
S2は、2009/03/19にセッションからnullが返るように対応されています。
(コンソールには「セッションオブジェクト({0})のシリアライズ形式が変更されたため破棄します。」って出る)