セションリカバリ機能を使用するためのWebアプリケーションの条件を説明します。
セションの属性に格納するオブジェクトはjava.io.Serializableインタフェースをimplementsしている(オブジェクト直列化可能である)必要があります。
この条件を満たしていない場合、setAttributeを行ったときにIllegalArgumentExceptionが発生します。
セションの属性に格納するオブジェクトが保持する直列化可能でないインスタンス変数には、transient修飾子を宣言してください(バックアップ、リカバリの対象外となります)。
OSおよびプロセス(Java VM)固有の資源を表すオブジェクトをセションに格納した場合、動作の保証はできません。たとえば、Threadクラスや入出力に関するクラス(InputStreamクラスやWriterクラスなどを継承したクラス)、CORBAやEJBのクライアント(スタブ、org.omg.CORBA.ORBやjavax.naming.Context等、およびこれに類するオブジェクトへの参照を保持するクラス)などはJava VMに固有の資源です。ユーザ定義オブジェクトを開発する場合には、このようなクラスを継承したり、このようなクラスへの参照を保持したりしないようにしてください。
セションの属性にはアプリケーションのリクエストを復元するために必要な情報をすべて格納する必要があります。
セションのリカバリ処理ではセション属性に格納された情報だけが復元され、セションとは別のオブジェクトやクラスに格納した情報は復元されません。そのため、アプリケーションのリクエスト処理がセション属性以外の動的情報に依存している場合にセションのリカバリ処理をしても、リカバリ先のServletコンテナでアプリケーションがリクエストを正しく処理できないことがあります。
セション属性に格納するオブジェクトクラスを変更し、かつ変更前にバックアップされたセションを継続して使用する場合、“セション属性に格納するオブジェクトクラスを変更する方法”に示す対応方法に従ってオブジェクトクラスを作成、または修正する必要があります。
この条件を満たさない場合、クラス修正前に保存されたオブジェクトをクラス修正後に復元させようとするとjava.io.InvalidClassExceptionがログ出力され、アプリケーションのリクエストは新規セションとして処理されます。
注意
セションの属性に格納するオブジェクトのサイズが大きくなればなるほど、実行速度が遅くなります。
セション属性に格納するオブジェクトクラスを変更する方法
セション属性に格納するオブジェクトクラスを変更する場合、以下の2つの方法があります。
オブジェクトクラスの作成時に、将来の修正に備えておく方法
オブジェクトクラスの作成時に、修正に対する備えをしていなかった場合の変更方法
オブジェクトクラスの作成時に、将来の修正に備えておく方法
オブジェクトクラスの作成時に将来属性の変更があることを見越し、かつ修正前に格納した情報を修正後も使用したい場合、以下の対応が必要です。
オブジェクトクラスの作成時にserialVersionUIDをクラス変数として宣言し、任意の値(long整数)を設定しておきます。
修正前のオブジェクトクラス例
package com.fujitsu.sample; import java.io.*; public class Company implements Serializable { private String longName; private String shortName; private String address; static final long serialVersionUID = 10203040506070809L; ........(1) public Company(String longName, String shortName, String address) { : : } } (1):任意(一意)のlong整数値を設定します。
オブジェクトクラスを変更(属性追加)します。
修正後のオブジェクトクラス例
package com.fujitsu.sample; import java.io.*; public class Company implements Serializable { private String longName; private String shortName; private String address; private String telNumber; ........(2) static final long serialVersionUID = 10203040506070809L; public Company(String longName, String shortName, String address, String telNumber ) { : : } } (2):telNumber属性を追加します。
オブジェクトクラスの作成時に、修正に対する備えをしていなかった場合の変更方法
オブジェクトクラスの作成時に修正に対する備えをしていなく、かつ修正前に格納した情報を修正後も使用したい場合、以下の対応を行う必要があります。
修正前のオブジェクトクラス例
修正前のオブジェクトクラスではserialVersionUIDの対応はされていません。
package com.fujitsu.sample; import java.io.*; public class Company implements Serializable { private String longName; private String shortName; private String address; public Company(String longName, String shortName, String address) { : : } }
修正前クラスに対して、serialverコマンドを実行してserialVersionUIDを取得します。
serialVersionUIDの取得方法
> serialver com.fujitsu.sample.Company ←クラス名 com.fujitsu.sample.Company: static final long serialVersionUID = 7242562793746307240L; ←serialVersionUIDが通知されます。 >
修正後のクラスに取得したserialVersionUIDをクラス変数として設定します。
修正後のオブジェクトクラス例
package com.fujitsu.sample; import java.io.*; public class Company implements Serializable { private String longName; private String shortName; private String address; private String telNumber; ....(3) static final long serialVersionUID = 7242562793746307240L; ....(4) public Company(String longName, String shortName, String address, String telNumber ) { : : } } (3):telNumber属性を追加します。 (4):serialverコマンドで取得したsevialVersionUIDをクラス変数として設定します。
補足
修正前と修正後のオブジェクトクラスを一意なserialVersionUIDをつけることで互換性を持たせることができます。
修正前のオブジェクトクラスでバックアップしたセション情報を修正後のオブジェクトクラスでリカバリした場合、追加された属性値にはデフォルト値(String型:null、Int型:0 等)が通知され、エラーは通知されません。
オブジェクト直列化の詳細につきましては、以下のJavaの仕様についてのドキュメントを参照してください。
日本語: http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/serialization/index.html
英語 : http://download.oracle.com/javase/1.5.0/docs/guide/serialization/index.html