セッションレプリケーション機能を使用するためのWebアプリケーションの条件を説明します。
glassfish-web.xmlの<session-manager>タグのpersistence-type属性にredisを指定する必要があります。この設定を実施すると、Webアプリケーションのweb.xmlおよびWEB-INF/lib配下のjarファイルに<distributable>タグが設定されているかどうかにかかわらず、Webアプリケーションがdistributableであるとみなして動作します。
Webコンテナへ接続するクライアントの認証を行う場合、FORM認証は使用しないでください。FORM認証を使用する代わりに、セッション属性に認証関連の情報を格納することで、アプリケーション固有の認証処理を実装してください。
Servlet3.0以降の規約である非同期処理を利用したアプリケーションを作成しないでください。
jakarta.servlet.http.HttpSessionはWebアプリケーションのリクエストを処理するスレッドでのみ使用してください。Webアプリケーションが作成するスレッド(Jakarta Concurrencyが提供する並行処理リソース)では使用しないでください。
セッション属性に格納するオブジェクトはjava.io.Serializableインターフェイスを実装している(オブジェクト直列化可能である)必要があります。
この条件を満たさずにセッションレプリケーション機能を利用した場合、setAttributeを行ったときにjava.lang.IllegalArgumentExceptionが発生します。
セッション属性に格納するオブジェクトが保持する直列化可能でないインスタンス変数には、transient修飾子を宣言してください(バックアップ、リカバリーの対象外となります)。
OSおよびプロセス(Java VM)固有の運用資産を表すオブジェクトをセッションに格納した場合、動作の保証はできません。例えば、Threadクラスや入出力に関するクラス(InputStreamクラスやWriterクラスなどを継承したクラス)、CORBAやEJBのクライアント(スタブ、org.omg.CORBA.ORBやjavax.naming.Contextなど、およびこれに類するオブジェクトへの参照を保持するクラス)などはJava VMに固有の運用資産です。ユーザー定義オブジェクトを開発する場合には、このようなクラスを継承したり、このようなクラスへの参照を保持したりしないようにしてください。
セッション属性には、アプリケーションのリクエストを復元するために必要な情報をすべて格納する必要があります。
セッションのリカバリー処理ではセッション属性に格納された情報だけが復元され、セッションとは別のオブジェクトやクラスに格納した情報は復元されません。そのため、アプリケーションのリクエスト処理がセッション属性以外の動的情報に依存している場合にセッションのリカバリー処理をしても、リカバリー先のWebコンテナでアプリケーションがリクエストを正しく処理できないことがあります。
セッション属性に格納するオブジェクトクラスを変更し、かつ変更前にバックアップされたセッションを継続して使用する場合、「セッション属性に格納するオブジェクトクラスを変更する方法」に示す対応方法に従ってオブジェクトクラスを作成、または修正する必要があります。
この条件を満たさない場合、クラス修正前に保存されたオブジェクトをクラス修正後に復元させようとするとjava.io.InvalidClassExceptionがログ出力され、アプリケーションのリクエストは新規セッションとして処理されます。
注意
セッション属性に格納するオブジェクトのサイズが大きくなればなるほど、実行速度が遅くなります。
セッション属性に格納するオブジェクトクラスを変更する方法
セッション属性に格納するオブジェクトクラスを変更する場合、以下の2つの方法があります。
オブジェクトクラスの作成時に、将来の修正に備えておく方法
オブジェクトクラスの作成時に、修正に対する備えをしていなかった場合の変更方法
オブジェクトクラスの作成時に、将来の修正に備えておく方法
オブジェクトクラスの作成時に将来属性の変更があることを見越し、かつ修正前に格納した情報を修正後も使用したい場合、以下の対応が必要です。
オブジェクトクラスの作成時にserialVersionUIDをクラス変数として宣言し、任意の値(long整数)を設定しておきます。
修正前のオブジェクトクラス例
package com.fujitsu.appsrv.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.appsrv.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.appsrv.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.appsrv.sample.Company ←クラス名 com.fujitsu.appsrv.sample.Company: static final long serialVersionUID = 7242562793746307240L; ←serialVersionUIDが通知されます。 >
修正後のクラスに取得したserialVersionUIDをクラス変数として設定します。
修正後のオブジェクトクラス例
package com.fujitsu.appsrv.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仕様のドキュメントを参照してください。