サブスクリプションの操作
Subscription オブジェクトには、EventAction オブジェクトと、EventAction オブジェクトが参照するユーザー実装のイベント・アクション・ハンドラーが必要です。EventAction オブジェクトとイベント・アクション・ハンドラーがまだない場合は、まずオブジェクトとハンドラーを作成してから、Subscription オブジェクトを関連付けます。以降のトピックではこの手順を説明します。
Subscription オブジェクトを取得して、このオブジェクトのプロパティーとアクセス権限を設定および取得することもできます。以下のトピックでは、取得したサブスクリプションを使用する一般的な状況に対応するコーディング方法を示します。
システム・イベントに加えて、カスタム・イベントをサブスクリプションに追加できます。以下のトピックに示すように、クライアント・アプリケーションでは、手動でカスタム・イベントを発生させて、イベント・アクション・ハンドラーを開始する必要があります。 クライアントは、カスタム・イベントの状況を設定することにより、状態をイベント・アクション・ハンドラーに伝達することもできます。
サブスクリプションが開始すると、そのサブスクリプションの EventAction オブジェクトが保留中のアクションとして Content Engine キューに入れられます (非同期で動作するように構成されている場合)。 保留中のアクションをモニターして、失敗したアクションがある場合は、修正し、キューから再起動できます。「オブジェクト・ストアからのキュー・アイテムの取得」を参照してください。
サブスクリプションの概要については、『Subscriptions』を参照してください。
イベント・アクション・ハンドラーの作成
イベント・アクション・ハンドラーを作成するには、Java™ EventActionHandler インターフェースまたは RetrievalEventActionHandler インターフェースの onEvent メソッドを実装する必要があります。イベント・アクション・ハンドラーを実装する際には、以下の点に注意してください。
- Content Engine は、デフォルトのコンストラクターを使用してイベント・アクション・ハンドラー・オブジェクトを作成します。カスタムのコンストラクターは使用しないでください。
- イベント・アクション・ハンドラーが発行または再発行操作によって開始される場合、そのハンドラーの開始にはサブスクリプションは含まれません。したがって、ハンドラーに渡されるサブスクリプション Id オブジェクトの値は null になります。発行によって呼び出されるハンドラーは、null サブスクリプション値をエラーとして扱いません。
以下の例に、新しいフォーム・ドキュメントを表示するハンドラーの Java 実装と JavaScript 実装を示します。FloodClaim クラスのフォームは、NOL グループに属するユーザー用の特別なフォルダーにファイリングされます。このハンドラーは ClassSubscription オブジェクトを対象にしています。そのオブジェクトでは、サブスクリプション付きイベントは CreationEvent で、ターゲット・オブジェクトは FloodClaim クラスです。ユーザーが新規フォームを作成し、そのクラス・タイプを FloodClaim に設定すると、ハンドラーが実行されます。ObjectChangeEvent サブオブジェクトは CreationEvent オブジェクトであり、イベントのソース・オブジェクトは FloodClaim クラスの任意のフォーム・ドキュメントです。このシナリオに適用できるクラス・サブスクリプションを作成するサンプル・コードについては、「Subscription オブジェクトの作成」を参照してください。
- Windows: C:¥Program Files¥Filenet¥Content Engine¥samples
- Windows 以外: /opt/IBM/FileNet/ContentEngine/samples
Java の例
package sample.actionhandler;
import java.util.Iterator;
import com.filenet.api.engine.EventActionHandler;
import com.filenet.api.events.*;
import com.filenet.api.property.*;
import com.filenet.api.security.*;
import com.filenet.api.util.Id;
import com.filenet.api.exception.*;
import com.filenet.api.core.*;
import com.filenet.api.collection.GroupSet;
import com.filenet.api.constants.*;
public class FilterNewDocumentsEventHandler implements EventActionHandler
{
public void onEvent(ObjectChangeEvent event, Id subId)
{
try
{
// As a best practice, fetch the persisted source object of the event,
// filtered on the two required properties, Owner and Name.
ObjectStore os = event.getObjectStore();
Id id = event.get_SourceObjectId();
FilterElement fe = new FilterElement(null, null, null, "Owner Name", null);
PropertyFilter pf = new PropertyFilter();
pf.addIncludeProperty(fe);
Document doc = Factory.Document.fetchInstance(os, id, pf);
User user = Factory.User.fetchInstance(os.getConnection(), doc.get_Owner(), null);
GroupSet groups = user.get_MemberOfGroups();
Iterator groupsIter = groups.iterator();
while (groupsIter.hasNext())
{
Group group = (Group) groupsIter.next();
if ( group.get_ShortName().equals("NOL") )
{
Folder folder=Factory.Folder.fetchInstance(os, "/Special Processing", null);
// File form and save.
DynamicReferentialContainmentRelationship drcr =
(DynamicReferentialContainmentRelationship)folder.file((IndependentlyPersistableObject)doc,
AutoUniqueName.AUTO_UNIQUE,
doc.getProperties().getStringValue("Name"),
DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
drcr.save(RefreshMode.NO_REFRESH);
break;
}
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
JavaScript の例
importPackage(java.lang);
importClass(java.util.Iterator);
importClass(Packages.com.filenet.api.engine.EventActionHandler);
importClass(Packages.com.filenet.api.collection.GroupSet);
importClass(Packages.com.filenet.api.util.Id);
importPackage(Packages.com.filenet.api.events);
importPackage(Packages.com.filenet.api.property);
importPackage(Packages.com.filenet.api.security);
importPackage(Packages.com.filenet.api.core);
importPackage(Packages.com.filenet.api.constants);
function onEvent(event, subId){
try {
// As a best practice, fetch the persisted source object of the event,
// filtered on the two required properties, Owner and Name.
var os=event.getObjectStore();
var id=event.get_SourceObjectId();
var fe=new FilterElement(null,null,null,"Owner Name",null);
var pf=new PropertyFilter();
pf.addIncludeProperty(fe);
var doc = Factory.Document.fetchInstance(os,id, pf);
var user=Factory.User.fetchInstance(os.getConnection(), doc.get_Owner(),null);
var groups=user.get_MemberOfGroups();
var groupsIter=groups.iterator();
while (groupsIter.hasNext())
{
var group = groupsIter.next();
if( group.get_ShortName().equals("NOL") )
{
var folder = Factory.Folder.fetchInstance(os, "/Special Processing", null);
//File form and save.
var drcr =
folder.file(doc, AutoUniqueName.AUTO_UNIQUE,
doc.getProperties().getStringValue("Name"),
DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
drcr.save(RefreshMode.NO_REFRESH);
break;
}
}
}
catch ( e) {
throw new RuntimeException(e);
}
}
EventAction オブジェクトの作成
EventAction オブジェクトは、サブスクライブ済みイベントのトリガー時に開始されるイベント・アクション・ハンドラーを識別します。EventAction オブジェクトの作成方法、およびこのオブジェクトをイベント・アクション・ハンドラーに関連付けるプロパティー (ProgId、および条件によっては CodeModule) の設定方法を、次の Java および C# のコードの一部に示します。Java で実装されたハンドラーの場合、ProgId プロパティーに、ハンドラー・クラスの完全修飾名を設定する必要があります。例に示すように、イベント・アクション・ハンドラーがオブジェクト・ストアに格納された CodeModule に含まれている場合は、CodeModule オブジェクトも取得し、このオブジェクトを EventAction オブジェクトの CodeModule プロパティーに割り当てる必要があります。CodeModule プロパティーを CodeModule の予約 (実行中) バージョンに設定することはできません。詳細については、「CodeModule オブジェクトの作成」を参照してください。
EventAction オブジェクトは、保存すると、Content Engine オブジェクト・ストアの Events フォルダーまたは Event Action フォルダーに保管されます。
Java の例
...
//Create event action.
EventAction eventAction = Factory.EventAction.createInstance(os, null);
// ハンドラー・クラスの完全修飾名を指定して ProgId プロパティーを設定する
eventAction.set_ProgId("sample.actionhandler.FilterNewDocumentsEventHandler");
// CodeModule オブジェクトを取得する。
CodeModule cm = Factory.CodeModule.fetchInstance(os, new Id("{E6C739B5-0EEB-43E1-B1FB-D6BC74F80EAC}"), null);
// ハンドラー・クラスをオブジェクト・ストアにチェックインする場合は、CodeModule プロパティーを設定する。
eventAction.set_CodeModule(cm);
eventAction.set_DisplayName("FilterNewDocumentsEventAction");
eventAction.save(RefreshMode.REFRESH);
C# の例
...
// Create event action.
IEventAction eventAction = Factory.EventAction.CreateInstance(os, null);
// ハンドラー・クラスの完全修飾名を指定して ProgId プロパティーを設定する
eventAction.ProgId = "sample.actionhandler.FilterNewDocumentsEventHandler";
// CodeModule オブジェクトの取得
ICodeModule cm = Factory.CodeModule.FetchInstance(os, new Id("{E6C739B5-0EEB-43E1-B1FB-D6BC74F80EAC}"), null);
// CodeModule プロパティーの設定
eventAction.CodeModule = cm;
eventAction.DisplayName = "FilterNewDocumentsEventAction";
eventAction.Save(RefreshMode.REFRESH);
サブスクリプション・オブジェクトの作成
イベント・アクション・ハンドラーと EventAction オブジェクトを作成したら、次に Subscription オブジェクトを作成し、オブジェクト・ストアに永続化できます。さまざまなサブスクリプションの種類がありますが、Subscription オブジェクトの作成プロセスは、ほぼ同じです。サブスクリプションの種類を定義し、プロパティー (実行するイベント・アクション、サブスクリプションのターゲット・オブジェクト、およびサブスクリプション付きイベント) を設定します。サブスクリプション付きイベントがターゲット・オブジェクト上で起動されると、イベント・アクションが呼び出されます。
以下の Java および C# の例では、ClassSubscription タイプのサブスクリプションの作成方法を示します。指定したクラスのオブジェクトでイベントがトリガーされると、クラス・サブスクリプションが起動されます。 この例では、サブスクリプションのターゲットは Document クラスのサブクラスであり、DocumentClassDefinition オブジェクトによって表されます。サブスクリプション付きイベントは CreationEvent です。このため、Document サブクラスのオブジェクトを作成すると必ず、イベント・アクションが実行されます。ただし、サブクラスの子クラスがある場合、IncludeSubclassesRequested プロパティーの設定に従って、子クラスはサブスクリプションから明示的に除外されます。
サブスクリプション内のイベントは、SubscribedEvent オブジェクトによって表されます。例に示すように、オブジェクトの EventClass プロパティーを、イベントを識別する EventClassDefinition オブジェクトとともに設定します。次に、SubscribedEvent オブジェクトを SubscribedEventList コレクションに追加し、サブスクリプションの SubscribedEvents プロパティーをこのコレクションに設定します。
サブスクリプションは、保存すると、Content Engine のオブジェクト・ストアの Events フォルダーまたは Subscription フォルダーに保管されます。
Java の例
// クラス・サブスクリプションを作成する
ClassSubscription subscription = Factory.ClassSubscription.createInstance(os, null);
// クラス・サブスクリプションのターゲットは、ID オブジェクトによって識別される
// identified by the ID object.
DocumentClassDefinition docCD=Factory.DocumentClassDefinition.getInstance(
os, new Id("{B19C39FD-9E71-4E56-8D7E-9B036B3B903B}") );
subscription.set_SubscriptionTarget(docCD);
// ターゲット・クラスのサブクラスを除外する
subscription.set_IncludeSubclassesRequested(Boolean.FALSE);
// 前の例で作成した EventAction オブジェクトを取得して、
// and set subscription's EventAction property.
EventAction eventAction = Factory.EventAction.fetchInstance(os,
new Id("{F1C9ACE3-8454-4B2C-9AC4-30228FAA8113}"), null);
subscription.set_EventAction(eventAction);
// 発生したらサブスクリプションを呼び出すイベントを 1 つ以上指定する。
// イベントをリストに追加して、サブスクリプション・オブジェクトを設定する。
Id subscribedEventId = GuidConstants.Class_CreationEvent;
EventClassDefinition evDef = Factory.EventClassDefinition.getInstance(os, subscribedEventId);
SubscribedEvent subEvent = Factory.SubscribedEvent.createInstance();
subEvent.set_EventClass(evDef);
SubscribedEventList subEventList = Factory.SubscribedEvent.createList();
subEventList.add(subEvent);
subscription.set_SubscribedEvents(subEventList);
// イベント・ハンドラーの同期実行を指定する
subscription.set_IsSynchronous(Boolean.TRUE);
subscription.set_DisplayName("FileDocumentSubscription");
subscription.save(RefreshMode.REFRESH);
C# の例
// クラス・サブスクリプションを作成する
IClassSubscription subscription = Factory.ClassSubscription.CreateInstance(os, null);
// クラス・サブスクリプションのターゲットは、ID オブジェクトによって識別される
// identified by the ID object.
IDocumentClassDefinition docCD = Factory.DocumentClassDefinition.GetInstance(
os, new Id("{B19C39FD-9E71-4E56-8D7E-9B036B3B903B}") );
subscription.SubscriptionTarget = docCD;
// ターゲット・クラスのサブクラスを除外する
subscription.IncludeSubclassesRequested= false;
// 前の例で作成した EventAction オブジェクトを取得して、
// and set subscription's EventAction property.
IEventAction eventAction = Factory.EventAction.FetchInstance(
os, new Id("{F1C9ACE3-8454-4B2C-9AC4-30228FAA8113}"), null);
subscription.EventAction = eventAction;
// 発生したらサブスクリプションを呼び出すイベントを
// 1 つ以上指定する。
// イベントをリストに追加して、サブスクリプション・オブジェクトを設定する。
Id subscribedEventId = GuidConstants.Class_CreationEvent;
IEventClassDefinition evDef = Factory.EventClassDefinition.GetInstance(
os, subscribedEventId);
ISubscribedEvent subEvent = Factory.SubscribedEvent.CreateInstance();
subEvent.EventClass = evDef;
ISubscribedEventList subEventList = Factory.SubscribedEvent.CreateList();
subEventList.Add(subEvent);
subscription.SubscribedEvents = subEventList;
// イベント・ハンドラーの同期実行を指定する
subscription.IsSynchronous = true;
subscription.DisplayName = "FileDocumentSubscription";
subscription.Save(RefreshMode.REFRESH);
サブスクリプションの取得
Subscription オブジェクトを 1 つだけを取得するには Factory メソッドを使用します。Subscription オブジェクトのコレクション (SubscriptionSet) を取得するには、EventAction または ObjectStore オブジェクトで Subscriptions プロパティーを取得します。また、WorkflowDefinition オブジェクトの WorkflowSourceSubscriptions プロパティーを使用して SubscriptionSet を返すこともできます。
オブジェクト・ストア内にあるすべてのサブスクリプションの取得を使用する状況の 1 つとして、特定のオブジェクトがサブスクリプションのターゲットであるときに、その元のサブスクリプションをすべて取得する場合があります。ObjectStore オブジェクトから SubscriptionSet コレクションを取得し、サブスクリプションのターゲットが特定の Document オブジェクトであるサブスクリプションの検索を、このコレクションに対して反復処理する方法を、次の Java および C# の例に示します。
Java の例
// Document オブジェクトを取得して、Document オブジェクトがサブスクリプションの
// Document object is the target object of the subscriptions.
Document doc = Factory.Document.getInstance(
os, "Document", new Id("{5B80C0B6-8EE3-430D-BE20-C461842326F8}"));
// ArrayList オブジェクトを初期化して、Document オブジェクトが
// in which Document object is the target of the subscriptions.
ArrayList targetFound = new ArrayList();
// オブジェクト・ストアからすべてのサブスクリプションを取得する
SubscriptionSet subscriptions = os.get_Subscriptions();
// SubscriptionSet を繰り返し、指定された Document オブジェクトに
// 一致するサブスクリプション・ターゲットを取得する。
// 一致するたびに、サブスクリプションを ArrayList オブジェクトに追加する。
Iterator subcriptionsIter = subscriptions.iterator();
while (subcriptionsIter.hasNext())
{
Subscription subscription = (Subscription) subcriptionsIter.next();
Subscribable subObject = subscription.get_SubscriptionTarget();
if (subObject.equals(doc))
{
targetFound.add(subscription);
}
}
// ArrayList オブジェクトを繰り返し、Document オブジェクトがサブスクリプションのターゲット・オブジェクトである
// in which Document object is the target object of the subscription.
Iterator pi = targetFound.iterator();
while (pi.hasNext())
{
Subscription subscription = (Subscription)pi.next();
System.out.println(subscription.get_Name());
}
C# の例
// Document オブジェクトを取得して、Document オブジェクトがサブスクリプションの
// Document object is the target object of the subscriptions.
IDocument doc = Factory.Document.GetInstance
(os, "Document", new Id("{5B80C0B6-8EE3-430D-BE20-C461842326F8}"));
// ArrayList オブジェクトを初期化して、Document オブジェクトが
// in which Document object is the target of the subscriptions.
ArrayList targetFound = new ArrayList();
// オブジェクト・ストアからすべてのサブスクリプションを取得する
ISubscriptionSet subscriptions = os.Subscriptions;
// SubscriptionSet を繰り返し、指定された Document オブジェクトに
// 一致するサブスクリプション・ターゲットを取得する。
// 一致するたびに、サブスクリプションを ArrayList オブジェクトに追加する。
foreach (ISubscription subscription in subscriptions)
{
ISubscribable subObject = subscription.SubscriptionTarget;
if (subObject.Equals(doc))
{
targetFound.Add(subscription);
}
}
// ArrayList オブジェクトを繰り返し、Document オブジェクトがサブスクリプションのターゲット・オブジェクトである
// in which Document object is the target object of the subscription.
foreach (ISubscription subscription in targetFound)
{
System.Console.WriteLine(subscription.Name);
}
詳細については、ワークフロー・サブスクリプションの取得を参照してください。
サブスクリプション付きイベントの既存のサブスクリプションへの追加
Subscription オブジェクトの SubscribedEvents プロパティーには、サブスクリプションのサブスクリプション先イベントのコレクションが格納されています。次の Java および C# の例は、既存のサブスクリプションを取得し、そのサブスクリプションに現在割り当てられているサブスクリプション付きイベントの表示名を出力します。次に、サブスクリプションにシステム・イベントとカスタム・イベントの 2 つの新規イベントが追加されます。重複するイベント型を SubscribedEvents プロパティーに追加すると、EVENT_DUPLICATE_LIST_SUBSCRIBED_EVENT 例外がスローされます。 サブスクリプションに既に割り当てられているイベント型の追加は無視されます。
Java の例
// 既存のサブスクリプションを取り出すためにプロパティー・フィルターをセットアップする
FilterElement fe = new FilterElement(null, null, null,PropertyNames.SUBSCRIBED_EVENTS);
PropertyFilter pf = new PropertyFilter();
pf.addIncludeProperty(fe);
Subscription subscription = Factory.Subscription.fetchInstance(os,
new Id("{AB264E14-2D28-46F1-9215-783952A61897}"), pf);
// サブスクリプションの既存のサブスクライブ済みイベントの名前を取得して表示する
SubscribedEventList subEvents = subscription.get_SubscribedEvents();
Iterator subEventsIter = subEvents.iterator();
System.out.println("Subscribed events before additions:");
while (subEventsIter.hasNext())
{
SubscribedEvent existingEvent = (SubscribedEvent) subEventsIter.next();
System.out.println(existingEvent.get_EventClass().get_DisplayName());
}
// システムのサブスクライブ済みイベントを作成し、それをサブスクライブ済みイベントの集合に追加する
Id subscribedEventId = GuidConstants.Class_CancelCheckoutEvent;
EventClassDefinition evDef = Factory.EventClassDefinition.getInstance(
os, subscribedEventId);
SubscribedEvent newEvent1 = Factory.SubscribedEvent.createInstance();
newEvent1.set_EventClass(evDef);
subEvents.add(newEvent1);
// カスタムのサブスクライブ済みイベントを作成し、それをサブスクライブ済みイベントの集合に追加する
SubscribedEvent newEvent2 = Factory.SubscribedEvent.createInstance();
subscribedEventId = new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}");
evDef = Factory.EventClassDefinition.getInstance(os, subscribedEventId);
newEvent2.set_EventClass(evDef);
subEvents.add(newEvent2);
// 新規イベントの集合をサブスクリプションに追加して、サブスクリプションを保存する。
subscription.set_SubscribedEvents(subEvents);
subscription.save(RefreshMode.REFRESH);
C# の例
// 既存のサブスクリプションを取り出すためにプロパティー・フィルターをセットアップする
FilterElement fe = new FilterElement(null, null, null, PropertyNames.SUBSCRIBED_EVENTS);
PropertyFilter pf = new PropertyFilter();
pf.AddIncludeProperty(fe);
ISubscription subscription = Factory.Subscription.FetchInstance(
os, new Id("{AB264E14-2D28-46F1-9215-783952A61897}"), pf);
// サブスクリプションの既存のサブスクライブ済みイベントの名前を取得して表示する
ISubscribedEventList subEvents = subscription.SubscribedEvents;
System.Console.WriteLine("Subscribed events before additions:");
foreach (ISubscribedEvent existingEvent in subEvents)
{
System.Console.WriteLine(existingEvent.EventClass.DisplayName);
}
// システムのサブスクライブ済みイベントを作成し、それをサブスクライブ済みイベントの集合に追加する
Id subscribedEventId = GuidConstants.Class_CancelCheckoutEvent;
IEventClassDefinition evDef = Factory.EventClassDefinition.GetInstance(
os, subscribedEventId);
ISubscribedEvent newEvent1 = Factory.SubscribedEvent.CreateInstance();
newEvent1.EventClass = evDef;
subEvents.Add(newEvent1);
// カスタムのサブスクライブ済みイベントを作成し、それをサブスクライブ済みイベントの集合に追加する
ISubscribedEvent newEvent2 = Factory.SubscribedEvent.CreateInstance();
subscribedEventId = new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}");
evDef = Factory.EventClassDefinition.GetInstance(os, subscribedEventId);
newEvent2.EventClass = evDef;
subEvents.Add(newEvent2);
// 新規イベントの集合をサブスクリプションに追加して、サブスクリプションを保存する。
subscription.SubscribedEvents = subEvents;
subscription.Save(RefreshMode.REFRESH);
カスタム・イベントの作成および起動
カスタム・イベントを作成し、それを Subscribableオブジェクトで実行するには、このオブジェクト上で raiseEvent メソッドを呼び出します。カスタム・イベントを発生させるには、その前にイベントがオブジェクト・ストアに存在する必要があります。サブスクリプションが存在し、そのサブスクリプション内で、サブスクリプションのターゲットが raiseEvent メソッドの呼び出し元の Subscribable オブジェクトであること、かつ発生するカスタム・イベントがサブスクリプション付きイベントに含まれていることも必要です。 カスタム・イベントを発生させると、RaiseEvent クラスのインスタンスが作成され、サブスクリプションに設定されたイベント・アクションが実行されます。
- カスタム・イベントは、Content Engine の監査ログに記録できます。詳細については、「クラスに対する監査の構成」を参照してください。
- カスタム・イベントの状態をクライアント・アプリケーションで設定し、次に、それを条件付き処理のためにイベント・ハンドラーで使用できます。詳細については、「カスタム・イベントの状況の設定」を参照してください。
次の Java および C# の例は、カスタム・イベントを作成し、それを Subscribable オブジェクトで起動します。EventClassDefinition オブジェクトを使用して、CustomEvent クラスのサブクラスである MyCustomEvent を作成し、永続化します。EventClassDefinition オブジェクトが、既存のサブスクリプションに追加されます。新規に作成されたカスタム・イベントが取得され、Subscribable オブジェクトおよび Document オブジェクトも取得されます。Document オブジェクトでカスタム・イベントが起動され、次に、raiseEvent メソッドをサーバーに送信するためにイベントが保存されます。(Document オブジェクトはイベント・アクションを使用して変更されないため、NO_REFRESH が指定されています。)
Java の例
// 新規のカスタム・イベントを作成してオブジェクト・ストアに保存する
EventClassDefinition custom = Factory.EventClassDefinition.getInstance(
os, GuidConstants.Class_CustomEvent);
EventClassDefinition customSubclass =(EventClassDefinition) custom.createSubclass();
LocalizedString ls = Factory.LocalizedString.createInstance();
ls.set_LocalizedText("MyCustomEvent");
ls.set_LocaleName("en_US");
LocalizedStringList lsl = Factory.LocalizedString.createList();
lsl.add(ls);
customSubclass.set_DisplayNames(lsl);
customSubclass.save(RefreshMode.REFRESH);
// 新規のカスタム・イベントの追加先にある既存のサブスクリプションを取得する
FilterElement fe = new FilterElement(null, null, null,PropertyNames.SUBSCRIBED_EVENTS);
PropertyFilter pf = new PropertyFilter();
pf.addIncludeProperty(fe);
Subscription subscription = Factory.Subscription.fetchInstance(os,
new Id("{AB264E14-2D28-46F1-9215-783952A61897}"), pf);
// サブスクリプションの既存のサブスクライブ済みイベントのリストを取得し、
// その後、新規のカスタム・イベントをそのリストに追加する。
SubscribedEventList subEvents = subscription.get_SubscribedEvents();
SubscribedEvent newEvent = Factory.SubscribedEvent.createInstance();
newEvent.set_EventClass(customSubclass);
subEvents.add(newEvent);
// 新規イベントの集合をサブスクリプションに追加して、サブスクリプションを保存する。
subscription.set_SubscribedEvents(subEvents);
subscription.save(RefreshMode.REFRESH);
// 生成される新規作成のカスタム・イベントを取得する。
CustomEvent custEvent = Factory.CustomEvent.getInstance(os, "MyCustomEvent", customSubclass.get_Id());
// カスタム・イベントが生成される Document オブジェクトを取得する。
Document doc=Factory.Document.getInstance (
os, "Document", new Id("{50E32923-D1B7-40B5-A394-2F44CA955D2E}") );
// Document オブジェクト上でイベントを生成し、それを保存してサーバー上で操作を呼び出す。
doc.raiseEvent(custEvent);
doc.save(RefreshMode.NO_REFRESH);
C# の例
// 新規のカスタム・イベントを作成してオブジェクト・ストアに保存する
IEventClassDefinition custom = Factory.EventClassDefinition.GetInstance(
os, GuidConstants.Class_CustomEvent);
IEventClassDefinition customSubclass = (IEventClassDefinition)custom.CreateSubclass();
ILocalizedString ls = Factory.LocalizedString.CreateInstance();
ls.LocalizedText = "MyCustomEvent";
ls.LocaleName = "en_US";
ILocalizedStringList lsl = Factory.LocalizedString.CreateList();
lsl.Add(ls);
customSubclass.DisplayNames = lsl;
customSubclass.Save(RefreshMode.REFRESH);
// 新規のカスタム・イベントの追加先にある既存のサブスクリプションを取得する
FilterElement fe = new FilterElement(null, null, null, PropertyNames.SUBSCRIBED_EVENTS);
PropertyFilter pf = new PropertyFilter();
pf.AddIncludeProperty(fe);
ISubscription subscription = Factory.Subscription.FetchInstance(os,
new Id("{AB264E14-2D28-46F1-9215-783952A61897}"), pf);
// サブスクリプションの既存のサブスクライブ済みイベントのリストを取得し、
// その後、新規のカスタム・イベントをそのリストに追加する。
ISubscribedEventList subEvents = subscription.SubscribedEvents;
ISubscribedEvent newEvent = Factory.SubscribedEvent.CreateInstance();
newEvent.EventClass = customSubclass;
subEvents.Add(newEvent);
// 新規イベントの集合をサブスクリプションに追加して、サブスクリプションを保存する。
subscription.SubscribedEvents = subEvents;
subscription.Save(RefreshMode.REFRESH);
// 生成される新規作成のカスタム・イベントを取得する。
ICustomEvent custEvent = Factory.CustomEvent.CreateInstance(os, "MyCustomEvent", customSubclass.Id);
// カスタム・イベントが生成される Document オブジェクトを取得する。
IDocument doc = Factory.Document.FetchInstance (
os, new Id("{50E32923-D1B7-40B5-A394-2F44CA955D2E}"), null);
// Document オブジェクト上でイベントを生成し、それを保存してサーバー上で操作を呼び出す。
doc.RaiseEvent(custEvent);
doc.Save(RefreshMode.NO_REFRESH);
カスタム・イベントの状況の設定
CustomEvent オブジェクトの EventStatus プロパティーを設定することにより、イベント・アクション・ハンドラーの実装が、このプロパティーの値に基づいた条件付きのロジックを適用するようにできます。この状況を以下の例に示します。最初の例には、EventStatus プロパティーを設定するクライアント・アプリケーションのコードを示します。2 番目の例には、EventStatus プロパティーの値を取得し、調べるサーバーのイベント・ハンドラー・コードを示します。
クライアント・アプリケーション: 状況の設定
以下のクライアント・ベースの Java および C# の例に示すように、setEventStatus メソッドは、CustomEvent オブジェクトを作成し、そのオブジェクトの EventStatus プロパティーを設定し、このメソッドに渡された Document オブジェクトで CustomEvent オブジェクトを発生させます。EventStatus プロパティーを設定できるのは、作成されたイベント上でのみであるため、カスタム・イベントのインスタンスは、取得するのではなく、作成する必要があります。
Java の例
/* このメソッドは、ドキュメント・クラスに対するユーザー・アクションに基づいて呼び出されます。
* このメソッドにより、カスタム・イベントが作成され、アクションを起動したユーザーが属するグループに基づいて、
* そのイベントの EventStatus プロパティーが設定されます。
* このメソッドでは、次に、このメソッドに渡されたドキュメントでカスタム・イベントを発生させ、
* これにより下に示すイベント・ハンドラーを起動します。
* これが正常に機能するために、クラス・サブスクリプションが存在します。このクラス・サブスクリプションには、
* ドキュメント・クラス、カスタム・イベント、およびイベント・ハンドラーを表すイベント・アクションが含まれています。
*/
public void setEventStatus (Document doc, Connection ceConn)
// 既存のカスタム・イベントのインスタンスを作成する
CustomEvent custEvent = Factory.CustomEvent.createInstance(os, "MyCustomEvent");
// ドキュメント・クラスでアクションを起動したユーザーとそのユーザーが属するグループを取得する
User user = Factory.User.fetchCurrent(ceConn, null);
GroupSet groups = user.get_MemberOfGroups();
Iterator groupsIter = groups.iterator();
// groups を繰り返し、ユーザーが "Manager" グループと "Clerical" グループの
// どちらに属しているかに応じて、カスタム・イベントのイベント・ステータスを設定する
// (ユーザーが両方のグループに属することはできない。)
while (groupsIter.hasNext())
{
Group group = (Group) groupsIter.next();
if ( group.get_ShortName().equals("Manager") )
custEvent.set_EventStatus(new Integer(50));
else if ( group.get_ShortName().equals("Clerical") )
custEvent.set_EventStatus(new Integer(51));
}
// Document オブジェクト上でイベントを生成し、それを保存してサーバー上で操作を呼び出す。
doc.raiseEvent(custEvent);
doc.save(RefreshMode.NO_REFRESH);
}
C# の例
public void setEventStatus (IDocument doc, IConnection ceConn)
{
// 既存のカスタム・イベントのインスタンスを作成する
ICustomEvent custEvent = Factory.CustomEvent.CreateInstance(os, "MyCustomEvent");
// ドキュメント・クラスでアクションを起動したユーザーとそのユーザーが属するグループを取得する
IUser user = Factory.User.FetchCurrent(ceConn, null);
IGroupSet groups = user.MemberOfGroups;
// groups を繰り返し、ユーザーが "Manager" グループと "Clerical" グループの
// どちらに属しているかに応じて、カスタム・イベントのイベント・ステータスを設定する
// (ユーザーが両方のグループに属することはできない。)
foreach (IGroup group in groups)
{
if ( group.ShortName.Equals("Manager") )
custEvent.EventStatus = 50;
else if ( group.ShortName.Equals("Clerical") )
custEvent.EventStatus = 51;
}
// Document オブジェクト上でイベントを生成し、それを保存してサーバー上で操作を呼び出す。
doc.RaiseEvent(custEvent);
doc.Save(RefreshMode.NO_REFRESH);
}
サーバーのイベント・ハンドラー: 状況の取得
以下のコード例は、前もってクライアント・アプリケーションのコードに設定されている EventStatus プロパティーの値を取得する EventActionHandler の実装を示しています。CheckStatusEventHandler クラスは、EventStatus プロパティーの値に基づいて、使用可能な 2 つのログのいずれかに項目を 1 つ書き込みます。EventActionHandler インターフェースは Java でのみ実装できることに注意してください。
Java の例
/* このイベント・ハンドラーは、上のメソッドの結果として呼び出されます。
* これにカスタム・イベントが渡され、ログの書き込み先を判別するために
* イベントの EventStatus プロパティーが調べられます。
*/
import com.filenet.api.engine.EventActionHandler;
import com.filenet.api.events.ObjectChangeEvent;
import com.filenet.api.util.Id;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class CheckStatusEventHandler implements EventActionHandler
{
public void onEvent(ObjectChangeEvent event, Id subId)
{
// Initialize File objects for logs.
File outputFile1 = new File("C:¥¥Program Files¥¥FileNet¥¥ContentEngine¥¥logs¥¥manager.txt");
// Windows 以外: File outputFile1 = new File("/opt/FileNet/ContentEngine/logs/manager.txt");
File outputFile2 = new File("C:¥¥Program Files¥¥FileNet¥¥ContentEngine¥¥logs¥¥clerical.txt");
// Windows 以外: File outputFile2 = new File("/opt/FileNet/ContentEngine/logs/clerical.txt");
FileWriter out;
// カスタム・イベントの状況を検査して、該当するログに書き込む
try
{
if ( event.get_EventStatus().equals(new Integer(50)) )
{
//Write to manager log.
out = new FileWriter(outputFile1, true); // true = append
out.write("Manager action taken at: "
+ new java.util.Date() + "¥r¥n");
out.close();
}
else if ( event.get_EventStatus().equals(new Integer(51)) )
{
//Write to clerical log.
out = new FileWriter(outputFile2, true);
out.write("Clerical action taken at: "
+ new java.util.Date() + "¥r¥n");
out.close();
}
}
catch (IOException e) {
ErrorRecord er[] = {new ErrorRecord (e)};
throw new EngineRuntimeException(e, ExceptionCode.EVENT_HANDLER_THREW, er);
}
}
}
オブジェクト・ストアからのキュー・アイテムの取得
非同期で実行するように構成されたイベント・アクションをサブスクリプションによって開始すると、そのアクションは実行を待機する保留中のアクションとしてキューに追加されます。 (非同期で実行されるドキュメント分類アクションは、同じキューに入れられます。) アクションは QueueItem オブジェクトとして表され、関連するイベント・アクション・ハンドラーが正常に実行されるとキューから削除されます。アクション・ハンドラーが失敗すると、QueueItem オブジェクトの RetryCount プロパティーに設定されたのと同じ回数だけ実行が再試行されます。 RetryCount プロパティーのデフォルト値は 6 です。このため、実行が連続して失敗した場合、初回の試行と 6 回の再試行で、最大で 7 回の実行が試行できます。再試行が一度も成功しなかった場合、QueueItem オブジェクトは非アクティブ状態でキュー内部に残り、その RetryCount プロパティーは -1 に設定されます。
保留中のアクションと失敗したアクションを表す QueueItem オブジェクトを取得できます。失敗したアクション、すなわち RetryCount プロパティーが -1 に設定されたアクションについては、delete メソッドを使用してキューから削除できます。別の方法として、イベント・アクション・ハンドラーを修正し、オブジェクトの RetryCount プロパティーをリセットして、キュー内部のアクションを再度アクティブ化できます。
キュー内にある QueueItem オブジェクトを取得する最も簡単な方法は、Administration Console for Content Platform Engine を使用する方法です。これを使用すると、SQL 検索を作成することも、パッケージされた検索テンプレートを、キュー内の項目の管理用にカスタマイズすることもできます。ただし、Content Java API および .NET API を使用して QueueItem オブジェクトを取得することもできます。
キュー内にある非アクティブの QueueItem オブジェクトを再アクティブ化する方法を、次の Java および C# の例に示します。この例では、com.filenet.api.query クラスを使用して、検索対象の QueueItem データベース・テーブルを指定する SQL ステートメントを渡します。この例では、検索結果を反復処理し、イベント・アクションであるキュー・アイテムを検索して、キュー内に存在する可能性があるドキュメント分類アクションをフィルターで除去します。非アクティブのイベント・アクションの RetryCount プロパティーは、6 にリセットされます。
Java の例
...
// SQL 選択ステートメントを作成する
String sqlStr = "Select * from QueueItem";
SearchSQL sql = new SearchSQL(sqlStr);
SearchScope ss = new com.filenet.api.query.SearchScope(os);
// キュー内のすべてのアイテムを取得する
QueueItemSet qiSet = (QueueItemSet)ss.fetchObjects(sql, new Integer(1), null, Boolean.TRUE);
Iterator iter = qiSet.iterator();
QueueItem qi;
// キュー・アイテムを反復し、EventQueueItem オブジェクトの RetryCount プロパティーをリセットする
while (iter.hasNext())
{
qi = (QueueItem)iter.next();
if (qi.get_ClassDescription().get_SymbolicName().equals(ClassNames.EVENT_QUEUE_ITEM))
{
System.out.println("Creator: " + qi.get_Creator() +
"¥nDate Created: " + qi.get_DateCreated().toString() +
"¥nRetry count is " + qi.get_RetryCount() );
if (qi.get_RetryCount().equals(new Integer(-1)) )
{
qi.set_RetryCount(new Integer(6));
qi.save(RefreshMode.REFRESH);
}
}
}
}
C# の例
...
// SQL 選択ステートメントを作成する
String sqlStr = "Select * from QueueItem";
SearchSQL sql = new SearchSQL(sqlStr);
SearchScope ss = new FileNet.Api.Query.SearchScope(os);
// キュー内のすべてのアイテムを取得する
IQueueItemSet qiSet = (IQueueItemSet)ss.FetchObjects(sql, 1, null, true);
// キュー・アイテムを反復し、IEventQueueItem オブジェクトの RetryCount プロパティーをリセットする
foreach (IQueueItem qi in qiSet)
{
if (qi.ClassDescription.SymbolicName.Equals(ClassNames.EVENT_QUEUE_ITEM))
{
System.Console.WriteLine("Creator: " + qi.Creator +
"¥nDate Created: " + qi.DateCreated +
"¥nRetry count is " + qi.RetryCount);
if (qi.RetryCount == -1 )
{
qi.RetryCount = 6;
qi.Save(RefreshMode.REFRESH);
}
}
}
}