この章では、Oracle Portalコンテンツ管理イベント・フレームワーク(CMEF)について説明します。内容は、次のとおりです。
CMEFを使用して、事前定義済ポータルのイベントに対しプログラム的なフックを追加することによって、Oracle Portalのコンテンツ管理機能を拡張できます。フレームワークは、これらのイベントをOracleデータベースのキューに公開します。これにより、サード・パーティのプログラムがこれらのイベントをサブスクライブし、APIを使用してポータルを拡張できるようになります。このようにして、ポータル内のページおよびアイテム関連のイベントを使用して、1つ以上の外部アプリケーション内のアクションをトリガーできます。
CMEFは、Oracle Streamsアドバンスト・キューイング(AQ)テクノロジを採用しています。Oracle Streams AQはOracleデータベース・コンポーネントであり、業界標準に準拠した豊富な機能セットを持つメッセージ・キュー・システムを提供します。Oracle Streams AQには、次の機能が用意されています。
アプリケーション(プロデューサ)がキューにメッセージを配置(エンキュー)するための複数の方法
アプリケーション(コンシューマ)がキューからメッセージを取得(デキュー)するための複数の方法
プロデューサ・アプリケーションがコンシューマ・アプリケーションに依存しない公開/サブスクライブ・モデル
様々なマシンおよびデータベース上のキュー間でのメッセージの伝播
メッセージを配信できない場合におけるメッセージの保証付き配信および例外処理
メッセージの永続的記憶域
メッセージの優先順位付け
有効期限や遅延など、メッセージの時間プロパティ

詳細は、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つの基本的なキューイング操作が含まれます。
メッセージのエンキュー: Oracle Portalは、WWSBR_EVENT_Qという名前のマルチコンシューマ・キューにメッセージを公開します(エンキューと呼ばれます)。このキューのメッセージには有効期限はありません。詳細は、16.2.1項「メッセージのエンキュー」を参照してください。
メッセージのデキュー: サブスクライブするアプリケーションが、キューからメッセージを取得します(デキューと呼ばれます)。詳細は、16.2.2項「サブスクライバおよびメッセージのデキュー」を参照してください。
例外処理: メッセージが指定時間内に指定試行回数内で消費された場合、メッセージは正常に処理されたことになります。正常に消費されなかったメッセージは、例外キューと呼ばれる別のキューに格納されます。詳細は、16.2.3項「例外処理」を参照してください。
メッセージのリスニング: アプリケーションは、LISTENを使用して、キューを繰り返しポーリングしなくても複数のサブスクリプションに対するメッセージを待機できます。詳細は、16.2.4項「メッセージのリスニング」を参照してください。
通知: このOracle Streams AQ機能を使用して、ユーザーまたはクライアントは、目的のメッセージの通知を受信できます。詳細は、Oracle Streams AQのドキュメントを参照してください。
キューイング操作を実行するには、DBMS_AQパッケージを使用します。
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によって作成されたメッセージには有効期限がありません。
消費側であるサブスクライバには、CMEFによって作成されたメッセージを消費するために様々なメカニズムが用意されています。サブスクライバはメッセージが到着したときにメッセージを処理できるので、メッセージが到着するまで待機する必要があります。また、サブスクライバは、メッセージの到着時に通知を受けることもできます。これらの通知には、Oracle Call Interface (OCI)、コールバック・ファンクション、PL/SQLファンクションまたは電子メールがあります。
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項「サブスクライバ・コードの作成」を参照してください。
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-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イベントをデキューする必要はありません。 |
すべての対象となるコンシューマによってメッセージが正常にデキューされると、メッセージは処理されたとみなされます。なんらかの理由によってメッセージが処理されない場合、メッセージは例外キューに移動されます。
1つ以上のコンシューマが有効期限前にメッセージをデキューできない場合、メッセージは期限切れとみなされます。期限切れのメッセージも例外キューに移動されます。例外キューは、すべての期限切れのメッセージまたは使用できないメッセージが格納されるリポジトリです。
アプリケーションがメッセージを例外キューに直接エンキューすることはできません。また、例外キューにサブスクライバを関連付けることもできません。ただし、これらの期限切れのメッセージまたは使用できないメッセージを処理するアプリケーションは、例外キューからメッセージをデキューする必要があります。
CMEF例外は、WWSBR_EVENT_ERR_Q例外キューに送信されます。WWSBR_EVENT_Qマルチコンシューマ・キューの期限切れメッセージを、メッセージの対象となる受信者がデキューすることはできません。ただし、デキュー・オプションにNULLコンシューマ名を指定することにより、これらのメッセージがREMOVEモードになるとデキューできます。キュー・モニターは、マルチコンシューマ・キューから期限切れメッセージを削除します。これにより、デキュー元は、キュー表のメッセージをロックせずにデキュー操作を完了できます。
キュー・モニターは、すべてのコンシューマによって処理されたメッセージをマルチコンシューマ・キューから定期的に削除するので、ユーザーには、メッセージが完全に処理されたときと、メッセージがキューから物理的に削除されるときの間に遅延があるように見えることがあります。
|
注意: WWSBR_EVENT_ERR_Q例外キューは、すべての例外キューと同様に単一コンシューマ・キューです。 |
Oracle Streams AQは、1回の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;
/
すべてのポータル・アイテムおよびページ・アクションは、WWSBR_EVENT_QキューにエンキューされるCMEFメッセージを生成します。サブスクライバは、このメッセージに含まれる情報を利用し、Oracle Portal PL/SQL APIを使用して様々なアクションを実行できます。
CMEFイベントの処理には次の3つの基本ステップがあります。各ステップについてこの項で説明します。手順は次のとおりです。
また、この項では、メッセージのペイロードについて説明し、次に一般的なポータル・アクションとアクションによって生成されるイベントの例も示します。
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-6に示すように、CMEFイベント・メッセージを処理するには、サブスクライバをWWSBR_EVENT_Qキューに追加する必要があります。
Oracle Portalでは、CMEFはページ・グループ・レベルで有効化または無効化されます。デフォルトでは、ユーザーがページ・グループを作成するとCMEFが有効化され、Oracle Portalユーザー・インタフェースまたはWebDAVで変更が行われるたびにイベントがトリガーされます。
ページ・グループに対してCMEFを有効化または無効化する手順は、次のとおりです。
ページ・グループの任意のページに移動し、「編集」モードに切り替えます。
ページ上部のツールバーで、「ページ・グループ」の横にある「プロパティ」リンクをクリックします。
「構成」タブをクリックして前面に表示します。
「コンテンツ管理イベント・フレームワーク」セクションで、CMEFが有効か無効かを確認できます。この設定を変更するには、「編集」リンクをクリックします(図16-3)。
CMEFを有効にするには、「コンテンツ管理イベント・フレームワークを有効にする」チェック・ボックスを選択します(図16-1)。CMEFを無効にするには、チェック・ボックスの選択を解除します。
「OK」をクリックして変更内容を保存します。
「閉じる」をクリックして、ページに戻ります。
CMEFのイベントのページ(図16-5)を使用して、WWSBR_EVENTS_Qキューに追加されているサブスクライバを調査します。
CMEFのイベントのページにアクセスする手順は、次のとおりです。
Portalスキーマの所有者としてポータルにログインします。
ブラウザの「アドレス」フィールドに次の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スキーマの所有者のみです。 |
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) |
このメッセージによって参照されるポータル・オブジェクトへの一意の不変識別子。ページ、アイテム、カテゴリ、パースペクティブ、アイテム・タイプおよびページ・タイプに対してのみ使用されます。 |
この項では、最も一般的なポータル・アクションについて説明し、これらのアクションを検出するためのコードをサブスクライバに含める方法を示します。これらのアクションは、Oracle Portalユーザー・インタフェース、Oracle Portal PL/SQL APIまたはWebDAVを介して実行されます。
ポータル・アクションとアクションによって生成されるイベントおよびメッセージ・ペイロードの詳細なリストは、付録G「コンテンツ管理イベント・フレームワークのイベント」を参照してください。
Oracle Portalでは、ポータルは、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;
ページ・グループの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 |
ユーザーまたはグループを追加または削除し、ページ・グループのアクセス制御リスト(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」をクリックしたときに生成されます。 |
アイテムは、ポータル・ページの基本的なコンポーネントの1つです。ポータルのアイテムは、アイテム・タイプをベースとしています。ただし、アイテムに対するアクションは、アイテム・タイプとは関係なくCMEFイベントをトリガーします。
たとえば、ADD_ITEMアクションは、ユーザーが基本、拡張またはカスタムの各アイテム・タイプのアイテムを追加するたびに発生します。これにより、アイテムのアクションが発生する場合に、一貫性のあるCMEFメッセージ動作が行われるようになります。
ユーザーが「管理」権限を持っている場合、ページで任意のタイプのアイテムを作成すると、次のメッセージ・ペイロードが作成されます。
| アクション | イベント | 状態 | オブジェクト・クラス |
|---|---|---|---|
|
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;
ページ(またはページ・グループ)、および「承認付きアイテムの管理」権限を持つユーザーに対して承認および通知が有効である場合、ページにアイテムを追加すると、次のメッセージ・ペイロードが作成されます。
| アクション | イベント | 状態 | オブジェクト・クラス |
|---|---|---|---|
|
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;
アイテムを承認すると、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 |
アイテムに異なるカテゴリまたはパースペクティブを適用すると、アイテムの編集時と同じメッセージ・ペイロードが作成されます。
| アクション | イベント | 状態 | オブジェクト・クラス |
|---|---|---|---|
|
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;
削除されるアイテムが保持される(すなわち、アイテムは削除としてマークされているが、実際には削除されない)ページ・グループからアイテムを削除すると、次のメッセージ・ペイロードが作成されます。
| アクション | イベント | 状態 | オブジェクト・クラス |
|---|---|---|---|
|
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;
次のいくつかの項にある例をデプロイし使用する場合は、CMEFSAMPLESという名前の別のスキーマに作成することをお薦めします。このスキーマを作成する手順は、次のとおりです。
データベース・スキーマ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;
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);
Oracle Portal PL/SQL APIをコールする権限をCMEFSAMPLESスキーマに付与します。この方法の詳細は、9.3項「APIおよびセキュア・ビューへのアクセスの提供」を参照してください。
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;
CMEFSAMPLESスキーマにログインし、次を実行します。
sqlplus cmefsamples/<password> create synonym aq$_agent for sys.aq$_agent;

次の例のコードをOTNからダウンロードできます。
http://www.oracle.com/technology/products/ias/portal/files/cm_overview_10g1014_cmef_samples.zip
例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) )
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メッセージ・ペイロードを示します。
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-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を取得する |

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=us-ascii' || 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-16のitem_valication 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を参照してください。
組織では、ビジネス・プロセスを企業ポータルに統合する必要があることが数多くあります。Oracle Workflowの機能を使用して、組織に定義されているコンプライアンス・ルールに応じてあらゆるタイプの情報をルーティングするようにポータルを実装できます。CMEFを使用すると、従来のアプリケーション・ベースのワークフローとE-Business統合ワークフローの両方をOracle Portalコンテンツ管理システムに統合できます。
この項では、外部ワークフローをOracle Portalコンテンツ管理システムに統合する方法の例を示します。
Oracle Workflowは、Oracle Application ServerおよびOracle E-Business Suiteのコンポーネントであり、Oracle Workflowによって、内部ビジネス・プロセスの設計および中央リポジトリへの格納が可能になります。Oracle Workflowを使用して、様々なタイプのコンプライアンス義務に対応し、監査可能かつ反復可能なプロセスを設計し、事前に承認および制限を強制的に設定できます。Oracleの最新のコンプライアンス・ソリューションであるOracle Internal Controls Manager (Oracle ICM)は、Oracle Workflowと連携して内部ビジネス・プロセスを監視し、これらが設計どおりに実行されていることを確認するために使用されます。
通常、コンテンツの承認のためにOracle WorkflowをOracle Portalコンテンツ管理システムに統合する作業には次の5つの手順が含まれます。
Oracle Portalで承認と通知を有効にします。
ユーザーに「承認付きアイテムの管理」権限を付与します。
アイテムを承認または却下するためにOracle Workflowプロセスによって使用されるポータル・ユーザーを作成し、このユーザーをポータル承認プロセスに追加します。
このワークフロー・プロセスをOracle Workflowに登録します。このワークフロー・プロセスは、コンプライアンス・プロセスをコールするか、実際のコンプライアンス・プロセスを実行します。
サブスクライバ・コードを作成し、CMEFイベントを処理するためこのサブスクライバをWWSBR_EVENT_Qに追加します。このサブスクライバは、ワークフロー・エンジンを初期化してから、ワークフロー・プロセスをコールします。
この流れを確認するには、16.7項「例: アイテム検証」で説明されているアイテム検証例を変更し、ワークフロー・プロセスをコールしてアイテム検証を実行します。
図16-7のダイアグラムに基づいて、このプロセスの流れを確認してください。
図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がインストールされています。
「承認付きアイテムの管理」権限を持つポータル・ユーザーがアイテムをページに追加すると、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つの手順が実行されます。
これらの各手順の詳細は、次の各項を参照してください。
最初に実行する手順は、ページ・グループで承認と通知を有効にすることです。
承認と通知を有効にする手順は、次のとおりです。
|
注意: ポータル・アイテムの承認または却下が外部ワークフロー・プロセスに不要な場合は、この手順をスキップできます。 |
次の手順は、アイテムの承認を必要とするすべてのユーザーに対して「承認付きアイテムの管理」権限を付与することです。この例では、すべてのユーザーがアイテムの承認を要求するように指定しています。
すべてのユーザーがアイテムの承認を要求するように指定する手順は、次のとおりです。
ページ・グループの任意のページに移動し、「編集」モードに切り替えます。
ページ上部のツールバーで、「ページ・グループ」の横にある「プロパティ」リンクをクリックします。
「承認」タブをクリックして前面に表示します。
「すべてのユーザーに承認を要求する」チェック・ボックスを選択します(図16-10)。
「OK」をクリックします。
次の手順を実行する前に、実行する必要のあるタスクがいくつかあります。手順は次のとおりです。
SYSスキーマにログインし、次のコマンドを実行します。
GRANT EXECUTE ON owf_mgr.wf_engine to cmefsamples;
Portalスキーマにログインし、provsyns.sqlを実行します。スキーマ/プロバイダ名を入力するよう求められるので、owf_mgrと入力します。
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ワークフロー・スキーマに付与されます。
ワークフロー・スキーマにシノニムWF_ENGINEを作成します。
create synonym wf_engine for owf_mgr.wf_engine;
承認を必要とするアイテムをユーザーが追加するまで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; |
WF_CHECKURLプロセスは、実際にポータル・アイテムを承認または却下し、電子メール通知を送信します。Oracle Workflow Builderを使用して、このプロセスをOracle Workflowに登録する必要があります(図16-11)。
次の手順を使用して、WF_CHECKURLプロセスをOWF_MGRスキーマにインストールします。
Oracle Workflow Builderを開きます。
|
ヒント: Workflow Builderのインストール後、ORACLE_HOME環境変数をWorkflow Builderの環境変数に設定する必要があるため、コマンドラインでの実行が必要となる場合があります。例: set ORACLE_HOME=c:\oraclewf |
新しいワークフロー・プロジェクトを開始します。
ワークフロー・プロジェクトをwf_checkurl.wftとして保存します。
Oracle Workflow Builderを閉じます。
メモ帳などのテキスト・エディタでwf_checkurl.wftを開きます。
WF_CHECKURLコードをコピーしてファイルに貼り付けます。このコードは、Portal Centerからダウンロードできます。
http://www.oracle.com/technology/products/ias/portal/files/cm_overview_10g1014_cmef_samples.zip
ファイルを保存してテキスト・エディタを閉じます。
Oracle Workflow Builderでwf_checkurl.wftを開きます。
OWF_MGRスキーマを使用して、wf_checkurl.wftをポータル・データベースに保存します。
|
ヒント: OWF_MGRのパスワードがわからない場合、MetaLinkノート198800.1を参照してください。 |
次に、例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に対して承認状態を示す電子メール通知も送信します。