intra-mart Accel Platform アクセスコンテキスト 拡張プログラミングガイド 第2版 2015-12-01

3.3. アクセスコンテキストの切替機能の実装例

この章では、アクセスコンテキストを切り替える方法を説明します。
前章「アクセスコンテキストのキャッシュ機能の実装例 」で作成したアクセスコンテキストの切替処理を行うことによって、アクセスコンテキストの内容を変更します。
ここでは、「個人設定」が変更された場合にアクセスコンテキストを切り替えます。
切替処理についての詳細は、「 アクセスコンテキスト仕様書 」-「 切替 」を参照してください。

3.3.1. 機能定義と作業の流れ

この章で作成するアクセスコンテキストの切替処理の要件は、以下の通りです。
  • 「個人設定」の「ロケール」が変更されたタイミングで、コンテキストの保持内容を個人設定が反映された値に変更する。
アクセスコンテキストを切り替えるための作業手順は、以下の通りです。
順序 作業内容 解説
1 コンテキストデコレータクラスを用意する。 コンテキストデコレータの作成
2 アクセスコンテキスト設定を追加する。 アクセスコンテキスト設定の追加
3 アクセスコンテキストの動作を確認する。 アクセスコンテキストの動作確認

コラム

ここで説明する切替機能は、コンテキストスイッチを対象としています。
コンテキストスタックの実装の流れも、コンテキストスイッチと同じように行います。
アクセスコンテキスト仕様書 」-「 コンテキストスタック 」を参照して実装してください。

3.3.2. コンテキストデコレータの作成

コンテキストの切替に対応するコンテキストデコレータクラスを作成します。
クラスを作成する場合は、以下のクラスを継承してください。
jp.co.intra_mart.foundation.context.core.ContextDecoratorSupport
ContextDecoratorSupport クラスを継承することで、decorate メソッドの実装が必須となります。
完全修飾子(FQCN) sample.SimpleUserContextDecorator

package sample;

import java.util.Date;
import java.util.Locale;

import jp.co.intra_mart.common.platform.log.Logger;
import jp.co.intra_mart.foundation.context.Contexts;
import jp.co.intra_mart.foundation.context.core.ContextDecoratorSupport;
import jp.co.intra_mart.foundation.context.core.Resource;
import jp.co.intra_mart.foundation.context.model.AccountContext;
import jp.co.intra_mart.foundation.context.model.Context;
import jp.co.intra_mart.foundation.exception.BizApiException;
import jp.co.intra_mart.foundation.i18n.datetime.DateTime;
import jp.co.intra_mart.foundation.i18n.timezone.SystemTimeZone;
import jp.co.intra_mart.foundation.master.user.UserManager;
import jp.co.intra_mart.foundation.master.user.model.User;
import jp.co.intra_mart.foundation.master.user.model.UserBizKey;

public class SimpleUserContextDecorator extends ContextDecoratorSupport {

    private static final Logger LOGGER = Logger.getLogger(SimpleUserContextDecorator.class);

    /**
     * アクセスコンテキストの内容を切り替えて、新しいアクセスコンテキストのインスタンスを返却します。
     * @param context 拡張元アクセスコンテキスト
     * @param resource 環境情報
     * @return 切替後のアクセスコンテキストのインスタンス
     */
    @Override
    public Context decorate(final Context context, final Resource resource) {
        try {
            // ここに到達したことをログに出力
            LOGGER.info("SimpleUserContext decorated.");

            // アクセスコンテキストのインスタンスを生成して返却
            return createNewContext();
        } catch (final BizApiException e) {
            throw new RuntimeException(e);
        }
    }

    private SimpleUserContext createNewContext() throws BizApiException {
        // ログインユーザの情報をアカウントコンテキストから取得
        final AccountContext accountContext = Contexts.get(AccountContext.class);
        final String userCd = accountContext.getUserCd();
        final Locale locale = accountContext.getLocale();

        // ログインユーザの情報 (ユーザコード、ロケール) をキーとしてユーザ情報を取得
        final User user = getUser(userCd, locale);
        if (user == null) {
            // ユーザ情報が取得できないときは、空のアクセスコンテキストのインスタンスを返却
            return new SimpleUserContext();
        }

        // アクセスコンテキストのインスタンスに、ユーザ情報を設定
        final SimpleUserContext context = new SimpleUserContext();
        context.setUserName(user.getUserName());
        context.setMailAddress(user.getEmailAddress1());

        // アクセスコンテキストのインスタンスを返却
        return context;
    }

    private Date getBaseTime() {
        // ログインユーザのタイムゾーンで現在日付を取得
        final DateTime userDate = new DateTime(Contexts.get(AccountContext.class).getTimeZone());
        return new DateTime(SystemTimeZone.getDefaultTimeZone(), userDate.getYear(), userDate.getMonthOfYear(), userDate.getDayOfMonth()).getDate();
    }

    private User getUser(final String userCd, final Locale locale) throws BizApiException {
        // IM共通マスタの検索条件を設定
        final UserManager manager = new UserManager();
        final UserBizKey bizKey = new UserBizKey();
        bizKey.setUserCd(userCd);

        // IM共通マスタからユーザ情報を検索
        final User user = manager.getUser(bizKey, getBaseTime(), locale, false);
        return user;
    }

}
実装が必要なメソッドとその説明は、以下の通りです。
  • decorate メソッド

    自身のコンテキストデコレータがサポートするアクセスコンテキストのインスタンスを返却してください。
    切替処理では通常、切替元のアクセスコンテキストを参照して、情報を引き継ぎます。
    そのような場合は、引数の「拡張元アクセスコンテキスト(context)」を参照してください。
    今回の例では、SimpleUserContext クラスのインスタンスを作成して、各プロパティ値を設定後、返却します。

    コラム

    ここでは、引数 Resource のリソース情報プロパティは使用していません。
    切替処理によっては、プログラムの引数としてリソース情報が設定されているため、リソース情報を参照して処理をします。

3.3.3. アクセスコンテキスト設定の追加

アクセスコンテキストと、切替に対応したコンテキストデコレータを紐付ける設定を、「アクセスコンテキスト設定」に追加します。
設定ファイルに、以下のような形式で記述してください。
前章の「アクセスコンテキスト設定の追加 」で作成した設定ファイルに、切替に関する設定を追加します。
パス WEB-INF/conf/context-config/{任意のファイル名}.xml

<?xml version="1.0"?>
<context-config
    xmlns="http://intra-mart.co.jp/foundation/context/context-config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://intra-mart.co.jp/foundation/context/context-config ../../schema/context-config.xsd">

  <context
      name="sample.SimpleUserContext"
      depends="jp.co.intra_mart.foundation.context.model.AccountContext">

    <builder target="platform.request">
      <builder-class>sample.CachingSimpleUserContextBuilder</builder-class>
      <init-param>
        <param-key>cache-policy</param-key>
        <param-value>session-user-daily</param-value>
      </init-param>
      <init-param>
        <param-key>default-switch-resource-id</param-key>
        <param-value>sample.switch.default</param-value>
      </init-param>
    </builder>

    <builder target="sample.switch.default">
      <builder-class>jp.co.intra_mart.system.context.standard.StandardSwitchableContextBuilder</builder-class>
      <decorator>
        <decorator-class>sample.SimpleUserContextDecorator</decorator-class>
      </decorator>
    </builder>

  </context>

</context-config>
今回作成する切替処理は個人設定が変更された場合を想定していますが、特定の処理を対象とした場合、それ以外の切替処理に対応できません。
そのため、デフォルトコンテキストビルダとして定義します。
デフォルトコンテキストビルダについては、「 アクセスコンテキスト仕様書 」-「 デフォルトコンテキストビルダの設定 」を参照してください。
設定が必要なタグとその説明は、以下の通りです。
  • builder タグ

    target 属性に、呼び出すタイミングを示すリソースIDを指定してください。
    今回の例では、デフォルト用に新しいリソースID sample.switch.default を指定します。
    デフォルトコンテキストビルダとするため、リソースID platform.request の初期パラメータに、default-switch-resource-id の設定を追加します。
    builder-class タグ内に、コンテキストビルダクラスの完全修飾子(FQCN)を指定します。
    今回の例では、jp.co.intra_mart.system.context.standard.StandardSwitchableContextBuilder を指定します。
  • decorator タグ

    decorator-class タグ内に、コンテキストデコレータクラスの完全修飾子(FQCN)を指定してください。
    今回の例では sample.SimpleUserContextDecorator を指定します。

コラム

アクセスコンテキストの設定 」において、SimpleUserContextAccountContext に依存する設定を行っているため、「個人設定」が変更された際に、以下の順序でコンテキストの切替が行われます。
  1. AccountContext の切替。
  2. SimpleUserContext の切替。
そのため、SimpleUserContext で取得する AccountContext の内容は、変更後の個人設定が反映された状態で取得できます。

3.3.4. アクセスコンテキストの動作確認

作成したアクセスコンテキストの切替が動作しているか、以下の手順で確認します。
  1. サーバ起動時のログを確認します。

    アクセスコンテキスト、コンテキストビルダ、コンテキストデコレータ、および、設定ファイルが正しくアプリケーションサーバに配置されている場合、サーバ起動時に以下のログが出力されます。
    [I.IWP.CONTEXT.MANAGER.10001] Used context. sample.SimpleUserContext
    
    実際の出力例
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcs9     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. jp.co.intra_mart.foundation.context.model.ClientContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcsa     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. jp.co.intra_mart.foundation.context.model.AccountContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcsb     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. jp.co.intra_mart.foundation.job_scheduler.JobSchedulerContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcsc     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. jp.co.intra_mart.foundation.user_context.model.UserContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcsd     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. jp.co.intra_mart.foundation.authz.context.AuthzSubjectContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.context.manager.impl.MultipleXmlContextConfiguration     5ib6n4szdhcse     -  [I.IWP.CONTEXT.MANAGER.10001] Used context. sample.SimpleUserContext
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.service.impl.ServiceControllerImpl     5ib6n4szdi8sf     -  [I.IWP.SERVICE.00009]   Initialize service "server.service.queue.management".
    [2014-05-01 12:00:00.000]  [resin-11]  INFO  jp.co.intra_mart.system.service.impl.ServiceControllerImpl     5ib6n4szdi8sg     -  [I.IWP.SERVICE.00009]   Initialize service "server.service.task.management".
    
  2. ログイン時に、ログ、および、アクセスコンテキストの保持内容を確認します。

    任意のユーザ(例:サンプルユーザの青柳)でログイン後、CachingSimpleUserContextBuilder#create() メソッドの冒頭で実装しているログが以下のように出力されますので、システムログを確認してください。
    ログが出力されていれば、アクセスコンテキストの作成処理が正常に行われています。
    [] SimpleUserContext created.
    
    実際の出力例
    [2014-05-01 12:00:00.000]  [resin-port-8080-11] INFO  sample.CachingSimpleUserContextBuilder    5ib6n4umb3mos     -  [] SimpleUserContext created.
    
    アクセスコンテキストの保持内容を確認するため、以下の URL にアクセスしてください。

    http://<HOST>:<PORT>/<CONTEXT_PATH>/sample/context/context_view.jsp

    「Context: sample.SimpleUserContext」カテゴリが表示され、各プロパティに想定通りの値が表示されていれば成功です。
    ../../_images/make_context_3.png
    図 アクセスコンテキストの内容
  3. 「個人設定」を変更して、アクセスコンテキストの保持内容が変更されることを確認します。

    「個人設定」の「ロケール」を変更後にページを再表示すると、コンテキストの保持内容が更新されていることが確認できます。
    ../../_images/make_context_4.png
    図 「ロケール」変更後の内容
    「個人設定」を変更したタイミングで、SimpleUserContextDecorator#decorate() メソッドの冒頭で実装しているログが以下のように出力されますので、システムログを確認してください。
    ログが出力されていれば、アクセスコンテキストの切替処理が正常に行われています。
    [] SimpleUserContext decorated.
    
    実際の出力例
    [2014-05-01 12:00:00.000]  [resin-port-8080-12] INFO  sample.SimpleUserContextDecorator   default  5ib6n4umivfje  5ib6n4umisij2r2   -  [] SimpleUserContext decorated.