2024年10月18日金曜日

Oracle APEXのセッション・クローニングの機能を確認する

以前よりOracle APEXでは、セッション・クローニングという機能を提供しています。

APEXのアプリケーションを使用してるユーザーが、ブラウザで複数のタブ、またはウィンドウを同じAPEXセッションで開いていると、データの不整合が発生することがあります。このような事態を防ぐために、新しくタブ、または、ウィンドウを開く際に新規にAPEXセッションを作成し、元のセッションのセッション・ステートを新しく開始したセッションにコピーできます。

セッション・クローニングはインスタンス単位で有効化/無効化します。有効にする場合は、インスタンス・パラメータのCLONE_SESSION_ENABLEDYを設定します。セッション・クローニングはデフォルトで有効になっています。

説明だけでは分かりにくいので、APEXのセッション・クローニングを実装したAPEXアプリケーションを作成し、動作を確認します。

使用するAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/session-cloning-test.zip

アプリケーションのホーム・ページは、以下のようになっています。


一番上の選択リストより、セッション・クローニングの有効(Enable)または無効(Disable)を選択します。


その下にあるページ・アイテムにリダイレクト先のURLを表示しています。セッション・クローニングが有効なURLは、引数requestに文字列APEX_CLONE_SESSIONが渡されています。

/ords/r/apexdev/session-cloning-test/target?p2_org_app_session=114548193799634&request=APEX_CLONE_SESSION&session=114548193799634&cs=1blo0K2KZmnoQijOhBNokxvbhjROI2_SQxHETuH3NLhCyDwsEvRdhvQN1gbyEFSl4638mIAbCgWpnTH_7B8xwDA

ボタンRedirectをクリックすると、新規のタブを上記のURLで開きます。

CloneDisableを指定してRedirectをクリックします。


新しいタブにTargetのページが開きます。このとき、呼び出し元のセッションID(Original Session ID)と新しいタブでのセッションID(Session ID)は、同じ値になります。


CloneEnableに設定しボタンRedirectをクリックすると、呼び出し元のセッションID(Original Session ID)と新しいタブでのセッションID(Session ID)は、異なる値になります。つまり、新規にセッションが作成されています


セッション・クローニングを行わなかったときと行わなかったときの、動作の違いを説明する前に、テストに使っているAPEXアプリケーションの実装について説明します。

セッション・クローニングのEnable/Disableの選択は、ページ・アイテムP1_CLONEとして作成しています。

設定選択時のページ・アクション値のリダイレクトと設定を選択し、Enable/Disableの選択を切り替えたときにページを再ロードしています。

LOVNULL値の表示オンNULL表示値Disableを設定しています。


LOVタイプ静的値を選び、静的値表示値Enable戻り値APEX_CLONE_SESSIONを設定しています。


結果としてページ・アイテムP1_CLONEの値は、Disableを選択すると空白Enableを選択するとAPEX_CLONE_SESSIONになります。

ページ・アイテムP1_URLに、新しいタブのリダイレクト先となるURLを設定します。この値は、ページ・アイテムの計算によって生成します。

計算PL/SQLファンクション本体として、以下を記述します。APEX_PAGE.GET_URLの引数p_requestにページ・アイテムP1_CLONEの値を渡すことにより、セッション・クローニングを有効にするか無効にするかを決めています。
declare
    l_url varchar2(400);
begin
    return apex_page.get_url(
        p_page => 'target'
        ,p_items => 'P2_ORG_APP_SESSION'
        ,p_values => :APP_SESSION
        ,p_request => :P1_CLONE
    );
    /*
        return apex_util.prepare_url(
        apex_string.format('f?p=%s:target:%s:%s:::P2_ORG_APP_SESSION:%s:', :APP_ID, :APP_SESSION, :P1_CLONE, :APP_SESSION )
    );
    */
end;
P1_URLに設定されたURLを新規のタブで開く処理は、ボタンREDIRECTに設定した動的アクションとして実装しています。

ボタンREDIRECTをクリックしたときに、apex.navitation.openInNewWindowを実行しています。

apex.navigation.openInNewWindow( apex.items.P1_URL.value );


セッション・クローニングの効果を確認するために、ページ・アイテムP1_COUNTを作成しています。

ソースタイプアイテムアイテムとしてG_COUNTを設定し、使用セッション・ステートの既存の値を常に置換を選択しています。

結果としてページ・アイテムP1_COUNTがページに表示される際には、常にアプリケーション・アイテムG_COUNTに保存された値が表示されます。


アイテムG_COUNTは、共有コンポーネントアプリケーション・アイテムとして作成しています。


ボタンINCREMENT動作アクションページの送信としています。


ボタンINCREMENTをクリックしたときに、アプリケーション・アイテムG_COUNTの値に1を加えています。

:G_COUNT := coalesce(:G_COUNT, 0) + 1;

アプリケーション・アイテムG_COUNTの値は、セッション・ステートとして保存されています。


ボタンREDIRECTをクリックしたときに開かれるページには、呼び出し元のセッションIDを表示するページ・アイテムP2_ORG_APP_SESSIONと、現行のセッションIDを表示するP2_APP_SESSIONを作成しています。

P2_APP_SESSIONソースタイプ静的値静的値として&APP_SESSION.を設定しています。使用セッション・ステートの既存の値を常に置換を選択することにより、ページ・アイテムP2_APP_SESSIONを表示する際には常に、セッション・ステートに保存されたP2_APP_SESSIONの値よりも現在のセッションIDである&APP_SESSION.を優先して表示するようにしています。


ボタンINCREMENTをクリックすると、ホーム・ページのボタンINCREMENTと同様にアプリケーション・アイテムG_COUNTに1を加えます。

ページ・アイテムP2_COUNTソースは、P1_COUNTと同様にアイテムG_COUNTを設定しています。


セッション・クローニングを確認するAPEXアプリケーションの説明は以上になります。

実際にセッション・クローニングが無効のときと有効のときでの、動作の違いを確認します。

アプリケーションにサインインし、何回かボタンIncrementをクリックします。

以下のスクリーンショットではCount4になっています。


CloneDisableにしてボタンRedirectをクリックすると、新たなタブが開きます。

Count4になっています。


ボタンIncrementをクリックします。Countは4,5,6,7と増えていきます。

以下のスクリーンショットではCount7になっています。


ホーム・ページのタブに戻ります。

Count4です。


ホーム・ページのボタンIncrementをクリックします。

Count4から8に変わります。

これはホーム・ページとTargetのページは同じセッションで動作していて、アプリケーション・アイテムG_COUNTの値(セッション・ステート)を共有しているためです。


Targetのタブに移動すると、Countは7のままです。ここでボタンIncrementをクリックすると、Count9になります。

セッション・クローニングを無効にして新たにタブやウィンドウを開くと、セッション・ステートが共有されるため、このような動作になります。


次にCloneEnableにして、動作を確認します。

先ほどと同様にCount4まで上げ、CloneEnableを選択してボタンRedirectをクリックします。


Targetが開きます。Countはホーム・ページの値と同じく4になっていますが、これは元のセッション・ステートを参照しているのではなく、新たに作成したセッションにコピーされたセッション・ステートを参照しています。


ボタンIncrementを複数回クリックすると、Countの表示は4,5,6,7と上がっていきます。


ホーム・ページのタブに戻ります。Countの表示は変わらずです。


ホーム・ページのボタンIncrementを複数回クリックすると、Countは5,6,7,8と増加していきます。Targetのページで変更した値の影響は受けません。これは、ホーム・ページとTargetのページでは、別のセッション・ステートを参照しているためです。


セッション・クローニングの動作の説明は以上になります。