ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Portal開発者ガイド
11gリリース1(11.1.1)
B61384-01
  ドキュメント・ライブラリ
ライブラリ
製品リスト
製品
目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

16 コンテンツ管理イベント・フレームワークの使用

この章では、Oracle Portalコンテンツ管理イベント・フレームワーク(CMEF)について説明します。この章の内容は、次のとおりです。

16.1 コンテンツ管理イベント・フレームワークの概要

CMEFを使用して、事前定義済ポータルのイベントに対しプログラム的なフックを追加することによって、Oracle Portalのコンテンツ管理機能を拡張できます。フレームワークは、これらのイベントをOracleデータベースのキューに公開します。これにより、サード・パーティのプログラムがこれらのイベントをサブスクライブし、APIを使用してポータルを拡張できるようになります。このようにして、ポータル内のページおよびアイテム関連のイベントを使用して、1つ以上の外部アプリケーション内のアクションをトリガーできます。

16.2 コンテンツ管理イベント・フレームワークの動作

CMEFは、Oracle Streamsアドバンスト・キューイング(AQ)テクノロジを採用しています。Oracle Streams AQはOracleデータベース・コンポーネントであり、業界標準に準拠した豊富な機能セットを持つメッセージ・キュー・システムを提供します。Oracle Streams AQには、次の機能が用意されています。

詳細はOTN

詳細は、Oracle Technology Network(OTN)の「Oracle Streams Advanced Queuing」を参照してください。

http://www.oracle.com/technology/products/aq

Oracle Portalユーザー・インタフェース、Web-based Distributed Authoring and Versioning(WebDAV)プロトコルまたはPL/SQL APIを介したポータル内でのアクションにより、CMEFイベントがトリガーされます。このイベントにより、Oracle PortalはCMEFメッセージをキューに公開します。キューにあるメッセージを消費するサブスクライバを作成し、これらに基づいてアクションを実行できます。たとえば、ユーザーがポータル・ページにアイテムを追加したときに、その表示名が80文字以内であることを確認するサブスクライバを作成できます。サブスクライバは、イベントが発生したときに、または一定の時間間隔に基づいて、イベントを処理できます。

CMEFイベントには、ADD、UPDATEおよびDELETEの3つの主要タイプがあります。すべてのコンテンツ管理アクションは、これらのイベントのいずれかに分類されます。イベントには、複数の異なる状態があります。たとえば、ユーザーがページにアイテムを追加した場合、ADDイベントの状態には、アイテムが即座に使用可能であることを示すもの(PUBLISHED)や、後から使用可能になることを示すもの(NOT_PUBLISHED)があります。サブスクライバがこの情報を使用して目的のメッセージを取得する方法の詳細は、16.3項「コンテンツ管理イベント・フレームワークの使用」を参照してください。

CMEFによって公開されたイベントの使用には、次の5つの基本的なキューイング操作が含まれます。

キューイング操作を実行するには、DBMS_AQパッケージを使用します。

16.2.1 メッセージのエンキュー

CMEFは、AQメッセージ・プロパティを指定することにより、WWSBR_EVENT_Qキューにメッセージをエンキューします。このプロパティは、デキュー時にサブスクライバ・アプリケーションにより使用されます(表16-1)。

表16-1 CMEFによって設定されるAQメッセージ・プロパティ

メッセージ・プロパティ タイプ

PRIORITY

BINARY_INTEGER

1

DELAY

BINARY_INTEGER

NO_DELAY

EXPIRATION

BINARY_INTEGER

NEVER

CORRELATION

VARCHAR2(128)

NULL

RECIPIENT_LIST

AQ$_RECIPIENT_LIST_T

NULL

EXCEPTION_QUEUE

VARCHAR2(51)

WWSBR_EVENT_ERR_Q

ORIGINAL_MSGID

RAW(16)

NULL


WWSBR_EVENT_Qキューは、マルチコンシューマ・キューです。このキューにより、複数のサブスクライバがメッセージごとに複数のコピーを作成しないで1つのメッセージを消費できるようになります。キュー内のすべてのメッセージの優先順位は同じなので、このキューは先入れ先出し方式で動作します。

CMEFによってWWSBR_EVENT_Qキューにエンキューされる各メッセージには、ページIDやページ・グループIDなど、イベントが関連するポータル・オブジェクトに関する情報を含むペイロードが含まれます。サブスクライバは、このペイロード情報を使用して、ポータル・オブジェクトに対するアクションを実行できます。CMEFメッセージのペイロードのコンテンツの詳細は、16.3.6項「CMEFメッセージのペイロード」を参照してください。

CMEFは、即座に消費するためにメッセージをエンキューします。つまり、ポータルでアクションが発生すると同時にメッセージはWWSBR_EVENT_Qキューに格納されます。遅延はありません。CMEFによって作成されたメッセージには有効期限がありません。

16.2.2 サブスクライバおよびメッセージのデキュー

消費側であるサブスクライバには、CMEFによって作成されたメッセージを消費するために様々なメカニズムが用意されています。サブスクライバはメッセージが到着したときにメッセージを処理できるので、メッセージが到着するまで待機する必要があります。また、サブスクライバは、メッセージの到着時に通知を受けることもできます。これらの通知には、Oracle Call Interface(OCI)、コールバック・ファンクション、PL/SQLファンクションまたは電子メールがあります。

16.2.2.1 WWSBR_EVENT_Qキューへのサブスクライバの追加

CMEFによって作成されたメッセージをサブスクライバが消費できるようにするには、DBMS_AQADM.ADD_SUBSCRIBERプロシージャを使用して、WWSBR_EVENT_Qキューにサブスクライバを追加し、Portalスキーマ・ユーザーとしてログインする必要があります。

GRANT EXECUTE ON DBMS_AQADM TO <<PORTAL_SCHEMA>>;
GRANT Aq_administrator_role TO <<PORTAL_SCHEMA>>;

例16-1では、JAYサブスクライバをWWSBR_EVENT_Qキューに追加しています。

例16-1 WWSBR_EVENT_Qへのサブスクライバの追加

subscriber := sys.aq$_agent('JAY', null, null);
dbms_aqadm.add_subscriber(
  queue_name => 'portal.wwsbr_event_q',
  subscriber => subscriber
);

Oracle Streams AQは、マルチコンシューマ・キューごとに最大1024のサブスクライバをサポートしているので、WWSBR_EVENT_Qキューには最大1024のサブスクライバを追加できます。このキューにサブスクライバとして追加されるすべてのコンシューマでは、AQ$_AGENTパラメータに対して一意の値を設定する必要があります。

DBMS_AQADM.REMOVE_SUBSCRIBERプロシージャを使用して、サブスクライバを削除できます。

サブスクライバの簡単な例については、16.3.1項「サブスクライバ・コードの作成」を参照してください。

16.2.2.2 サブスクライバのキューの管理

Oracle Enterprise Manager DBA Studioにより、Oracle Streams AQを管理できます。DBA Studioを使用すると、キュー表の作成、キューの作成、AQメッセージのブラウズ、AQメッセージのアーカイブまたはパージ、AQサブスクライバの追加および伝播の管理を実行できます。また、DBA Studioには、データベース・レベルおよびキュー・レベルのキュー間でのメッセージの伝播を示す図が表示されます。

Oracle Diagnostics and Tuning Packは、AQキューに関するアラートおよび監視をサポートしています。特定のサブスクライバのメッセージ数がしきい値を超えた場合や、伝播中にエラーが発生した場合に対応するアラートを設定できます。また、READY状態にあるメッセージ数やサブスクライバごとのメッセージ数などについてキューを監視することもできます。

標準AQ APIを使用して、サブスクライバのキューを管理することもできます。詳細は、Oracle Enterprise Managerのドキュメントを参照してください。

16.2.2.3 メッセージのデキュー

キューからメッセージを取得する操作は、デキューと呼ばれます(図16-1)。

図16-1 デキュー・プロセス

デキュー・プロセスを示すフロー・チャート。
「図16-1 デキュー・プロセス」の説明

DBMS_AQ.DEQUEUEプロシージャを使用して、WWSBR_EVENT_Qキューからメッセージをデキューします。例16-2は、サブスクライバJAYのデキューを示します。

例16-2 メッセージのデキュー

...
dequeue_options.wait          := dbms_aq.NO_WAIT;
dequeue_options.consumer_name := 'JAY';
dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
dequeue_options.dequeue_mode  := dbms_aq.BROWSE;
dbms_aq.dequeue(
  queue_name         => 'WWSBR_EVENT_Q',
  dequeue_options    => dequeue_options,
  message_properties => message_properties,
  payload            => message,
  msgid              => message_handle
);
...
  • NAVIGATION: DBMS_AQ.DEQUEUE操作のNAVIGATIONパラメータを使用して、メッセージをデキューする順序を決定します。デキュー・リクエストのデフォルトのNAVIGATIONパラメータは、NEXT_MESSAGEです。つまり、後続のデキュー操作では、メッセージは、最初のデキューで取得されたスナップショットに基づいてキューから取得されます。特に、デキュー・コマンドの後にエンキューされたメッセージは、先にキューにエンキューされていたメッセージがすべて処理されないと処理されません。このキューでは優先順位に基づく順序付けが行われないので、WWSBR_EVENT_Qキューにエンキューされたメッセージの場合はこれで十分対応できます。


    注意:

    多少の遅延を伴うNEXT_MESSAGEは、AQメッセージの処理に最適な方法です。デキュー・コマンドごとにキュー内の最初のメッセージを処理する必要がある場合、サブスクライバは、FIRST_MESSAGEナビゲーション・オプションを明示的に使用する必要があります。

  • DEQUEUE_MODE: デキュー・リクエストによって、メッセージを表示および削除できます。メッセージを表示する場合、サブスクライバはBROWSEまたはLOCKモードを使用できます。メッセージを消費する場合、サブスクライバはREMOVEまたはREMOVE_NODATAモードを使用できます。サブスクライバがメッセージをブラウズしても、メッセージは後の処理で引き続き使用可能です。同様に、ロックされたメッセージは、サブスクライバがトランザクションのコミットまたはロールバックを実行してロックを解放した後でも、後の処理で引き続き使用可能です。表示されたメッセージが同時ユーザーによってデキューされないようにするには、メッセージをロック・モードで表示する必要があります。サブスクライバがいずれかのREMOVEモードでメッセージを消費すると、メッセージはデキュー・リクエストに対して使用不可能になります。

    サブスクライバがREMOVE_NODATAモードでメッセージをデキューする場合、リクエストではメッセージのペイロードは取得されません。ユーザーが前回、BROWSEモードでのデキューなどによってメッセージのペイロードをすでに調べている場合に、このモードを使用できます。このようにして、ペイロードが大きい場合に長時間を要するペイロード取得のオーバーヘッドを回避できます。


    注意:

    サブスクライバごとに1つのイベントがエンキューされます。このため、1つのサブスクライバのキューからイベントを削除しても、そのイベントはその他のサブスクライバのキューからは削除されません。

  • CONSUMER_NAME: サブスクライバは、このキューの名前を指定することにより、WWSBR_EVENT_Qキューからメッセージをデキューできます。

    • PL/SQLでは、DEQUEUE_OPTIONS_TレコードのCONSUMER_NAMEフィールドを使用してコンシューマ名を指定します。

    • OCIでは、OCISetAttrプロシージャを使用してコンシューマ名を指定し、テキスト文字列をOCI_DTYPE_AQDEQ_OPTIONS記述子のOCI_ATTR_CONSUMER_NAMEとして指定します。

    • Visual Basic(OO4O)では、OraAQオブジェクトのコンシューマ・プロパティを設定して、コンシューマ名を指定します。

    複数のプロセスまたはオペレーティング・システム・スレッドが同じメッセージ名を使用してキューからメッセージを同時にデキューすることは可能です。コンシューマは、デキュー時に特定のメッセージIDを指定しないかぎり、READY状態にあるメッセージをすべてデキューできます。


注意:

検索パラメータを使用してCMEFイベントをデキューする必要はありません。

16.2.3 例外処理

すべての対象となるコンシューマによってメッセージが正常にデキューされると、メッセージは処理されたとみなされます。なんらかの理由によってメッセージが処理されない場合、メッセージは例外キューに移動されます。

1つ以上のコンシューマが有効期限前にメッセージをデキューできない場合、メッセージは期限切れとみなされます。期限切れのメッセージも例外キューに移動されます。例外キューは、すべての期限切れのメッセージまたは使用できないメッセージが格納されるリポジトリです。

アプリケーションがメッセージを例外キューに直接エンキューすることはできません。また、例外キューにサブスクライバを関連付けることもできません。ただし、これらの期限切れのメッセージまたは使用できないメッセージを処理するアプリケーションは、例外キューからメッセージをデキューする必要があります。

CMEF例外は、WWSBR_EVENT_ERR_Q例外キューに送信されます。WWSBR_EVENT_Qマルチコンシューマ・キューの期限切れメッセージを、メッセージの対象となる受信者がデキューすることはできません。ただし、デキュー・オプションにNULLコンシューマ名を指定することにより、これらのメッセージがREMOVEモードになるとデキューできます。キュー・モニターは、マルチコンシューマ・キューから期限切れメッセージを削除します。これにより、デキュー元は、キュー表のメッセージをロックせずにデキュー操作を完了できます。

キュー・モニターは、すべてのコンシューマによって処理されたメッセージをマルチコンシューマ・キューから定期的に削除するので、ユーザーには、メッセージが完全に処理されたときと、メッセージがキューから物理的に削除されるときの間に遅延があるように見えることがあります。


注意:

WWSBR_EVENT_ERR_Q例外キューは、すべての例外キューと同様に単一コンシューマ・キューです。

16.2.4 メッセージのリスニング

Oracle Streams AQは、1回のLISTENコールで複数のメッセージ・キューを監視できます。サブスクライバは、LISTENを使用して、複数のサブスクリプション用のメッセージを待機できます。また、ゲートウェイ・アプリケーションも、LISTENを使用して複数のキューを監視できます。LISTENコールが正常に返された場合、デキューを使用してメッセージを取得する必要があります。LISTENコールを使用しない場合、一連のキューからデキューしようとするアプリケーションは、WWSBR_EVENT_Qキューに対して連続してポーリングし、メッセージの有無を確認する必要があります。

また、キューごとに別々のデキュー・プロセスを使用するようにサブスクライバを設計することもできます。ただし、WWSBR_EVENT_Qを含む任意のキューに長期間にわたってトラフィックがない場合、許容不可能なオーバーヘッドがこれらのアプリケーションによって発生します。LISTENコールは、このようなサブスクライバに適しています。エージェント・リストの複数のエージェントにメッセージがある場合、LISTENは、メッセージがある最初のエージェントを返します。

LISTENコールを使用すると、エージェント・リストのエージェントではなく、1つ以上のキューでのメッセージ受信を監視できます。このコールは、エージェント・リストを引数として使用します。監視対象のキューは、リストされている各エージェントのアドレス・フィールドで指定されます。また、マルチコンシューマ・キューを監視する場合は、エージェント名も指定する必要があります。例16-3に、LISTENコールを使用して複数のキューでメッセージをリスニングする方法を示します。

例16-3 複数のキューにおけるメッセージのリスニング

declare
  agent_w_msg   aq$agent;
  qlist         dbms_aq.agent_list_t;
begin
  -- MYQ1, MYQ2, MYQ3 are multiconsumer queues in the SCOTT schema.
  qlist(1) := aq$agent('agent1', 'scott.MYQ1', null);
  qlist(2) := aq$agent(null, 'scott.MYQ2', null);
  qlist(3) := aq$agent('agent3', 'scott.MYQ3', null);
  -- Listen with a timeout of 100 seconds.
  dbms_aq.listen(
    agent_list => qlist,
    wait       => 100,
    agent      => agent_w_msg
  );
  dbms_output.put_line('MSG in Q: '||agent_w_msg.address||'for '
    ||agent_w_msg.name);
  dbms_output.put_line('');
end;
/

これは、リスト内のエージェントについて消費可能なメッセージがあるときに返されるブロック化コールです。複数のエージェントに対するメッセージがある場合、リストされている最初のエージェントのみが返されます。待機時間が経過したときにメッセージがない場合は、エラーが発生します。

コールが正常に返された場合でも、リストされているエージェントの1つに対するメッセージが指定されたキューのいずれかにあることしかわかりません。関連エージェントは該当するメッセージをデキューする必要があります。例16-4は、リスニングとデキュー・プロセスの組合せを示しています。ここでは、一定期間にわたるサブスクライバJAYのメッセージをデキューしています。

例16-4 リスニングおよびメッセージのデキュー

begin
  agent_list(1)     := sys.aq$_agent('JAY', 'WWSBR_EVENT_Q', null);
  wait_time integer := 100;
  loop
    -- Wait for order status messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    -- If there are messages for JAY, dequeue them.
    if (agent_w_message.name = 'JAY') then
      dequeue_options.wait          := dbms_aq.NO_WAIT;
      dequeue_options.consumer_name := 'JAY';
      dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
      dequeue_options.dequeue_mode  := dbms_aq.BROWSE;
      dbms_aq.dequeue(
        queue_name         => 'item_queue',
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
    end if;
  end loop;
exception
  when NO_MESSAGES then
    dbms_output.put_line('No more messages for Jay');
end;
/

16.3 コンテンツ管理イベント・フレームワークの使用

すべてのポータル・アイテムおよびページ・アクションは、WWSBR_EVENT_QキューにエンキューされるCMEFメッセージを生成します。サブスクライバは、このメッセージに含まれる情報を利用し、Oracle Portal PL/SQL APIを使用して様々なアクションを実行できます。

CMEFイベントの処理には次の3つの基本ステップがあります。各ステップについてこの項で説明します。手順は次のとおりです。

  1. 16.3.1項「サブスクライバ・コードの作成」

  2. 16.3.2項「WWSBR_EVENT_Qへのサブスクライバの追加」

  3. 16.3.3項「ページ・グループ・レベルでのCMEFイベントの有効化」

また、この項では、メッセージのペイロードについて説明し、次に一般的なポータル・アクションとアクションによって生成されるイベントの例も示します。

16.3.1 サブスクライバ・コードの作成

Oracle Streams AQには、コンテンツ・ベースのサブスクリプション・モデルが用意されています。サブスクライバ・アプリケーションは、メッセージ・コンテンツに基づいてお気に入りを指定できます。Oracle PortalスキーマでCMEFイベント・サブスクライバ・コードを実行する必要があります。例16-5に、サンプル・サブスクライバを示します。

例16-5 サブスクライバの例

create or replace <procedure name> as
  agent_list         dbms_aq.aq$_agent_list_t;
  wait_time          integer       := <time in seconds>;
  agent_w_message    sys.aq$_agent;
  dequeue_options    dbms_aq.dequeue_options_t;
  message_properties dbms_aq.message_properties_t;
  message_handle     raw(16);
  message            <portal schema>.wwsbr_event;
  l_subscriber       varchar2(30)  := '<subscriber name>';
  l_queue            varchar2(30)  := 'PORTAL.WWSBR_EVENT_Q';
  l_mode             binary_integer := dbms_aq.[BROWSE|LOCK|REMOVE|REMOVE_NODATA];
  ...
  <additional parameters>
  ...
BEGIN
  agent_list(1) := sys.aq$_agent(l_subscriber, l_queue, null);
  loop
    -- Listen for messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    -- If there are messages for the subscriber then dequeue them.
    if (agent_w_message.name = l_subscriber) then
      dequeue_options.wait          := dbms_aq.NO_WAIT;
      dequeue_options.consumer_name := l_subscriber;
      dequeue_options.navigation    := dbms_aq.[NEXT_MESSAGE|FIRST_MESSAGE];
      dequeue_options.dequeue_mode  := l_mode;
      -- Dequeue messages.
      dbms_aq.dequeue(
        queue_name         => l_queue,
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
      -- Determine the type of event that occurred and act accordingly.
      ...
      <your code here>
      ...
    end if;
  end loop;
  -- Process cache invalidation messages.
  wwpro_api_invalidation.execute_cache_invalidation;
end;
/

16.3.2 WWSBR_EVENT_Qへのサブスクライバの追加

サブスクライバは、メッセージを消費するキューをサブスクライブします。例16-6に示すように、CMEFイベント・メッセージを処理するには、サブスクライバをWWSBR_EVENT_Qキューに追加する必要があります。

例16-6 WWSBR_EVENT_Qへのサブスクライバの追加

declare
  subscriber sys.aq$_agent;
begin
  subscriber := sys.aq$_agent('<subscriber>', null, null);
  dbms_aqadm.add_subscriber(
    queue_name => '<portal schema>.wwsbr_event_q',
    subscriber => subscriber
  );
end;
/

16.3.3 ページ・グループ・レベルでのCMEFイベントの有効化

Oracle Portalでは、CMEFはページ・グループ・レベルで有効化または無効化されます。デフォルトでは、ユーザーがページ・グループを作成するとCMEFが有効化され、Oracle Portalユーザー・インタフェースまたはWebDAVで変更が行われるたびにイベントがトリガーされます。

ページ・グループに対してCMEFを有効化または無効化する手順は、次のとおりです。

  1. ページ・グループの任意のページに移動し、「編集」モードに切り替えます。

  2. ページ上部のツールバーで、「ページ・グループ」の横にある「プロパティ」リンクをクリックします。


    注意:

    「ページ」の横にあるリンクではなく、「ページ・グループ」の横にあるリンクをクリックしてください(図16-2)。

    図16-2 「編集」モードのツールバーにある「ページ・グループ: プロパティ」リンク

    「ページ・グループ: プロパティ」リンク。
    「図16-2 「編集」モードのツールバーにある「ページ・グループ: プロパティ」リンク」の説明

  3. 「構成」タブをクリックして前面に表示します。

  4. 「コンテンツ管理イベント・フレームワーク」セクションで、CMEFが有効か無効かを確認できます。この設定を変更するには、「編集」リンクをクリックします(図16-3)。

    図16-3 ページ・グループのCMEFのステータス

    ページ・グループのCMEFのステータス。
    「図16-3 ページ・グループのCMEFのステータス」の説明

  5. CMEFを有効にするには、「コンテンツ管理イベント・フレームワークを有効にする」チェック・ボックスを選択します(図16-1)。CMEFを無効にするには、チェック・ボックスの選択を解除します。

    図16-4 ページ・グループのCMEFの有効化または無効化

    「コンテンツ管理イベント・フレームワークを有効にする」ページ。
    「図16-4 ページ・グループのCMEFの有効化または無効化」の説明

  6. OK」をクリックして変更内容を保存します。

  7. 「閉じる」をクリックして、ページに戻ります。

16.3.4 CMEFイベントの調査

CMEFのイベントのページ(図16-5)を使用して、WWSBR_EVENTS_Qキューに追加されているサブスクライバを調査します。

CMEFのイベントのページにアクセスする手順は、次のとおりです。

  1. Portalスキーマの所有者としてポータルにログインします。

  2. ブラウザの「アドレス」フィールドに次のURLを入力します。

    http://<host>:<port>/portal/pls/<dad>/<schema>.wwsbr_event_dbg.show
    
    • host: ポータルの中間層がインストールされているマシンです。

    • port: ポータルによって使用されるポートです。

    • dad: Oracle Portalインストールのデータベース・アクセス記述子(DAD)です。

    • schema: Oracle Portalがインストールされているスキーマです。


注意:

CMEFのイベントのページはサポートされていませんが、デバッグ用としてOracle Portalに含まれています。このページにアクセスできるのは、Portalスキーマの所有者のみです。

図16-5 CMEFのイベントのページ

CMEFのイベントのページ。
「図16-5 CMEFのイベントのページ」の説明

16.3.5 CMEFサブスクライバの実行

サブスクライバを実行するには、例16-7に示されているコマンドをSQLプロンプトで発行します。

例16-7 サブスクライバの実行

begin
  <subscriber procedure>();
end;
/

16.3.6 CMEFメッセージのペイロード

Oracle Portalユーザー・インタフェースまたはPL/SQLコンテンツ管理のアクションは、すべてINSERT、UPDATE、DELETEという3つの主要なCMEFイベントの1つに分類されます。また、状態はイベントをより詳細に説明します。たとえば、ADD/INSERT ITEMイベントには、次のタイプがあります。

  • アイテムを追加し、即座に公開します。

  • アイテムを追加し、後で公開します。

  • ユーザーが「承認付きアイテムの管理」権限を持っているため、承認が必要なアイテムを追加します。

アクションとそれに関連するイベントおよび状態の詳細なリストは、付録G「コンテンツ管理イベント・フレームワークのイベント」を参照してください。

表16-2に示すように、各CMEFイベントには関連付けられたCMEFメッセージ・ペイロードがあります。

表16-2 CMEFメッセージのペイロード・プロパティ

メッセージ・プロパティ タイプ 説明

ACTION

VARCHAR2(30)

イベントをトリガーしたポータル・アクション。

RAW_EVENT

VARCHAR2(30)

ポータル・アクションの結果として作成されたイベント。

STATE

VARCHAR2(30)

イベントに関連する追加情報を提供します。

OBJECT_ID

NUMBER

イベントが関連するオブジェクト(アイテム、ページ、カテゴリなど)のID。

OBJECT_SITE_ID

NUMBER

オブジェクトが属しているページ・グループのID。

OBJECT_LANGUAGE

VARCHAR2(30)

セッション言語。

アクションが言語に依存していない場合はNULL。

PAGE_ID

NUMBER

アイテムの場合、アイテムが表示されるページのID。

その他のオブジェクトの場合はNULL。

PAGE_SITE_ID

NUMBER

アイテムの場合、PAGE_IDで識別されるページが属しているページ・グループのID。

アイテム以外の関連するイベントの場合はNULL。

OBJECT_CLASS

VARCHAR2(30)

イベントが発生したオブジェクトのクラスを記録します。

EVENTS_USER

VARCHAR2(256)

ポータル・アクションを実行したユーザーの名前。

EVENTS_DATE

VARCHAR2(60)

イベントが発生した日付。書式: dd-mon-yyyy HH12:MI PM。

ID1 (OVERLOADED)

NUMBER

アイテムの場合、アイテム・タイプID。

ページの場合、ページ・タイプID。

アイテム・タイプおよびページ・タイプの場合、基本タイプID。

SITE_ID1 (OVERLOADED)

NUMBER

アイテム・タイプの場合、アイテム・タイプが属しているページ・グループのID。

ページの場合、ページ・タイプが属しているページ・グループのID。

アイテム・タイプおよびページ・タイプの場合、基本タイプが属しているページ・グループのID。

GROUP_ID

NUMBER

特定のイベントに複数のメッセージが関連付けられている場合に、関連するメッセージが持つ同じグループID。

OBJECT PATH

VARCHAR2(4000)

キューにあるこのメッセージによって参照されるポータル・オブジェクトの一意のパス(NULLも可)。ページ、アイテム、カテゴリ、パースペクティブ、アイテム・タイプおよびページ・タイプに対してのみ使用されます。

OBJECT UID

VARCHAR2(4000)

このメッセージによって参照されるポータル・オブジェクトへの一意の不変識別子。ページ、アイテム、カテゴリ、パースペクティブ、アイテム・タイプおよびページ・タイプに対してのみ使用されます。


16.3.7 Oracle PortalアクションおよびCMEFイベント

この項では、最も一般的なポータル・アクションについて説明し、これらのアクションを検出するためのコードをサブスクライバに含める方法を示します。これらのアクションは、Oracle Portalユーザー・インタフェース、Oracle Portal PL/SQL APIまたはWebDAVを介して実行されます。

ポータル・アクションとアクションによって生成されるイベントおよびメッセージ・ペイロードの詳細なリストは、付録G「コンテンツ管理イベント・フレームワークのイベント」を参照してください。

16.3.7.1 ページおよびページ・グループのアクション

Oracle Portalでは、ポータルは、1つ以上のページ・グループの集合です。ページ・グループは、一般的な属性やメカニズムを設定できるページの階層的な集合です。

16.3.7.1.1 ページの作成

ページを作成すると、次のCMEFメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
ADD_PAGE INSERT PUBLISHED PAGE
ADD_ITEM INSERT PUBLISHED ITEM

最初のメッセージはページ自体用で、2つ目のメッセージは、ページ上でデフォルトのナビゲーション・ページを表示するポートレット・インスタンス用です。

ページの作成に応答するサブスクライバを必要とする場合は、次のチェックを実行します。

if ((message.object_class = 'PAGE') and
    (message.raw_event    = wwsbr_event_q_access.EVENT_INSERT) then
. . .
end if;
16.3.7.1.2 ページのアクセス制御リストの更新

ページ・グループのACLを継承しないようにページのACLを変更し、「適用」または「OK」をクリックすると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
SPECIFY_PAGE_ACL UPDATE GENERAL PAGE

ユーザーをページのACLに追加し、「追加」をクリックすると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
ADD_PAGE_ACL UPDATE GENERAL PAGE

ページ・グループのACLを継承しないようにページのACLを変更して、ユーザーまたはグループをACLに追加し、「適用」または「OK」をクリックすると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
SPECIFY_AND_ADD_PAGE_ACL UPDATE GENERAL PAGE

ページ・グループのACLを継承するようにページのACLを変更し、「適用」または「OK」をクリックすると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
INHERIT_PAGE_ACL UPDATE GENERAL PAGE

「ページ・プロパティ」ページで「適用」または「OK」をクリックすると、追加メッセージが作成されます。

アクション イベント 状態 オブジェクト・クラス
UPDATE_PAGE_ACL UPDATE GENERAL PAGE

16.3.7.1.3 ページ・グループのアクセス制御リストの更新

ユーザーまたはグループを追加または削除し、ページ・グループのアクセス制御リスト(ACL)を更新すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
ADD_PAGEGROUP_ACL

または

DELETE_PAGE_GROUP_ACL

UPDATE GENERAL PAGE_GROUP
UPDATE_PAGE_GROUP_ACL UPDATE GENERAL PAGE_GROUP

ページ・グループでの一般ACLの更新に応答するサブスクライバを必要とする場合は、次のチェックを実行します。

if ((message.action       = 'UPDATE_PAGE_GROUP_ACL') and
    (message.object_class = 'PAGE_GROUP') and
    (message.raw.event    = wwsbr_event_q_access.EVENT_UPDATE)) then
. . .
end if;

ただし、ページ・グループのACLに対して実際に更新および削除イベントがあるかどうかでフィルタ処理する必要がある場合、サブスクライバは次のチェックを実行する必要があります。

if ((message.object_class = 'PAGE_GROUP') and
    (message.raw_event    = wwsbr_event_q_access.EVENT_UPDATE)) then
  if (message.action = 'ADD_PAGE_GROUP_ACL') then
    . . .
  end if;
  if (message.action = 'DELETE_PAGE_GROUP_ACL') then
    . . .
  end if;
  . . .
end if;

注意:

ADD_PAGE_GROUP_ACLおよびDELETE_PAGE_GROUP_ACLイベントは、ACLに追加またはACLから削除するユーザーごとに、ユーザーが「追加」をクリックしたときにトリガーされます。UPDATE_PAGE_GROUP_ACLは、ユーザーが「適用」または「OK」をクリックしたときに生成されます。

16.3.7.1.4 ページの削除

ページを削除すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
DELETE_PAGE DELETE PURGED PAGE


注意:

イベントは、ページ上のサブページまたはアイテムに対しては生成されません。

16.3.7.2 アイテムの操作

アイテムは、ポータル・ページの基本的なコンポーネントの1つです。ポータルのアイテムは、アイテム・タイプをベースとしています。ただし、アイテムに対するアクションは、アイテム・タイプとは関係なくCMEFイベントをトリガーします。

たとえば、ADD_ITEMアクションは、ユーザーが基本、拡張またはカスタムの各アイテム・タイプのアイテムを追加するたびに発生します。これにより、アイテムのアクションが発生する場合に、一貫性のあるCMEFメッセージ動作が行われるようになります。

16.3.7.2.1 アイテムの作成と即時公開

ユーザーが「管理」権限を持っている場合、ページで任意のタイプのアイテムを作成すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
ADD_ITEM INSERT PUBLISHED ITEM

このアクションに応答するサブスクライバを必要とする場合は、次のチェックを実行します。

if ((message.action       = 'ADD_ITEM') and
    (message.object_class = 'ITEM') and
    (message.raw_event    = 'INSERT') and
    (message.state        = 'PUBLISHED')) then
   . . .
end if;
16.3.7.2.2 承認を必要とするアイテムの追加

ページ(またはページ・グループ)、および「承認付きアイテムの管理」権限を持つユーザーに対して承認および通知が有効である場合、ページにアイテムを追加すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
SUBMIT_ITEM_FOR_APPROVAL INSERT NOT_PUBLISHED ITEM

このアクションに応答するサブスクライバを必要とする場合は、次のチェックを実行します。

if ((message.action       = 'SUBMIT_ITEM_FOR_APPROVAL') and
    (message.object_class = 'ITEM') and
    (message.raw_event    = 'INSERT') and
    (message.state        = 'NOT_PUBLISHED')) then
   . . .
end if;
16.3.7.2.3 アイテムの承認

アイテムを承認すると、INSERTまたはUPDATEイベントがトリガーされます。バージョニングが有効かどうかに応じて、この後にDELETEまたはUPDATEイベントが続く場合もあります。

アイテムは承認、バージョニングは無効

これが最も単純なケースです。アイテムにまだ通過する承認手順がある場合は、UPDATEイベントがトリガーされます。

アクション イベント 状態 オブジェクト・クラス
APPROVE_ITEM_STEP UPDATE GENERAL ITEM

アイテムの承認手順がすべて完了すると、INSERTイベントがトリガーされます。

アクション イベント 状態 オブジェクト・クラス
APPROVE_ITEM INSERT PUBLISHED ITEM

アイテムは承認、バージョニングは有効、現行のバージョンは上書き

アイテムのバージョニングがページまたはページ・グループ・レベルでシンプルに設定されているときに、ユーザーがアイテムの編集時に「現行のバージョンの上書き」を選択すると、アイテムの承認時に2つのイベントが生成されます。最初のイベントは、承認されるアイテムに関するイベントです。2つ目のイベントは、アイテムが承認される結果上書きされるアイテムに関するDELETEイベントです。

アクション イベント 状態 オブジェクト・クラス
APPROVE_ITEM INSERT PUBLISHED ITEM
APPROVE_ITEM DELETE PURGED ITEM

アイテムは承認、バージョニングは有効、新規の現行バージョン

アイテムのバージョニングがページまたはページ・グループ・レベルで「監査」またはシンプルに設定されている場合に、ユーザーが「アイテムを新規かつ現行バージョンとして追加」を選択すると、アイテムの承認時にINSERTイベントが生成されます。また、アイテムの前のバージョンをUNPUBLISHEDとしてマークすることに関するUPDATEイベントも生成されます。

アクション イベント 状態 オブジェクト・クラス
APPROVE_ITEM INSERT PUBLISHED ITEM
APPROVE_ITEM UPDATE UNPUBLISHED ITEM

アイテムが承認されたか承認のあるステージを通過したときに通知を送信するサブスクライバを作成する場合、次のチェックを実行する必要があります。

-- If an item is approved.
if ((message.action       = 'APPROVE_ITEM') and
    (message.object.class = 'ITEM') and
    (message.raw_event    = 'INSERT') and
    (message.state        = 'PUBLISHED')) then
   . . .
-- If an item has passed an approval step.
elsif ((message.action       = 'APPROVE_ITEM_STEP') and
       (message.object_class = 'ITEM') and
       (message.raw_event    = 'UPDATE') and
       (message.state        = 'PUBLISHED')) then
   . . .
end if;

アイテムは承認、バージョニングは有効、新規の非現行バージョン

追加されるアイテムに対してINSERTイベントが発生しますが、アイテムの状態はNOT_PUBLISHEDとしてマークされ、現行のバージョンとして公開されないことを示します。

アクション イベント 状態 オブジェクト・クラス
APPROVE_ITEM INSERT NOT_PUBLISHED ITEM

16.3.7.2.4 アイテムへのカテゴリまたはパースペクティブの適用

アイテムに異なるカテゴリまたはパースペクティブを適用すると、アイテムの編集時と同じメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
EDIT_ITEM UPDATE GENERAL ITEM


注意:

アイテムに適用したカテゴリまたはパースペクティブが変更されても、特定のイベントは生成されず、また、追加情報も提供されません。

このアクションに応答するサブスクライバを必要とする場合は、次のチェックを実行します。

if ((message.action       = 'EDIT_ITEM') and
    (message.object_class = 'ITEM') and
    (message.raw_event    = 'UPDATE') and
    (message.state        = 'GENERAL') then
   . . .
end if;
16.3.7.2.5 アイテムの削除

削除されるアイテムが保持される(すなわち、アイテムは削除としてマークされているが、実際には削除されない)ページ・グループからアイテムを削除すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
DELETE_ITEM DELETE MARKED_FOR_DELETE ITEM

削除されるアイテムが保持されない(すなわち、削除アイテムが即座に永続的に削除される)ページ・グループからアイテムを削除すると、次のメッセージ・ペイロードが作成されます。

アクション イベント 状態 オブジェクト・クラス
DELETE_ITEM DELETE PURGED ITEM

サブスクライバは、メッセージ・ペイロード内の状態値を使用して、発生した削除アクションのタイプを確認できます。

if ((message.action       = 'DELETE_ITEM') and
    (message.object_class = 'ITEM') and
    (message.raw_event    = 'DELETE')) then
  . . .
  -- If item is in a page group that does not actually delete items.
  if (message.state = 'MARKED_FOR_DELETE') then
      . . .
  -- If item is in a page group that actually deletes items.
  elsif (message.state = 'PURGED') then
      . . .
  end if;
end if;

16.4 例のインストール

次のいくつかの項にある例をデプロイし使用する場合は、CMEFSAMPLESという名前の別のスキーマに作成することをお薦めします。このスキーマを作成する手順は、次のとおりです。

  1. データベース・スキーマCMEFSAMPLESを作成します。SYSのみがアクセス権を持つ権限パッケージを付与する必要があるため、この操作はSYSユーザーとして実行する必要があります。このデータベース・スキーマは、Oracle Portalリポジトリがあるデータベースと同じデータベースに作成する必要があります。次に例を示します。

    @connect "/ as sysdba"
    drop user cmefsamples cascade;
    create user cmefsamples identified by oracle1
    default tablespace users temporary tablespace temp;
    grant connect, resource to cmefsamples;
    
  2. SYSスキーマとして、次の権限をCMEFSAMPLESに付与します。

    @connect "/ as sysdba"
    grant create table                  to cmefsamples;
    grant create sequence               to cmefsamples;
    grant create view                   to cmefsamples;
    grant create procedure              to cmefsamples;
    grant create trigger                to cmefsamples;
    grant create indextype              to cmefsamples;
    
    grant create synonym                to cmefsamples;
    grant create public synonym         to cmefsamples;
    
    grant create database link          to cmefsamples;
    grant create public database link   to cmefsamples;
    grant execute on dbms_utility       to cmefsamples;
    grant aq_administrator_role         to cmefsamples;
    grant aq_user_role                  to cmefsamples;
    grant execute  on dbms_aqadm        to cmefsamples;
    grant execute  on dbms_aq           to cmefsamples;
    grant execute  on aq$_agent         to cmefsamples;
    grant execute  on dbms_job          to cmefsamples;
    
    execute dbms_aqadm.grant_type_access('cmefsamples');
    execute dbms_aqadm.grant_system_privilege('ENQUEUE_ANY','cmefsamples',FALSE);
    execute dbms_aqadm.grant_system_privilege('DEQUEUE_ANY','cmefsamples',FALSE);
    execute dbms_aqadm.grant_system_privilege('MANAGE_ANY', 'cmefsamples', FALSE);
    EXECUTE DBMS_AQADM.GRANT_QUEUE_PRIVILEGE('ENQUEUE','portal.WWSBR_EVENT_Q','cmefsamples', FALSE);
    EXECUTE DBMS_AQADM.GRANT_QUEUE_PRIVILEGE('DEQUEUE','portal.WWSBR_EVENT_Q','cmefsamples', FALSE);
    
  3. Oracle Portal PL/SQL APIをコールする権限をCMEFSAMPLESスキーマに付与します。この方法の詳細は、9.3項「APIおよびセキュア・ビューへのアクセスの提供」を参照してください。

  4. Portalスキーマにログインし、次の権限を付与します。

    EXECUTE DBMS_AQADM.GRANT_QUEUE_PRIVILEGE('DEQUEUE','WWSBR_EVENT_Q','cmefsamples', FALSE);
    grant execute on wwsbr_event_q_access to cmefsamples;
    grant execute on wwpob_page_util to cmefsamples;
    grant select on wwsbr_all_folders to cmefsamples;
    grant execute on wwsbr_thing_types to cmefsamples;
    grant execute on wwv_thingdb to cmefsamples;
    grant execute on wwsbr_event to cmefsamples;
    
  5. CMEFSAMPLESスキーマにログインし、次を実行します。

    sqlplus cmefsamples/<password>
    create synonym aq$_agent for sys.aq$_agent;
    
詳細はOTN

次の例のコードをOTNからダウンロードできます。

http://www.oracle.com/technology/products/ias/portal/files/cm_overview_10g1014_cmef_samples.zip

16.5 例: Portalオブジェクトのイベント・ロギング

例16-9のLOG_PORTAL_EVENTサブスクライバは、CMEFイベントをリスニングし、CMEF_LOG_TABLEというログ・データベース表(例16-8)にこのイベントを書き込みます。

例16-8 CMEF_LOG_TABLE

create table cmef_log_table(
  action          varchar2(30),
  event           varchar2(30),
  state           varchar2(30),
  object_type     varchar2(30),
  object_id       number,
  object_site_id  number,
  object_language varchar2(30),
  page_id         number,
  page_site_id    number,
  performed_by    varchar2(30)
)

例16-9 LOG_PORTAL_EVENTサブスクライバ

create or replace procedure log_portal_event as
  agent_list         dbms_aq.aq$_agent_list_t;
  wait_time          integer        := 5;
  agent_w_message    sys.aq$_agent;
  dequeue_options    dbms_aq.dequeue_options_t;
  message_properties dbms_aq.message_properties_t;
  message_handle     raw(16);
  message            portal.wwsbr_event;
  l_subscriber       varchar2(30)   := 'CMEF_LOG_PORTAL_EVENT';
  l_queue            varchar2(30)   := 'PORTAL.WWSBR_EVENT_Q';
  l_mode             binary_integer := dbms_aq.REMOVE;
begin
  agent_list(1) := sys.aq$_agent(l_subscriber, l_queue, null);
  loop
    -- Wait for messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    if (agent_w_message.name = l_subscriber) then
      dequeue_options.wait          := dbms_aq.NO_WAIT;
      dequeue_options.consumer_name := l_subscriber;
      dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
      dequeue_options.dequeue_mode  := l_mode;
      dbms_aq.dequeue(
        queue_name         => l_queue,
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
      insert into cmef_log_table values(
        message.action,
        message.raw_event,
        message.state,
        message.object_class,
        message.object_id,
        message.object_site_id,
        message.object_language,
        message.page_id,
        message.page_site_id,
        message.events_user
      );
      commit;
    end if;
  end loop;
end;
/

LOG_PORTAL_EVENTサブスクライバは、wait_time変数に指定された5秒の待機時間の間、WWSBR_EVENT_Qキュー上でイベントを継続的にリスニングします。次に、REMOVEモードでCMEFイベントをデキューし、メッセージ・ペイロード値をログ表に挿入します。

例16-9のコードを使用して、ログ表の結果を表示するHTMLページを構築できます。たとえば、図16-6の表は、アイテムの編集操作に関するCMEFメッセージ・ペイロードを示します。

図16-6 CMEFメッセージのペイロード値を示すHTML表

ポータル・イベント・ロギング・サブスクライバの出力例。
「図16-6 CMEFメッセージのペイロード値を示すHTML表」の説明

CMEFメッセージのペイロードのプロパティ(message.raw_eventなど)の詳細は、16.3.6項「CMEFメッセージのペイロード」を参照してください。

LOG_PORTAL_EVENTサブスクライバがWWSBR_EVENT_Qキューから継続的にメッセージを削除するようにするには、例16-9から次の内容を削除する必要があります。

dbms_aq.listen(
  agent_list => agent_list,
  wait       => wait_time,
  agent      => agent_w_message
);
if (agent_w_message.name = l_subscriber) then
  dequeue_options.wait          := dbms_aq.NO_WAIT;
  dequeue_options.consumer_name := l_subscriber;
  dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
  dequeue_options.dequeue_mode  := l_mode;
END IF;

例16-10は、前項で作成したLOG_PORTAL_EVENTサブスクライバをWWSBR_EVENT_Qキューに追加する方法を示しています。

例16-10 WWSBR_EVENT_QへのLOG_PORTAL_EVENTサブスクライバの追加

declare
  subscriber sys.aq$_agent;
begin
  subscriber := sys.aq$_agent('CMEF_LOG_PORTAL_EVENT', null, null);
  dbms_aqadm.add_subscriber(
    queue_name => 'portal.wwsbr_event_q',
    subscriber => subscriber
  );
end;
/

LOG_PORTAL_EVENTサブスクライバを実行するには、例16-11に示されているコマンドを発行します。

例16-11 LOG_PORTAL_EVENT CMEFサブスクライバの実行

begin
  log_portal_event();
end;
/

16.6 例: アイテム通知

例16-12のitem_notifyサブスクライバは、ユーザーが指定ページ上でアイテムを追加、更新または削除するたびに電子メール通知を送信します。

例16-12 CMEF_ITEM_NOTIFYサブスクライバ

create or replace procedure item_notify as
  MIME_TYPE_TEXT      constant varchar(30)  := 'text/plain';
  CUSTOM_ATTRIBUTE_ID constant number := 1020;
  ADDED               constant varchar2(20) := 'added';
  UPDATED             constant varchar2(20) := 'updated';
  DELETED             constant varchar2(20) := 'deleted';
  ITEM                constant varchar2(10) := 'ITEM';
  agent_list          dbms_aq.aq$_agent_list_t;
  wait_time           integer               := 5;
  begin_time          pls_integer;
  end_time            pls_integer;
  agent_w_message     sys.aq$_agent;
  dequeue_options     dbms_aq.dequeue_options_t;
  message_properties  dbms_aq.message_properties_t;
  message_handle      raw(16);
  message             portal.wwsbr_event;
  l_subscriber        varchar2(30)          := 'CMEF_ITEM_NOTIFY';
  l_queue             varchar2(30)          := 'PORTAL.WWSBR_EVENT_Q';
  l_page_id           number                := 33; -- Page ID of page.
  l_mode              binary_integer        := dbms_aq.REMOVE;
  l_rec               varchar2(256);
  l_body              varchar2(4000)        := null;
  l_from_user         varchar2(30)          := '<from-email-address>';
  l_to_user           varchar2(30)          := '<to-email-address>';
  l_event             varchar2(30)          := '';
  l_portal_user_name  varchar2(30)          := 'portal';
  l_portal_password   varchar2(30)          := '<portal password>';
  l_display_name      varchar2(256)         := '';

begin
  begin_time :=  dbms_utility.get_time;
  agent_list(1) := sys.aq$_agent(l_subscriber, l_queue, null);
  loop
    -- Wait for messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    if (agent_w_message.name = l_subscriber) then
      dequeue_options.wait          := DBMS_AQ.NO_WAIT;
      dequeue_options.consumer_name := l_subscriber;
      dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
      dequeue_options.dequeue_mode  := l_mode;
      dbms_aq.dequeue(
        queue_name         => l_queue,
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
      if ((message.object_class = ITEM)) then
        -- Determine the type of event that occurred.
        if (message.raw_event = portal.wwsbr_event_q_access.EVENT_INSERT) then
          l_event  := ADDED;
        elsif (message.raw_event = portal.wwsbr_event_q_access.EVENT_UPDATE) then
          l_event  := UPDATED;
        elsif (message.raw_event = portal.wwsbr_event_q_access.EVENT_DELETE) then
          l_event  := DELETED;
        end if;
        if ((l_event = ADDED) or
            (l_event = UPDATED) or
            (l_event = DELETED)) then
          -- Set the Portal Context.
          portal.wwctx_api.set_context(l_portal_user_name, l_portal_password);

          begin
            -- Get the Item Display name from the all items view.
            select display_name
            into l_display_name
            from portal.wwsbr_all_items
            where id=message.object_id 
            and caid=message.object_site_id;
          exception
            when NO_DATA_FOUND then
              dbms_output.put_line(sqlerrm);
              exit;
          end;

          -- Only send an e-mail if the item has a display name.
          if (l_display_name is not null) then
            -- Construct the body of the message.
            l_body := l_body || '<br>An item titled '
            || CSBR_UTIL.file_viewer_hyperlink(
            message.object_id, message.page_site_id, l_display_name)
            || ' was '
            || l_event || ' on '
            || to_char(message.events_date,'dd-mon-yyyy hh12:mi pm')
            || ' by ' || message.events_user || '. ';
            -- Send the message.
            html_email(
              p_from => l_from_user,
              p_to => l_to_user,
              p_subject => 'Item ' || l_event || ' Notification',
              p_text => 'Text',
              p_html => l_body
            );
          end if;
        end if;
      end if;
    end if;
    end_time :=  dbms_utility.get_time;
    if (end_time - begin_time) > 3000 then
      exit;
    end if;
  end loop;
end;
/

ITEM_NOTIFY CMEFサブスクライバは、キューから実際のイベントを削除し、複数の電子メールがユーザーに送信されないようにします。


注意:

アイテムのURLを取得するfile_viewer_hyperlinkファンクション、およびメッセージの実際の送信を処理するhtml_emailプロシージャの詳細は、「追加コード」を参照してください。

詳細はOTN

AQイベントのパフォーマンスおよび実行時間の詳細は、OTNの「Streams Advanced Queuing」ページを参照してください。

http://www.oracle.com/technology/products/aq

サブスクライバをWWSBR_EVENT_Qキューに追加する方法の例は、例16-10を参照してください。

サブスクライバの実行方法の例は、例16-11を参照してください。

ITEM_NOTIFY CMEFサブスクライバは、3秒間実行されます。これにより、サブスクライバが作動し続けてシステム・リソースを消費することがなくなります。また、サブスクライバで使用されるwait_time値をより高い値(60秒など)に変更し、サブスクライバが新しいイベントを毎分リスニングすることもできます。例16-13に示すように、DBMS_JOBを使用して、サブスクライバを一定間隔(30分など)で実行することもできます。

例16-13 DMBS_JOBの使用

declare
  v_job number;
begin
  dbms_job.submit(
    job      => v_job,
    what     => 'item_notify()',
    interval => 'SYSDATE + (30/(24*60))'
  );
end;
/

追加コード

例16-14は、CSBR_UTILパッケージを示します。

例16-14 CSBR_UTILパッケージ

create or replace package CSBR_UTIL as
  function file_viewer_hyperlink(
    p_item_id in number,
    p_caid    in number,
    p_text    in varchar2) return varchar2;
end;

create or replace package body CSBR_UTIL as

  function file_viewer_url(
    p_item_id in number,
    p_caid    in number) return varchar2 is

    l_return      varchar2(10000);
    l_item_name   varchar2(100);
    l_folder_id   number;
    l_folder_name varchar2(100);
    l_portal_url  varchar2(1000);
  begin
    select name, folder_id
    into l_return, l_folder_id
    from portal.wwsbr_all_items
    where id   = p_item_id
    and caid   = p_caid
    and active = 1;
    begin
      while 1=1 loop
        select parent_id, name
        into l_folder_id, l_folder_name
        from portal.wwsbr_all_folders
        where id = l_folder_id
        and caid = p_caid;
        l_return := l_folder_name||'/'||l_return;
      end loop;
    exception
      when NO_DATA_FOUND then
        null; -- Exit loop at no rows found, this is expected.
    END;
    -- Set the Portal URL.
    l_portal_url := 'http://<host>:<port>/portal/page/<dad>/';
    return l_portal_url||l_return;
    exception
      when OTHERS then
        dbms_output.put_line(sqlerrm);
        return 'Error';
  end file_viewer_url;

  function file_viewer_hyperlink(
    p_item_id in number,
    p_caid    in number,
    p_text    in varchar2) return varchar2 is
  begin
    return ('<a href="'||file_viewer_url(
      p_item_id => p_item_id,
      p_caid    => p_caid)||'">'||p_text||'</a>');
  end file_viewer_hyperlink;

end;
/

例16-15は、html_emailプロシージャを示します。


注意:

このプロシージャを実行するには、データベースにOracle Database Sendmailパッケージをデプロイする必要があります。

例16-15 HTML電子メール・プロシージャ

create or replace procedure html_email(
  p_to      in varchar2,
  p_from    in varchar2 default '',
  p_subject in varchar2,
  p_text    in varchar2 default null,
  p_html    in varchar2 default null
)
is
  l_boundary   varchar2(255) default 'a1b2c3d4e3f2g1';
  l_connection utl_smtp.connection;
  l_body_html  clob := empty_clob; -- This LOB will be the e-mail message.
  l_offset     number;
  l_ammount    number;
  l_temp       varchar2(32767) default null;
begin
  l_connection := utl_smtp.open_connection('<Mail Server here>');
  utl_smtp.helo( l_connection, '<Mail Server here>' );
  utl_smtp.mail( l_connection, p_from );
  utl_smtp.rcpt( l_connection, p_to );
  l_temp := l_temp || 'MIME-Version: 1.0' || chr(13) || chr(10);
  l_temp := l_temp || 'To: ' || p_to || chr(13) || chr(10);
  l_temp := l_temp || 'From: ' || p_from || chr(13) || chr(10);
  l_temp := l_temp || 'Subject: ' || p_subject || chr(13) || chr(10);
  l_temp := l_temp || 'Reply-To: ' || p_from || chr(13) || chr(10);
  l_temp := l_temp || 'Content-Type: multipart/alternative; boundary=' || chr(34) || l_boundary || chr(34) || chr(13) || chr(10);
  ------------------------------------------------------------------------------
  -- Write the headers.
  dbms_lob.createtemporary( l_body_html, false, 10 );
  dbms_lob.write(l_body_html, length(l_temp), 1,l_temp);

  -------------------------------------------------------------------------------
  -- Write the text boundary.
  l_offset := dbms_lob.getlength(l_body_html) + 1;
  l_temp   := '--' || l_boundary || chr(13) || chr(10);
  l_temp   := l_temp || 'content-type: text/plain; charset=Shift_JIS' || chr(13) || chr(10) || chr(13) || chr(10);
  dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);

  ------------------------------------------------------------------------------
  -- Write the plain text portion of the e-mail.
  l_offset := dbms_lob.getlength(l_body_html) + 1;
  dbms_lob.write(l_body_html, length(p_text), l_offset, p_text);

  ------------------------------------------------------------------------------
  -- Write the HTML boundary.
  l_temp := chr(13) || chr(10) || chr(13) || chr(10) || '--' || l_boundary || chr(13) || chr(10);
  l_temp := l_temp || 'content-type: text/html;' || chr(13) || chr(10) || chr(13) || chr(10);
  l_offset := dbms_lob.getlength(l_body_html) + 1;
  dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);

  ------------------------------------------------------------------------------
  -- Write the HTML portion of the message.
  l_offset := dbms_lob.getlength(l_body_html) + 1;
  dbms_lob.write(l_body_html, length(p_html), l_offset, p_html);

  ------------------------------------------------------------------------------
  -- Write the final HTML boundary.
  l_temp := chr(13) || chr(10) || '--' || l_boundary || '--' || chr(13);
  l_offset := dbms_lob.getlength(l_body_html) + 1;
  dbms_lob.write(l_body_html, length(l_temp), l_offset, l_temp);

  ------------------------------------------------------------------------------
  -- Send the e-mail in 1900 byte chunks to UTL_SMTP.
  l_offset := 1;
  l_ammount := 1900;
  utl_smtp.open_data(l_connection);
  while l_offset < dbms_lob.getlength(l_body_html) loop
    utl_smtp.write_data(l_connection, dbms_lob.substr(l_body_html,l_ammount,l_offset));
    l_offset := l_offset + l_ammount;
    l_ammount := least(1900, dbms_lob.getlength(l_body_html) - l_ammount);
  end loop;
  utl_smtp.close_data(l_connection);
  utl_smtp.quit( l_connection );
  dbms_lob.freetemporary(l_body_html);
end;
/

16.7 例: アイテム検証

例16-16のitem_validation CMEFサブスクライバは、指定のポータル・ページに追加されたURLアイテムにURLが含まれるかどうかを検証します。アイテムにURLが含まれる場合、アイテムは、wwsbr_api.approve APIを使用して承認されます。含まれない場合、アイテムは、wwsbr_api.reject APIを使用して却下されます。

例16-16 ITEM_VALIDATION CMEFサブスクライバ

create or replace procedure item_validation as
  MIME_TYPE_TEXT      constant varchar2(30) := 'text/plain';
  agent_list          dbms_aq.aq$_agent_list_t;
  wait_time           integer               := 5;
  begin_time          pls_integer;
  end_time            pls_integer;
  agent_w_message     sys.aq$_agent;
  dequeue_options     dbms_aq.dequeue_options_t;
  message_properties  dbms_aq.message_properties_t;
  message_handle      raw(16);
  message             portal.wwsbr_event;
  l_subscriber        varchar2(30)          := 'CMEF_ITEM_VALIDATION';
  l_queue             varchar2(30)          := 'PORTAL.WWSBR_EVENT_Q';
  l_mode              binary_integer        := dbms_aq.REMOVE;
  l_attribute_site_id number                := 0;
  l_event             varchar2(30);
  l_doc               wwdoc_api.document_record;
  l_desc              varchar2(4000);
  l_portal_user_name  varchar2(30)          := 'portal';
  l_portal_password   varchar2(30)          := ' <portal password>';
  l_itemtype          varchar2(30)          := '';
  l_url               varchar2(4000)        := '';
begin
  begin_time :=  dbms_utility.get_time;
  agent_list(1) := sys.aq$_agent(l_subscriber, l_queue, null);
  loop
    -- Wait for messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    if (agent_w_message.name = l_subscriber) then
      dequeue_options.wait := DBMS_AQ.NO_WAIT;
      dequeue_options.consumer_name := l_subscriber;
      dequeue_options.navigation := dbms_aq.FIRST_MESSAGE;
      dequeue_options.dequeue_mode := l_mode;
      dbms_aq.dequeue(
        queue_name         => l_queue,
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
      -- If the event is an ITEM INSERT event and marked for later publication.
      if ((message.action       = 'SUBMIT_ITEM_FOR_APPROVAL') and
          (message.object_class = 'ITEM') and
          (message.raw_event    = 'INSERT') and
          (message.state        = 'NOT_PUBLISHED')) then

        -- Set the Portal Context.
        portal.wwctx_api.set_context(l_portal_user_name, l_portal_password);
        -- Get the Object Information.
        begin
          select itemtype, url
          into l_itemtype, l_url
          from portal.wwsbr_all_items
          where id=message.object_id 
            and caid=message.object_site_id;
        exception
          when NO_DATA_FOUND then
            dbms_output.put_line(sqlerrm);
            exit;
        end;
        -- If the item type is a URL and no URL is specified.
        if (l_itemtype = portal.wwsbr_thing_types.BASE_ITEM_TYPE_URL) and
           (l_url is null) then
          begin
            -- Update item to indicate that a URL needs to be specified.
            l_desc := '<font color=RED>NO URL SPECIFIED</font>';
            -- Reset the CMEF global variables.
            wwsbr_api.clear_cmef_context;
            wwsbr_api.set_attribute(
              p_site_id           => message.object_site_id,
              p_thing_id          => message.object_id,
              p_attribute_site_id => l_attribute_site_id,
              p_attribute_id      => wwsbr_api.ATTRIBUTE_DESCRIPTION,
              p_attribute_value   => l_desc
              p_log_cmef_message  => FALSE
            );
            -- Reject the item.
            wwsbr_api.reject(
              p_item_id => message.object_id,
              p_site_id => message.object_site_id,
              p_comment => 'Rejected'
            );
            -- Reset the CMEF global variables.
            wwsbr_api.clear_cmef_context;
          exception
            when OTHERS then
              dbms_output.put_line(sqlerrm);
          end;
        else
          -- Approve the item.
          begin
            wwsbr_api.approve(
              p_item_id => message.object_id,
              p_site_id => message.object_site_id,
              p_comment => 'Approved'
            );
            -- Reset the CMEF global variables.
            wwsbr_api.clear_cmef_context;
          exception
            when OTHERS then
              dbms_output.put_line(sqlerrm);
          end;
        end if;
        commit;
      end if;
    end if;
    end_time :=  dbms_utility.get_time;
    if (end_time - begin_time) > 3000 then
      exit;
    end if;
  end loop;
  -- Process cache invalidation messages.
  wwpro_api_invalidation.execute_cache_invalidation;
end;
/

item_validation CMEFサブスクライバの次のチェックにより、アイテムに承認が必要かどうかを確認します。

-- If the event is an ITEM INSERT event and marked for later publication.
if ((message.action       = 'SUBMIT_ITEM_FOR_APPROVAL') and
    (message.object_class = 'ITEM') and
    (message.raw_event    = 'INSERT') and
    (message.state        = 'NOT_PUBLISHED')) then
   . . .
end if;

item_validation CMEFサブスクライバには、wwsbr_api.set_attribute APIを使用して、ユーザーがURLを指定していないことを示すためアイテムの説明が設定されます。また、サブスクライバでは、このAPIをコールするときにCMEFメッセージをログに記録しないことも選択されます(p_log_cmef_messages = FALSE)。

-- Update item to indicate that a URL needs to be specified.
l_desc := '<font color=RED>No FILE NAME SPECIFIED</font>';
wwsbr_api.set_attribute(
  p_site_id           => l_thing.siteid,
  p_thing_id          => l_thing.id,
  p_attribute_site_id => l_attribute_site_id,
  p_attribute_id      => wwsbr_api.ATTRIBUTE_DESCRIPTION,
  p_attribute_value   => l_desc
  p_log_cmef_message  => FALSE
);

approveまたはreject APIを使用してアイテムを承認または却下すると、Oracle Portal UIを介してアイテムが承認または却下されたときと同様のイベントがトリガーされます。たとえば、wwsbr_api.approve APIをコールすると、INSERTイベントがAPPROVE_ITEMのアクションとともにトリガーされます。

wwsbr_api.approve(
  p_item_id => l_thing.id,
  p_site_id => l_thing.siteid,
  p_comment => 'Approved'
);

サブスクライバをWWSBR_EVENT_Qキューに追加する方法の例は、例16-10を参照してください。

サブスクライバの実行方法の例は、例16-11を参照してください。

16.8 例: 外部ワークフローの統合

組織では、ビジネス・プロセスを企業ポータルに統合する必要があることが数多くあります。Oracle Workflowの機能を使用して、組織に定義されているコンプライアンス・ルールに応じてあらゆるタイプの情報をルーティングするようにポータルを実装できます。CMEFを使用すると、従来のアプリケーション・ベースのワークフローとE-Business統合ワークフローの両方をOracle Portalコンテンツ管理システムに統合できます。

この項では、外部ワークフローをOracle Portalコンテンツ管理システムに統合する方法の例を示します。

16.8.1 ワークフローとOracle Portalの統合

Oracle Workflowは、Oracle Fusion MiddlewareおよびOracle E-Business Suiteのコンポーネントです。Oracle Workflowによって、内部ビジネス・プロセスの設計および中央リポジトリへの格納が可能になります。Oracle Workflowを使用して、様々なタイプのコンプライアンス義務に対応し、監査可能かつ反復可能なプロセスを設計し、事前に承認および制限を強制的に設定できます。Oracleの最新のコンプライアンス・ソリューションであるOracle Internal Controls Manager(Oracle ICM)は、Oracle Workflowと連携して内部ビジネス・プロセスを監視し、これらが設計どおりに実行されていることを確認するために使用されます。

通常、コンテンツの承認のためにOracle WorkflowをOracle Portalコンテンツ管理システムに統合する作業には次の5つの手順が含まれます。

  1. Oracle Portalで承認と通知を有効にします。

  2. ユーザーに「承認付きアイテムの管理」権限を付与します。

  3. アイテムを承認または却下するためにOracle Workflowプロセスによって使用されるポータル・ユーザーを作成し、このユーザーをポータル承認プロセスに追加します。

  4. このワークフロー・プロセスをOracle Workflowに登録します。このワークフロー・プロセスは、コンプライアンス・プロセスをコールするか、実際のコンプライアンス・プロセスを実行します。

  5. サブスクライバ・コードを作成し、CMEFイベントを処理するためこのサブスクライバをWWSBR_EVENT_Qに追加します。このサブスクライバは、ワークフロー・エンジンを初期化してから、ワークフロー・プロセスをコールします。

この流れを確認するには、16.7項「例: アイテム検証」で説明されているアイテム検証例を変更し、ワークフロー・プロセスをコールしてアイテム検証を実行します。

図16-7のダイアグラムに基づいて、このプロセスの流れを確認してください。

図16-7 WorkflowとOracle Portalの統合のプロセス・フロー

WorkflowとOracleAS Portalの統合のプロセス・フロー。
「図16-7 WorkflowとOracle Portalの統合のプロセス・フロー」の説明

16.8.2 例の概要

図16-7は、CMEFを使用してOracle WorkflowをOracle Portalコンテンツ管理システムに統合するためのプロセス・フローのダイアグラムを示します。「承認付きアイテムの管理」権限を持つユーザーがアイテムをポータルに追加すると、アイテムは保留中としてマークされます。例16-16のITEM_VALIDATIONサブスクライバと同様に、Oracle Streamsアドバンスト・キューイング・サブスクライバは、WWSBR_EVENT_Qキュー上でイベントをリスニングする必要があります(例16-17を参照)。イベントのタイプがSUBMIT_ITEM_FOR_APPROVALである場合、サブスクライバは、ワークフロー・エンジン・プロセスWF_CHECKURLを起動し、ポータル・アイテムのパラメータをワークフロー・プロセスに渡します。ワークフロー・プロセスは、外部PL/SQLプロシージャ(例16-18を参照)をコールし、そのビジネス・ロジックを実行します。この場合、ビジネス・ロジックには、ポータル・アイテムの承認または却下が含まれます。

URLが指定されている場合、Oracle Workflowは、wwsbr_api.approve APIを使用してアイテムを承認します。指定されていない場合は、wwsbr_api.reject APIを使用してアイテムを却下します。

この例では、次の前提条件が想定されています。

  • CMEFSAMPLESスキーマが、Portalスキーマと同じデータベースに存在しています。

  • Oracle OWF_MGRワークフロー・スキーマが、Portalスキーマと同じデータベースにインストールされています。

  • AQ_TM_PROCESSESパラメータが、5以上に設定されています。これをチェックするには、SYSユーザーとしてデータベースにログインし、次の問合せを実行します。

    select value
    from   v$parameter
    where  name = 'aq_tm_processes';
    

    この値が5未満である場合、次のように値を設定します。

    alter system set aq_tm_processes=5;
    
  • データベースを再起動します。

  • Oracle Portal 11gがインストールされています。

16.8.3 詳細な例の説明

「承認付きアイテムの管理」権限を持つポータル・ユーザーがアイテムをページに追加すると、SUBMIT_ITEM_FOR_APPROVALイベントがWWSBR_EVENT_Qキューに追加されます。このアイテムは、ポータル・ページ上で保留中としてマークされます。このユーザーのアイテムをページに表示するには、アイテムを承認する必要があります。

Streamsアドバンスト・キューイング・サブスクライバCMEF_WORKFLOWは、WWSBR_EVENT_Q上でイベントをリスニングします。イベントのタイプがSUBMIT_ITEM_FOR_APPROVALである場合、ワークフロー・エンジン・プロセスが起動され、ポータル・アイテムのパラメータがワークフロー・プロセスに渡されます。

ワークフロー・プロセスWF_CHECKURLは、そのビジネス・ロジックを実行します。この場合、ビジネス・ロジックにはポータル・アイテムの承認または却下が含まれます。WF_CHECKURLは、アイテムを承認または却下するためにビューおよびAPIを使用します。アイテムが承認されると、APPROVE_ITEMイベントがWWSBR_EVENT_Qに追加されます。アイテムが却下されると、REJECT_ITEMイベントがWWSBR_EVENT_Qに追加されます。

ページをリフレッシュすると、ページ上でアイテムが公開される(承認された場合)または削除される(却下された場合)ことを確認できます。

この例では、次の6つの手順が実行されます。

  1. 16.8.3.1項「Oracle Portalでの承認と通知の有効化」

  2. 16.8.3.2項「ユーザーへの「承認付きアイテムの管理」権限の付与」

  3. 16.8.3.3項「スクリプト(CMEFによるWorkflowの統合の例用)の実行」

  4. 16.8.3.4項「サブスクライバおよびチェック・プロシージャの作成」

  5. 16.8.3.5項「Oracle WorkflowへのWF_CHECKURLプロセスの登録」

  6. 16.8.3.6項「WWSBR_EVENT_QキューへのCMEF_WORKFLOWサブスクライバの追加」

これらの各手順の詳細は、次の各項を参照してください。

16.8.3.1 Oracle Portalでの承認と通知の有効化

最初に実行する手順は、ページ・グループで承認と通知を有効にすることです。

承認と通知を有効にする手順は、次のとおりです。

  1. ページ・グループの任意のページに移動し、「編集」モードに切り替えます。

  2. ページ上部のツールバーで、「ページ・グループ」の横にある「プロパティ」リンクをクリックします。


    注意:

    「ページ」の横にあるリンクではなく、「ページ・グループ」の横にあるリンクをクリックしてください(図16-2)。

  3. 「構成」タブをクリックして前面に表示します。

  4. 「承認と通知」セクションで、承認および通知が有効か無効かを確認できます。この設定を変更するには、「編集」リンクをクリックします(図16-8)。

    図16-8 ページ・グループの承認と通知のステータス

    ページ・グループの承認と通知のステータス。
    「図16-8 ページ・グループの承認と通知のステータス」の説明

  5. 承認と通知を有効にするには、「承認と通知を有効にする」チェック・ボックスを選択します(図16-9)。

    図16-9 ページ・グループの承認と通知の有効化または無効化

    このイメージは「承認と通知を有効にする」ページを示します。
    「図16-9 ページ・グループの承認と通知の有効化または無効化」の説明

  6. OK」をクリックして変更内容を保存します。

  7. 「閉じる」をクリックして、ページに戻ります。

16.8.3.2 ユーザーへの「承認付きアイテムの管理」権限の付与


注意:

ポータル・アイテムの承認または却下が外部ワークフロー・プロセスに不要な場合は、この手順をスキップできます。

次の手順は、アイテムの承認を必要とするすべてのユーザーに対して「承認付きアイテムの管理」権限を付与することです。この例では、すべてのユーザーがアイテムの承認を要求するように指定しています。

すべてのユーザーがアイテムの承認を要求するように指定する手順は、次のとおりです。

  1. ページ・グループの任意のページに移動し、「編集」モードに切り替えます。

  2. ページ上部のツールバーで、「ページ・グループ」の横にある「プロパティ」リンクをクリックします。


    注意:

    「ページ」の横にあるリンクではなく、「ページ・グループ」の横にあるリンクをクリックしてください(図16-2)。

  3. 「承認」タブをクリックして前面に表示します。

  4. 「すべてのユーザーに承認を要求する」チェック・ボックスを選択します(図16-10)。

    図16-10 すべてのユーザーがアイテムの承認を必要とする指定

    すべてのユーザーが承認を必要とします。
    「図16-10 すべてのユーザーがアイテムの承認を必要とする指定」の説明

  5. 「OK」をクリックします。

16.8.3.3 スクリプト(CMEFによるWorkflowの統合の例用)の実行

次の手順を実行する前に、実行する必要のあるタスクがいくつかあります。手順は次のとおりです。

  1. SYSスキーマにログインし、次のコマンドを実行します。

    GRANT EXECUTE ON owf_mgr.wf_engine to cmefsamples;
    
  2. Portalスキーマにログインし、provsyns.sqlを実行します。スキーマ/プロバイダ名を入力するよう求められるので、owf_mgrと入力します。

  3. CMEFSAMPLESスキーマにログインし、次を実行します。

    drop sequence WF_SEQ
    
    create sequence WF_SEQ
    increment by 1
    start with 1
    maxvalue 1000000000
    minvalue 1
    cache 20
    
    grant select on wf_seq to owf_mgr;
    

    これにより、ワークフローで必要とされる順序が作成され、順序に対する「SELECT」権限がOWF_MGRワークフロー・スキーマに付与されます。

  4. ワークフロー・スキーマにシノニムWF_ENGINEを作成します。

    create synonym wf_engine for owf_mgr.wf_engine;
    

16.8.3.4 サブスクライバおよびチェック・プロシージャの作成

承認を必要とするアイテムをユーザーが追加するまでWWSBR_EVENT_Qキューをリスニングするサブスクライバを作成する必要があります。このサブスクライバは、WF_CHECKURLワークフロー・プロセスをコールして、アイテム検証を実行し、電子メール通知を送信します。例16-17は、WORKFLOW_APPROVALサブスクライバのコードを示します。

例16-17 WORKFLOW_APPROVALサブスクライバ

create or replace procedure workflow_approval is
  MIME_TYPE_TEXT      constant varchar2(30) := 'text/plain';
  agent_list          dbms_aq.aq$_agent_list_t;
  wait_time           integer               := 30;
  begin_time          pls_integer;
  end_time            pls_integer;
  agent_w_message     aq$_agent;
  dequeue_options     dbms_aq.dequeue_options_t;
  message_properties  dbms_aq.message_properties_t;
  message_handle      raw(16);
  message             portal.wwsbr_event;
  l_subscriber        varchar2(30)          := 'CMEF_WORKFLOW';
  l_queue             varchar2(30)          := 'PORTAL.WWSBR_EVENT_Q';
  l_mode              binary_integer        := dbms_aq.REMOVE;
  l_attribute_site_id number                := 0;
  l_event             varchar2(30);
  l_doc               wwdoc_api.document_record;
  l_desc              varchar2(4000);
  l_itemkey           varchar2(100);
  l_job_nr            number;
  l_itemtype          varchar2(100)         := 'WF';
  l_wf_process        varchar2(100)         := 'WF_CHECKURL';
  l_is_indirect       boolean               := TRUE;
  l_portal_user_name  varchar2(30)          := 'portal';
  l_portal_password   varchar2(30)          := '<portal password>';
  l_url               varchar2(4000);       := '';

begin
  begin_time := dbms_utility.get_time;
  agent_list(1) := aq$_agent(l_subscriber, l_queue, null);
  loop
    -- Wait for messages.
    dbms_aq.listen(
      agent_list => agent_list,
      wait       => wait_time,
      agent      => agent_w_message
    );
    if (agent_w_message.name = l_subscriber) then
      dequeue_options.wait          := dbms_aq.NO_WAIT;
      dequeue_options.consumer_name := l_subscriber;
      dequeue_options.navigation    := dbms_aq.FIRST_MESSAGE;
      dequeue_options.dequeue_mode  := l_mode;
      dbms_aq.dequeue(
        queue_name         => l_queue,
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle
      );
      -- If the event is an ITEM INSERT event and marked for later publication.
        if ((message.action       = 'SUBMIT_ITEM_FOR_APPROVAL') and
            (message.object_class = 'ITEM') and
            (message.raw_event    = 'INSERT') and
            (message.state        = 'NOT_PUBLISHED') then
          portal.wwctx_api.set_context(l_portal_user_name, l_portal_password);
          -- Get the URL property for the object.
          select url
          into l_url
          from portal.wwsbr_all_items
          where id = message.object_id
          and caid = message.object_site_id;
          -- Get the nextval of the workflow sequence for the itemkey.
          select wf_seq.nextval
          into l_job_nr
          from dual;
          l_itemkey := lpad(to_char(l_job_nr), 5, '0');
          -- Launch the workflow engine process and pass the paramters for 
          -- the portal item to the workflow process.
          wf_engine.createprocess(l_itemtype, l_itemkey, l_wf_process);
          -- Set the value for the portal URL.
          wf_engine.setitemattrtext(l_itemtype, l_itemkey, 'PORTAL_URL', l__url);
          -- Set the value for the portal item ID.
          wf_engine.setitemattrnumber(l_itemtype, l_itemkey, 'PORTAL_ITEM_ID', message.object_id);
          -- Set the value for the portal page group ID.
          wf_engine.setitemattrnumber(l_itemtype, l_itemkey, 'PORTAL_SITE_ID', message.object_site_id);
          -- Start the workflow process.
          wf_engine.startprocess(l_itemtype, l_itemkey);
        end if;
    end if;
    end_time := dbms_utility.get_time;
    if (end_time - begin_time) > 3000 then
      exit;
    end if;
  end loop;
exception
  when OTHERS then
    dbms_output.put_line(sqlerrm);
end workflow_approval;
/

ユーザーがアイテムのファイル名を指定したかどうかをチェックし、アイテムが承認可能かどうかを判別するプロシージャも作成する必要があります。ワークフロー・プロセスは、アイテムの実際の検証および承認をこのCHECK_URLプロシージャに委任します。例16-18に、CHECK_URLプロシージャの作成方法を示します。

例16-18 CHECK_URLプロシージャ

create or replace procedure check_url(
  itemtype  in  varchar2,
  itemkey   in  varchar2,
  actid     in  number,
  funcmode  in  varchar2,
  resultout out varchar2) is

  MIME_TYPE_TEXT      constant varchar2(30) := 'text/plain';
  agent_list          dbms_aq.aq$_agent_list_t;
  wait_time           integer               := 30;
  begin_time          pls_integer;
  end_time            pls_integer;
  agent_w_message     aq$_agent;
  dequeue_options     dbms_aq.dequeue_options_t;
  message_properties  dbms_aq.message_properties_t;
  message_handle      RAW(16);
  message             portal.wwsbr_event;
  l_subscriber        varchar2(30)      := 'CMEF_WORKFLOW';
  l_queue             varchar2(30)      := 'PORTAL.WWSBR_EVENT_Q';
  l_mode              BINARY_INTEGER    := dbms_aq.REMOVE;
  l_attribute_site_id number            := 0;
  l_event             varchar2(30);
  l_doc               wwdoc_api.document_record;
  l_desc              varchar2(4000);
  l_itemtype          varchar2(100)    := 'WF';
  l_itemkey           varchar2(100);
  l_url               varchar2(100);
  l_siteid            number;
  l_itemid            number;
  l_ignore            boolean          := FALSE;
  l_is_indirect       boolean          := TRUE;
  l_portal_user_name  varchar2(30)     := 'portal';
  l_portal_password   varchar2(30)     := '<portal password>');
begin
  -- Get the values for the attributes stored in the procedure.
  l_url := wf_engine.getitemattrtext(itemtype,itemkey,'PORTAL_URL',l_ignore);
  l_itemid := wf_engine.getitemattrnumber(itemtype,itemkey,'PORTAL_ITEM_ID',l_ignore);
  l_siteid := wf_engine.getitemattrnumber(itemtype,itemkey,'PORTAL_SITE_ID',l_ignore);
  -- Set the portal context.
  portal.wwctx_api.set_context(l_portal_user_name, l_portal_password);
  -- If the item type is a URL item and no URL is specified.
  if l_url is null then
    begin
      -- Update the item to indicate that the URL needs to be specified.
      l_desc := '<font color=RED>NO URL SPECIFIED</font>';
      -- Reset the CMEF global variables.
      wwsbr_api.clear_cmef_context;
      wwsbr_api.set_attribute(
        p_site_id           => l_siteid,
        p_thing_id          => l_itemid,
        p_attribute_site_id => l_attribute_site_id,
        p_attribute_id      => wwsbr_api.attribute_description,
        p_attribute_value   => l_desc
        p_log_cmef_message  => FALSE
      );
      -- Reject the item.
      wwsbr_api.reject(
        p_item_id     => l_itemid,
        p_site_id     => l_siteid,
        p_is_indirect => l_is_indirect,
        p_comment     => 'Rejected'
      );
      -- Reset the CMEF global variables.
      wwsbr_api.clear_cmef_context;
    end;
  else
    -- Approve the item.
    begin
      wwsbr_api.approve(
        p_item_id => l_itemid,
        p_site_id => l_siteid,
        p_comment => 'Approved'
      );
      -- Reset the CMEF global variables.
      wwsbr_api.clear_cmef_context;
    end;
  end if;
  commit;
  -- Process cache invalidation messages.
  wwpro_api_invalidation.execute_cache_invalidation;
exception
  when OTHERS then
    dbms_output.put_line(sqlerrm);
end check_url;
/

注意:

CMEFSAMPLESは、WORKFLOW_APPROVALおよびCHECK_URLに対する実行権限をOWF_MGRに付与する必要があります。
grant execute on workflow_approval to owf_mgr;
grant execute on check_filename to owf_mgr;

16.8.3.5 Oracle WorkflowへのWF_CHECKURLプロセスの登録

WF_CHECKURLプロセスは、実際にポータル・アイテムを承認または却下し、電子メール通知を送信します。Oracle Workflow Builderを使用して、このプロセスをOracle Workflowに登録する必要があります(図16-11)。

図16-11 CHECK_FILE Oracle Workflowプロセス

Workflow BuilderのCHECK_FILE Oracle Workflowプロセス。
「図16-11 CHECK_FILE Oracle Workflowプロセス」の説明

次の手順を使用して、WF_CHECKURLプロセスをOWF_MGRスキーマにインストールします。

  1. Oracle Workflow Builderを開きます。


    ヒント:

    Workflow Builderのインストール後、ORACLE_HOME環境変数をWorkflow Builderの環境変数に設定する必要があるため、コマンドラインでの実行が必要となる場合があります。次に例を示します。
    set ORACLE_HOME=c:\oraclewf
    

  2. 新しいワークフロー・プロジェクトを開始します。

  3. ワークフロー・プロジェクトをwf_checkurl.wftとして保存します。

  4. Oracle Workflow Builderを閉じます。

  5. メモ帳などのテキスト・エディタでwf_checkurl.wftを開きます。

  6. WF_CHECKURLコードをコピーしてファイルに貼り付けます。このコードは、Portal Centerからダウンロードできます。

    http://www.oracle.com/technology/products/ias/portal/files/cm_overview_10g1014_cmef_samples.zip
    
  7. ファイルを保存してテキスト・エディタを閉じます。

  8. Oracle Workflow Builderでwf_checkurl.wftを開きます。

  9. OWF_MGRスキーマを使用して、wf_checkurl.wftをポータル・データベースに保存します。


    ヒント:

    OWF_MGRのパスワードがわからない場合、MetaLinkノート198800.1を参照してください。

16.8.3.6 WWSBR_EVENT_QキューへのCMEF_WORKFLOWサブスクライバの追加

次に、例16-19に示すように、CMEF_WORKFLOWサブスクライバをWWSBR_EVENT_Qキューに追加して、このサブスクライバがCMEFイベントを処理し、WF_CHECKURL Oracle Workflowプロセスをトリガーできるようにします。

例16-19 WWSBR_EVENT_QキューへのCMEF_WORKFLOWサブスクライバの追加

declare
  subscriber sys.aq$_agent;
begin
  1_subscriber := sys.aq$_agent('CMEF_WORKFLOW', null, null);
  dbms_aqadm.add_subscriber(
    queue_name => 'portal.wwsbr_event_q',
    1_subscriber => subscriber
  );
end;
/

「承認付きアイテムの管理」権限を持つユーザーがアイテムをページに追加すると、このアイテムは保留中としてマークされ、単一のINSERTイベント(状態は「NOT_PUBLISHED」)が発生します。

アクション イベント 状態 オブジェクト・クラス
SUBMIT_ITEM_FOR_APPROVAL INSERT NOT_PUBLISHED ITEM

CMEF_WORKFLOW_APPROVALサブスクライバは、このアクションに応答し、PORTAL_ITEM_WORKFLOW Oracle Workflowプロセスを起動します。

PORTAL_ITEM_APPROVAL Oracle Workflowプロセスは、そのビジネス・ロジックを実行し、Oracle Portalのapproveまたはreject APIをコールして、アイテムを承認または却下します。また、指定された電子メールIDに対して承認状態を示す電子メール通知も送信します。