セッションリカバリ機能を使用するためのWebアプリケーションの条件を説明します。
Web application deployment descriptor (web.xml)にdistributableタグを記載する必要があります。
Interstage Web application deployment descriptor (glassfish-web.xml)にセッション永続化方法の記述を記載する必要があります。
Servlet3.0以降の規約である非同期処理を利用したアプリケーションを作成しないでください。
セッションの属性に格納するオブジェクトはjava.io.Serializableインタフェースをimplementsしている(オブジェクト直列化可能である)必要があります。
この条件を満たしていない場合、setAttributeを行ったときにIllegalArgumentExceptionが発生します。
セッションの属性に格納するオブジェクトが保持する直列化可能でないインスタンス変数には、transient修飾子を宣言してください(バックアップ、リカバリの対象外となります)。
OSおよびプロセス(Java VM)固有の資源を表すオブジェクトをセッションに格納した場合、動作の保証はできません。例えば、Threadクラスや入出力に関するクラス(InputStreamクラスやWriterクラスなどを継承したクラス)、CORBAやEJBのクライアント(スタブ、org.omg.CORBA.ORBやjavax.naming.Contextなど、およびこれに類するオブジェクトへの参照を保持するクラス)などはJava VMに固有の資源です。ユーザ定義オブジェクトを開発する場合には、このようなクラスを継承したり、このようなクラスへの参照を保持したりしないようにしてください。
セッションの属性にはアプリケーションのリクエストを復元するために必要な情報をすべて格納する必要があります。
セッションのリカバリ処理ではセッション属性に格納された情報だけが復元され、セッションとは別のオブジェクトやクラスに格納した情報は復元されません。そのため、アプリケーションのリクエスト処理がセッション属性以外の動的情報に依存している場合にセッションのリカバリ処理をしても、リカバリ先のWebコンテナでアプリケーションがリクエストを正しく処理できないことがあります。
セッション属性に格納するオブジェクトクラスを変更し、かつ変更前にバックアップされたセッションを継続して使用する場合、“セッション属性に格納するオブジェクトクラスを変更する方法”に示す対応方法に従ってオブジェクトクラスを作成、または修正する必要があります。
この条件を満たさない場合、クラス修正前に保存されたオブジェクトをクラス修正後に復元させようとするとjava.io.InvalidClassExceptionがログ出力され、アプリケーションのリクエストは新規セッションとして処理されます。
セッションリカバリでは「2.28.1.3 URIでのセッションリカバリ機能の有効・無効」の判定をリクエストされた拡張子まで含む完全URIに基づいて行います。アプリケーションへはURIを省略せずにアクセスできるようにしてください。
注意
セッションの属性に格納するオブジェクトのサイズが大きくなればなるほど、実行速度が遅くなります。
セッション属性に格納するオブジェクトクラスを変更する方法
セッション属性に格納するオブジェクトクラスを変更する場合、以下の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の仕様についてのドキュメントを参照してください。