intra-mart Accel Platform アクセスコンテキスト仕様書 第7版 2018-08-01

4.2. アクセスコンテキストフレームワーク

ここでは、アクセスコンテキストの機能を実現するための基本的な機構を説明します。

4.2.1. 概要

アクセスコンテキストは、ライフサイクルの操作によりアクセスコンテキストを生成することで利用可能な状態となります。
ライフサイクルの操作の種類は以下の通りです。
  • ライフサイクルの開始
  • ライフサイクルの切替
  • ライフサイクルの終了
ここでは、アクセスコンテキストの仕組みについて、以下の順に説明します。
  1. ライフサイクルの開始フロー について説明します。

    ライフサイクルの切替については、「 切替 」で説明します。
    また、ライフサイクルの終了処理は、アクセスコンテキストの破棄のみが行われるため、ここでは説明を省略します。
  2. ライフサイクルの操作時に利用される、以下の要素について説明します。


4.2.2. ライフサイクルの開始フロー

ライフサイクルの開始により、アクセスコンテキストの生成処理が実行されます。
アクセスコンテキストの生成処理は、定義されたアクセスコンテキストごとにコンテキストビルダを呼び出して実行されます。
コンテキストビルダについては、「 コンテキストビルダ 」を参照してください。
アクセスコンテキストの処理は、以下の順に実行されます。
  1. 開始処理の呼び出し( Lifecycle#begin()
  2. アクセスコンテキスト一覧取得
  3. アクセスコンテキストごとに以下の処理を実行
    1. コンテキストビルダの選出
    2. コンテキストビルダの生成処理実行
    3. アクセスコンテキスト保存先への格納

4.2.3. 環境情報(Resource)

アクセスコンテキストの生成は、「環境情報(Resource)」を基に実行されます。
環境情報とは、実行環境と対象処理を表すオブジェクトで、環境情報を特定するプロパティとして、リソースIDを保持します。
環境情報を表すクラスは、以下のクラスです。
jp.co.intra_mart.foundation.context.core.Resource
ライフサイクルの操作ごとに環境情報を生成して利用します。
環境情報には、対象のライフサイクル操作で必要な情報を設定して、ライフサイクルの操作を実行します。
また、以降で説明する「 コンテキストビルダ 」や「 コンテキストデコレータ 」では、実行時の引数に環境情報が設定されます。
それぞれのクラスでは、ライフサイクルの操作実行時に設定された環境情報を参照できます。

4.2.3.1. リソースID

リソースIDは、任意の文字列です。
処理を分類するために、以下のように「.(ドット)」区切りで定義されます。
例) platform.request : Web実行環境の開始処理を表すリソースID
platform で始まるリソースIDは、 intra-mart Accel Platform で提供するリソースIDです。
新しいリソースIDを定義する場合は、他のリソースIDと重複しないようにアプリケーション固有の文字列を含めて定義してください。
intra-mart Accel Platform で提供するリソースIDについては、「 リソースID一覧 」を参照してください。

4.2.3.2. その他の情報

環境情報は、リソースIDの他に以下の情報を持ち、コンテキストビルダにより参照されます。
  • リソース情報

    環境情報に付属する任意の情報です。
    コンテキストビルダに渡される引数として利用されます。
    Resource#getResource() / Resource#setResource() メソッドを利用して取得・設定を行います。
    ライフサイクルの操作実行者が設定する情報で、処理中は変更されません。
  • リソース属性

    環境情報の追加情報です。
    キーと値で任意の情報が設定されます。
    ライフサイクルの操作の実行状態を表す情報で、ライフサイクルの操作処理プログラムの中で設定する情報です。
    例えば、アカウントコンテキスト生成中にアカウントに関する追加情報を設定し、ユーザコンテキストの生成時にその情報を参照する、といった使い方を想定しています。
    リソース属性のキーは任意の文字列です。
    ただし、キーの衝突を避けるため、利用する処理クラスの完全修飾子(FQCN)をキーとして利用してください。

    例) jp.co.intra_mart.system.context.impl.cache.SessionContextCachePolicy.session.create

    Resource#getAttribute() /Resource#setAttribute() メソッドを利用して取得・設定を行います。
環境情報は処理対象となる複数のアクセスコンテキストのコンテキストビルダで共有されます。
環境情報に設定する値は、複数のクラスで処理が可能な情報を設定するようにしてください。
詳しくは、「Resource クラスの APIドキュメント」を参照してください。

4.2.3.3. Web用環境情報

Web実行環境の環境情報は、以下のクラスで定義されます。
jp.co.intra_mart.foundation.context.web.HttpResource
このクラスを利用すれば、HTTPリクエスト(HttpServletRequest)およびHTTPレスポンス(HttpServletResponse)オブジェクトにアクセスが可能です。
Web実行環境用の処理クラス内で、以下のように Resource クラスをキャストして利用してください。
HttpResource httpResource = HttpResource.class.cast(resource);

4.2.4. アクセスコンテキストモデル

ここでは、アクセスコンテキストの実装クラスについて説明します。
アクセスコンテキストを表す実装クラス(または、インタフェース)をアクセスコンテキストモデルと呼びます。
アクセスコンテキストモデルは、以下の要素で定義されます。
  • コンテキスト種別

    アクセスコンテキストを区別する情報
  • プロパティ

    それぞれのアクセスコンテキストが保持する情報
また、アクセスコンテキストは便宜上、それぞれ名称(アクセスコンテキスト名)を持っています。
説明上は、アクセスコンテキスト名を利用します。

4.2.4.1. コンテキスト種別

アクセスコンテキストモデルは、コンテキスト種別を保持します。
コンテキスト種別は個々のアクセスコンテキストを区別する情報で、アクセスコンテキストのIDとして利用されます。
1つの実行環境には、あらかじめ定義されたコンテキスト種別のアクセスコンテキストが1つずつ存在します。
コンテキスト種別は、アクセスコンテキストモデルの完全修飾クラス名(FQCN)の文字列で表されます。
例)アカウントコンテキストのコンテキスト種別
jp.co.intra_mart.foundation.context.model.AccountContext
標準アクセスコンテキストのコンテキスト種別は、以下の通りです。
表 標準アクセスコンテキストのコンテキスト種別一覧
アクセスコンテキスト名 コンテキスト種別
アカウントコンテキスト jp.co.intra_mart.foundation.context.model.AccountContext
クライアントコンテキスト jp.co.intra_mart.foundation.context.model.ClientContext
ユーザコンテキスト jp.co.intra_mart.foundation.user_context.model.UserContext
認可サブジェクトコンテキスト jp.co.intra_mart.foundation.authz.context.AuthzSubjectContext
ジョブスケジューラコンテキスト jp.co.intra_mart.foundation.job_scheduler.JobSchedulerContext

4.2.4.2. アクセスコンテキストモデルの定義

アクセスコンテキストを定義するには、以下のインタフェースを実装します。
jp.co.intra_mart.foundation.context.model.Context
getType() メソッドを実装して、コンテキスト種別の定義を行います。

コラム

コンテキスト種別は、通常は自分自身の java.lang.Class オブジェクトを設定します。
実行環境ごとに複数の実装クラスを作成する場合は、共通のインタフェースを作成して、コンテキスト種別としてください。
アクセスコンテキストのモデルクラスは、プロパティのみを持つシンプルなオブジェクトとなるように実装します。
複雑な振る舞い(メソッド)を持つことは、共有情報の参照先としてのアクセスコンテキストの役割に反します。
アクセスコンテキストが提供する情報は、参照するための情報です。
そのため、アクセスコンテキストモデルは、 Setter のみ定義した読み取り専用のプロパティをもつインタフェースとして定義することを推奨します。
これにより、ユーザプログラムによるプロパティの変更を防ぐことができます。
アクセスコンテキストはキャッシュに格納するなどシリアライズが必要となるため、java.io.Serializable インタフェースを継承しています。
シリアライズ可能なオブジェクトとなるように実装してください。

4.2.5. コンテキストビルダ

コンテキストビルダとは、アクセスコンテキストを生成するための処理クラスです。
以下のライフサイクル操作時に、新しいアクセスコンテキストの生成を行います。
  • ライフサイクルの開始
  • ライフサイクルの切替
コンテキストビルダの定義は、設定ファイルに記述されます。
対象となるアクセスコンテキストごとに、必要なライフサイクル操作の数だけ定義されます。
コンテキストビルダを利用するための設定方法については、「 コンテキストビルダの設定 」を参照してください。
ライフサイクルの操作時に、リソースIDを基に実行対象のコンテキストビルダが選出され、実行されます。
コンテキストビルダの選出は以下の順に行われます。
  • ライフサイクルの開始時

    1. 設定ファイルの「ターゲット」と実行時に指定された「リソースID」が一致するコンテキストビルダ
  • ライフサイクルの切替時

    1. 設定ファイルの「ターゲット」と実行時に指定された「リソースID」が一致するコンテキストビルダ
    2. デフォルトコンテキストビルダ
デフォルトコンテキストビルダについては、「 デフォルトコンテキストビルダの設定 」を参照してください。

4.2.5.1. コンテキストビルダのインタフェース

コンテキストビルダは、以下のインタフェースを実装します。
jp.co.intra_mart.foundation.context.core.ContextBuilder
build() メソッドを実装して、アクセスコンテキストの生成を行います。
build() メソッドでは、ライフサイクル操作の実行時に渡された環境情報を参照することができます。

実装例

public class SampleContextBuilder implements ContextBuilder {

    @Override
    public Context build(final Resource resource) {
        // 環境情報を参照して、新しいアクセスコンテキストを生成する。
        final SampleInfo sampleInfo = SampleInfo.class.cast(resource.getResource());
        final SampleContext newContext = new SampleContext();
        newContext.setFoo(sampleInfo.getFoo());
        return newContext;
    }
}
build() メソッドの引数 resource には、実行時の「 環境情報(Resource) 」が設定されます。
リソース情報やリソース属性を利用して、コンテキストの生成を行います。

4.2.5.2. コンテキストビルダの抽象クラス

ContextBuilder インタフェースを実装する場合、 build() メソッド以外にも、以下のメソッドの実装が必要です。
  • init() : 設定ファイルの情報を参照して初期化を行います。
  • getBuilderInfo() : 設定ファイルの情報を返却します。
  • getContextType() : 生成対象のコンテキスト種別を返却します。
これらのメソッドは、設定ファイルの情報を参照する機能であり、通常はコンテキストビルダごとに処理を変更する必要がありません。
そのため、新しくコンテキストビルダを作成する場合は、これらのメソッドをあらかじめ実装した、以下の基底クラスが利用可能です。
jp.co.intra_mart.foundation.context.core.ContextBuilderSupport
このクラスを継承してコンテキストビルダを作成した場合は、create() メソッドを実装してください。

実装例

public class SampleContextBuilder extends ContextBuilderSupport {

    @Override
    protected Context create(final Resource resource) {
        // 環境情報を参照して、新しいアクセスコンテキストを生成する。
        final SampleInfo sampleInfo = SampleInfo.class.cast(resource.getResource());
        final SampleContext newContext = new SampleContext();
        newContext.setFoo(sampleInfo.getFoo());
        return newContext;
    }
}

4.2.5.3. キャッシュサポート

Web実行環境では、アクセスコンテキストのキャッシュが利用されます。
Web実行環境用のコンテキストビルダを実装するためには、以下の基底クラスを継承して実装してください。
キャッシュに関する処理は基底クラスが行うため、実装が必要なメソッドはありません。
jp.co.intra_mart.system.context.core.cache.CachingContextBuilderSupport

実装例

import jp.co.intra_mart.foundation.context.core.Resource;
import jp.co.intra_mart.foundation.context.model.Context;
import jp.co.intra_mart.system.context.core.cache.CachingContextBuilderSupport;
import test.SampleContext;
import test.SampleInfo;

public class SampleCachingContextBuilder extends CachingContextBuilderSupport {

    @Override
    protected Context create(final Resource resource) {
        // 環境情報を参照して、新しいアクセスコンテキストを生成する。
        // キャッシュに関する処理は、CachingContextBuilderSupport が行うため、特に必要な対応はありません。
        final SampleInfo sampleInfo = SampleInfo.class.cast(resource.getResource());
        final SampleContext newContext = new SampleContext();
        newContext.setFoo(sampleInfo.getFoo());
        return newContext;
    }
}
キャッシュ処理の詳細については、「 キャッシュ 」を参照してください。

4.2.6. コンテキストデコレータ

コンテキストデコレータは、コンテキストビルダで作成したアクセスコンテキストをさらに拡張する場合に利用されます。
モジュールの追加により、アクセスコンテキストの生成処理をカスタマイズしたい場合などに利用されます。
コンテキストデコレータの実行は、前述した基底クラス ContextBuilderSupport が行います。
そのため、コンテキストデコレータを利用するためには、 ContextBuilderSupport を継承したコンテキストビルダを作成する必要があります。
コンテキストデコレータを利用するための設定については、「 コンテキストデコレータの設定 」を参照してください。

4.2.6.1. コンテキストデコレータのインタフェース

コンテキストデコレータは、以下のインタフェースを実装します。
jp.co.intra_mart.foundation.context.core.ContextDecorator
decorate() メソッドを実装して、拡張元のアクセスコンテキストを基にアクセスコンテキストの生成を行います。
decorate() メソッドでは、ライフサイクル操作の実行時に渡された環境情報を参照することができます。

実装例

public class SampleContextDecorator implements ContextDecorator {

    @Override
    public Context decorate(final Context context final Resource resource) {
        // 拡張元アクセスコンテキストを参照して、新しいアクセスコンテキストを生成する。
        final SampleContext prevContext = SampleContext.class.cast(context);
        final SampleContext newContext = new SampleContext();
        newContext.setFoo(prevContext.getFoo());
        return newContext;
    }
}
decorate() メソッドの引数 resource には、実行時の「 環境情報(Resource) 」が設定されます。
リソース情報やリソース属性を利用して、コンテキストの生成を行います。

4.2.6.2. コンテキストデコレータの抽象クラス

ContextDecorator インタフェースを実装する場合、 decorate() メソッド以外にも、以下のメソッドの実装が必要です。
  • init() : 設定ファイルの情報を参照して初期化を行います。
  • getDecoratorInfo() : 設定ファイルの情報を返却します。
これらのメソッドは、設定ファイルの情報を参照する機能であり、通常はコンテキストデコレータごとに処理を変更する必要がありません。
そのため、新しくコンテキストデコレータを作成する場合は、これらのメソッドをあらかじめ実装した、以下の基底クラスが利用可能です。
jp.co.intra_mart.foundation.context.core.ContextDecoratorSupport

実装例

public class SampleContextDecorator extends ContextDecoratorSupport {

    @Override
    public Context decorate(final Context context final Resource resource) {
        // 拡張元アクセスコンテキストを参照して、新しいアクセスコンテキストを生成する。
        final SampleContext prevContext = SampleContext.class.cast(context);
        final SampleContext newContext = new SampleContext();
        newContext.setFoo(prevContext.getFoo());
        return newContext;
    }
}

4.2.7. ライフサイクルの実行

ライフサイクルの開始・終了処理を実行するためには、 Lifecycle API を利用します。
  • Lifecycle#begin(Resource) : ライフサイクルの開始
  • Lifecycle#end() : ライフサイクルの終了
ただし、標準の実行環境のライフサイクルの開始・終了処理はあらかじめ実装済みのため、開発者がこれらのメソッドを利用する必要はありません。
Lifecycle API の利用方法は、「 Lifecycle クラスの APIドキュメント 」を参照してください。