A Subscription
object requires an EventAction
object and a user-implemented event action handler that the EventAction
object references. If the EventAction
object and event action handler do not already exist, you must first create them, and then associate them with the Subscription
object, as shown in the following topics.
You can also retrieve Subscription
objects, as well as set and retrieve properties and permissions for them. The following topics show how to code for common scenarios with retrieved subscriptions.
In addition to system events, you can subscribe custom events to a subscription. As shown in the following topics, a client application must manually raise a custom event to invoke an event action handler. Also, the client can set the status of a custom event to convey state to the event action handler.
When a subscription is invoked, its EventAction
object — if it is configured to run asynchronously — is placed in a Content Engine queue as a pending action. You can monitor pending actions, and, if there are failed actions, you can fix them and relaunch them from the queue. See Retrieving Queue Items from an Object Store.
For an overview of subscriptions, see Subscription Concepts.
To create an event action handler, you must implement the onEvent
method of the Java™ EventActionHandler interface. The following example shows one such implementation. The onEvent
method receives an ObjectChangeEvent subobject and the Id
object for the subscription that references the event action handler (via the EventAction
object). With the Id
object, you can retrieve the subscription should you need it. With the ObjectChangeEvent
subobject, you can get the event's source object, which is the target object of the subscription.
NOTE The Content Engine uses the default constructor (not shown in the example) to create an event action handler object. Do not use a custom constructor.
The example handler below filters new forms, filing forms of the "FloodClaim" class to a special folder for users belonging to the "NOL" group. The handler is intended for a ClassSubscription
object, in which the subscribed event is CreationEvent
, and the target object is the "FloodClaim" class. When a user creates a new form and sets its class type to "FloodClaim", the handler will execute. The ObjectChangeEvent
subobject is the CreationEvent
object, and the event's source object is any form document of the "FloodClaim" class. For a code example of creating a class subscription applicable to this scenario, see Creating a Subscription Object.
For best practices in implementing and packaging an EventActionHandler
interface, see Implementation Concepts. To view a sample source code EventActionHandler
implementation packaged with the Content Engine, go to this Content Engine directory: <drive>:/Program Files/Filenet/Content Engine/samples. The EventActionHandler
implementation is JavaEventHandler.java.
NOTE When working with custom events, you can leverage the EventStatus property, with which you can set the state of a custom event in a client application, and then check the custom event's state in an event action handler and process accordingly. For more information, see Setting Status for a Custom Event.
Java Example
package sample.actionhandler; import com.filenet.api.engine.EventActionHandler; import com.filenet.api.events.*; 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.*; import java.util.Iterator; public class FilterNewDocumentsEventHandler implements EventActionHandler { public void onEvent(ObjectChangeEvent event, Id subId) { try { ObjectStore os = event.getObjectStore(); Document doc = (Document) event.get_SourceObject(); 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("DocumentTitle"), DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE); drcr.save(RefreshMode.NO_REFRESH); break; } } } catch (Exception e) { ErrorRecord er[] = {new ErrorRecord (e)}; throw new EngineRuntimeException(e, ExceptionCode.EVENT_HANDLER_THREW, er); } } }
An EventAction object
identifies the event action handler to be launched when a subscribed event fires. The following Java and C# code snippets show how to create an EventAction
object and set the properties that associate it with an event action handler: ProgId and, conditionally, CodeModule.
You must set the ProgId property with the fully qualified name of the handler class.
If, as shown in the examples, the event action handler is contained within a CodeModule
stored in an object store, you must
also get the CodeModule
object, then assign it to the
CodeModule property of the EventAction
object.
Note that you cannot set the CodeModule property to a reservation (in progress) version of CodeModule
. For more information, see Creating a CodeModule Object.
NOTE Do not set the CodeModule property if you set the application server's class path to the location of the event handler.
When saved, an EventAction
object is stored in the Events/Event Action folder of a Content Engine object store.
Java Example
... //Create event action EventAction eventAction = Factory.EventAction.createInstance(os, null); // Set ProgId property with fully qualified name of handler class eventAction.set_ProgId("sample.actionhandler.FilterNewDocumentsEventHandler"); //Get CodeModule object. CodeModule cm = Factory.CodeModule.fetchInstance(os, new Id("{E6C739B5-0EEB-43E1-B1FB-D6BC74F80EAC}"), null); // Set CodeModule property if handler class is checked into object store. eventAction.set_CodeModule(cm); eventAction.set_DisplayName("FilterNewDocumentsEventAction"); eventAction.save(RefreshMode.REFRESH);
C# Example
... // Create event action IEventAction eventAction = Factory.EventAction.CreateInstance(os, null); // Set ProgId property with fully qualified name of handler class eventAction.ProgId = "sample.actionhandler.FilterNewDocumentsEventHandler"; // Get CodeModule object. ICodeModule cm = Factory.CodeModule.FetchInstance(os, new Id("{E6C739B5-0EEB-43E1-B1FB-D6BC74F80EAC}"), null); // Set CodeModule property.. eventAction.CodeModule = cm; eventAction.DisplayName = "FilterNewDocumentsEventAction"; eventAction.Save(RefreshMode.REFRESH);
After creating the event action handler and the EventAction
object, you're ready to create a
Subscription
object and persist it to an object store. Although there are different subscription types,
the process of creating a Subscription object is generally the same.
You define the subscription type and set the following properties: the event action to execute,
the target object of the subscription, and the subscribed events, which, when triggered on the
target object, invoke the event action.
The following Java and C# examples show how to create a subscription of type ClassSubscription
.
A class subscription is launched when events are fired on objects of a specified class.
In this example, the subscription target is a subclass of the Document class,
represented by the DocumentClassDefinition
object, and the subscribed event is CreationEvent
.
Therefore, whenever an object of the Document subclass is created, the event action will execute.
Note, however, that if there are children classes of the subclass, they are explicitly excluded from the subscription,
as set in the IncludeSubclassesRequested property.
An event in a subscription is represented by a
SubscribedEvent object.
As shown in the examples,
you set the object's EventClass property with an EventClassDefinition
object, which identifies the event.
You then add the SubscribedEvent
object to a SubscribedEventList
collection,
and set the subscription's SubscribedEvents property to the collection.
When saved, a subscription is stored in the Events/Subscription folder of a Content Engine object store.
Java Example
// Create class subscription ClassSubscription subscription = Factory.ClassSubscription.createInstance(os, null); // The target of the class subscription will be a Document subclass, // identified by the ID object DocumentClassDefinition docCD=Factory.DocumentClassDefinition.getInstance( os, new Id("{B19C39FD-9E71-4E56-8D7E-9B036B3B903B}") ); subscription.set_SubscriptionTarget(docCD); // Exclude subclasses of the target class subscription.set_IncludeSubclassesRequested(Boolean.FALSE); // Get EventAction object created in previous example, // and set subscription's EventAction property EventAction eventAction = Factory.EventAction.fetchInstance(os, new Id("{F1C9ACE3-8454-4B2C-9AC4-30228FAA8113}"), null); subscription.set_EventAction(eventAction); // Specify one or more events that, when triggered, will invoke the subscription. // Add the events to a list and set the subscription object. 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); // Specify that event handler run synchronously subscription.set_IsSynchronous(Boolean.TRUE); subscription.set_DisplayName("FileDocumentSubscription"); subscription.save(RefreshMode.REFRESH);
C# Example
// Create class subscription IClassSubscription subscription = Factory.ClassSubscription.CreateInstance(os, null); // The target of the class subscription will be the Document class, // identified by the ID object IDocumentClassDefinition docCD = Factory.DocumentClassDefinition.GetInstance( os, new Id("{B19C39FD-9E71-4E56-8D7E-9B036B3B903B}") ); subscription.SubscriptionTarget = docCD; // Exclude subclasses of the target class subscription.IncludeSubclassesRequested= false; // Get EventAction object created in previous example, // and set subscription's EventAction property IEventAction eventAction = Factory.EventAction.FetchInstance( os, new Id("{F1C9ACE3-8454-4B2C-9AC4-30228FAA8113}"), null); subscription.EventAction = eventAction; //Specify one or more events that, when triggered, // will invoke the subscription. // Add the events to a list and set the subscription object. 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; // Specify that event handler run synchronously subscription.IsSynchronous = true; subscription.DisplayName = "FileDocumentSubscription"; subscription.Save(RefreshMode.REFRESH);
You can retrieve a single Subscription
object with a Factory
method, and you can retrieve a collection of Subscription
objects
(SubscriptionSet)
by getting the Subscriptions property on an EventAction
or ObjectStore
object. You can also return a SubscriptionSet
with a WorkflowDefinition
object's WorkflowSourceSubscriptions property.
One use case for retrieving all of the subscriptions in an object store is to find all of the subscriptions in which a particular object is
the target of the subscriptions.
The following Java and C# examples show how to retrieve a SubscriptionSet
collection from an ObjectStore
object, and iterate the collection in search of subscriptions where the target of the subscriptions is a particular Document object.
Java Example
// Get Document object to find subscriptions in which // Document object is the target object of the subscriptions Document doc = Factory.Document.getInstance( os, "Document", new Id("{5B80C0B6-8EE3-430D-BE20-C461842326F8}")); // Initialize ArrayList to hold subscriptions // in which Document object is the target of the subscriptions ArrayList targetFound = new ArrayList(); // Get all subscriptions from object store SubscriptionSet subscriptions = os.get_Subscriptions(); // Iterate SubscriptionSet and look for subscription target // that matches specified Document object. // For each match, add subscription to ArrayList object. Iterator subcriptionsIter = subscriptions.iterator(); while (subcriptionsIter.hasNext()) { Subscription subscription = (Subscription) subcriptionsIter.next(); Subscribable subObject = subscription.get_SubscriptionTarget(); if (subObject.equals(doc)) { targetFound.add(subscription); } } // Iterate ArrayList object and print out name of each subscription // 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# Example
// Get Document object to find subscriptions in which // Document object is the target object of the subscriptions IDocument doc = Factory.Document.GetInstance (os, "Document", new Id("{5B80C0B6-8EE3-430D-BE20-C461842326F8}")); // Initialize ArrayList to hold subscriptions // in which Document object is the target of the subscriptions ArrayList targetFound = new ArrayList(); // Get all subscriptions from object store ISubscriptionSet subscriptions = os.Subscriptions; // Iterate SubscriptionSet and look for subscription target // that matches specified Document object. // For each match, add subscription to ArrayList object. foreach (ISubscription subscription in subscriptions) { ISubscribable subObject = subscription.SubscriptionTarget; if (subObject.Equals(doc)) { targetFound.Add(subscription); } } // Iterate ArrayList object and print out name of each subscription // in which Document object is the target object of the subscription foreach (ISubscription subscription in targetFound) { System.Console.WriteLine(subscription.Name); }
See Retrieving Workflow Subscriptions for more information.
A Subscription
object's SubscribedEvents property contains a collection of the subscribed-to events for the subscription. The following Java and C# examples retrieve an existing subscription and print the display names of subscribed events currently assigned to the subscription.
Then two new events are added to the subscription: a system event and a custom event.
Note if you add duplicated event types into the SubscribedEvents property, then the EVENT_DUPLICATE_LIST_SUBSCRIBED_EVENT
exception will be thrown.
Adding event types that are already assigned to the subscription will be ignored.
Java Example
// Set up property filter for fetching existing subscription 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); // Retrieve and display names of subscription's existing subscribed events 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()); } // Create system subscribed event and add it to collection of subscribed events Id subscribedEventId = GuidConstants.Class_CancelCheckoutEvent; EventClassDefinition evDef = Factory.EventClassDefinition.getInstance( os, subscribedEventId); SubscribedEvent newEvent1 = Factory.SubscribedEvent.createInstance(); newEvent1.set_EventClass(evDef); subEvents.add(newEvent1); // Create custom subscribed event and add it to collection of subscribed events 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); // Add collection of new events to subscription, then save subscription subscription.set_SubscribedEvents(subEvents); subscription.save(RefreshMode.REFRESH);
C# Example
// Set up property filter for fetching existing subscription 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); // Retrieve and display names of subscription's existing subscribed events ISubscribedEventList subEvents = subscription.SubscribedEvents; System.Console.WriteLine("Subscribed events before additions:"); foreach (ISubscribedEvent existingEvent in subEvents) { System.Console.WriteLine(existingEvent.EventClass.DisplayName); } // Create system subscribed event and add it to collection of subscribed events Id subscribedEventId = GuidConstants.Class_CancelCheckoutEvent; IEventClassDefinition evDef = Factory.EventClassDefinition.GetInstance( os, subscribedEventId); ISubscribedEvent newEvent1 = Factory.SubscribedEvent.CreateInstance(); newEvent1.EventClass = evDef; subEvents.Add(newEvent1); // Create custom subscribed event and add it to collection of subscribed events 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); // Add collection of new events to subscription, then save subscription subscription.SubscribedEvents = subEvents; subscription.Save(RefreshMode.REFRESH);
You can create a custom event and invoke it on a
Subscribable object
by calling the raiseEvent
method on the object.
Before you can raise a custom event, the event must exist in the object store.
Also, a subscription must exist in which the subscription target is the Subscribable
object
on which the raiseEvent
method will be called, and in which the subscribed events include the
custom event that will be raised. When you raise the custom event, an instance of the
RaiseEvent class is created,
and the event action set in the subscription is invoked.
NOTE
The following Java and C# examples create a custom event and raise it on a Subscribable
object. An EventClassDefinition
object is used to create and persist a subclass, "MyCustomEvent", of the CustomEvent class. The EventClassDefinition
object is added to an existing subscription. The newly created custom event is retrieved, as well as a Subscribable
object, a Document object. The custom event is raised on the Document object, which is then saved to send the raiseEvent
method to the server. (Because the event action does not change the Document object, NO_REFRESH
is specified.)
Java Example
// Create new custom event and save it to object store 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); // Get existing subscription to which you will add the new custom event 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); // Retrieve list of subscription's existing subscribed events, // then add new custom event to it. SubscribedEventList subEvents = subscription.get_SubscribedEvents(); SubscribedEvent newEvent = Factory.SubscribedEvent.createInstance(); newEvent.set_EventClass(customSubclass); subEvents.add(newEvent); // Add collection of new events to subscription, then save subscription. subscription.set_SubscribedEvents(subEvents); subscription.save(RefreshMode.REFRESH); // Get newly created custom event that will be raised. CustomEvent custEvent = Factory.CustomEvent.getInstance(os, "MyCustomEvent", customSubclass.get_Id()); // Get Document object on which custom event will be raised. Document doc=Factory.Document.getInstance ( os, "Document", new Id("{50E32923-D1B7-40B5-A394-2F44CA955D2E}") ); // Raise event on Document object, then save it to invoke operation on server. doc.raiseEvent(custEvent); doc.save(RefreshMode.NO_REFRESH);
C# Example
// Create new custom event and save it to object store 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); // Get existing subscription to which you will add the new custom event 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); // Retrieve list of subscription's existing subscribed events, // then add new custom event to it. ISubscribedEventList subEvents = subscription.SubscribedEvents; ISubscribedEvent newEvent = Factory.SubscribedEvent.CreateInstance(); newEvent.EventClass = customSubclass; subEvents.Add(newEvent); // Add collection of new events to subscription, then save subscription. subscription.SubscribedEvents = subEvents; subscription.Save(RefreshMode.REFRESH); // Get newly created custom event that will be raised. ICustomEvent custEvent = Factory.CustomEvent.CreateInstance(os, "MyCustomEvent", customSubclass.Id); // Get Document object on which custom event will be raised IDocument doc = Factory.Document.FetchInstance ( os, new Id("{50E32923-D1B7-40B5-A394-2F44CA955D2E}"), null); // Raise event on Document object, then save it to invoke operation on server doc.RaiseEvent(custEvent); doc.Save(RefreshMode.NO_REFRESH);
You can set the EventStatus property of a CustomEvent
object, allowing an event action handler implementation to apply conditional logic that's based on the value of the property. This scenario is shown in the following examples. The first example shows client application code that sets the EventStatus property. The second example shows server event handler code that retrieves and tests the value of the EventStatus property.
As shown in the client-based Java and C# examples below, the setEventStatus
method creates a CustomEvent
object, sets the object's EventStatus property, and raises it on a Document
object passed to the method. Note that an instance of a custom event must be created and not retrieved because the EventStatus property can only be set on a created event.
Java Example
/* This method is invoked based on some user action on a document class. * The method creates a custom event and sets the event's EventStatus property based * on the group to which the user who invoked the action belongs. * The method then raises the custom event on the document passed to the method, which * triggers an event handler, shown below. * To make this work, a class subscription exists that contains the document class, * the custom event, and an event action representing the event handler. */ public void setEventStatus (Document doc, Connection ceConn) // Create an instance of existing custom event. CustomEvent custEvent = Factory.CustomEvent.createInstance(os, "MyCustomEvent"); // Get user who invoked action on document class and the group to which the user belongs. User user = Factory.User.fetchCurrent(ceConn, null); GroupSet groups = user.get_MemberOfGroups(); Iterator groupsIter = groups.iterator(); // Iterate the groups, and set the event status of the custom event // based on whether the user is in the "Manager" group or the "Clerical" group. // (A user cannot belong to both groups.) 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)); } // Raise event on Document object, then save it to invoke operation on server. doc.raiseEvent(custEvent); doc.save(RefreshMode.NO_REFRESH); }
C# Example
public void setEventStatus (IDocument doc, IConnection ceConn) { // Create an instance of existing custom event. ICustomEvent custEvent = Factory.CustomEvent.CreateInstance(os, "MyCustomEvent"); // Get user who invoked action on document class and the group to which the user belongs. IUser user = Factory.User.FetchCurrent(ceConn, null); IGroupSet groups = user.MemberOfGroups; // Iterate the groups, and set the event status of the custom event // based on whether the user is in the "Manager" group or the "Clerical" group. // (A user cannot belong to both groups.) foreach (IGroup group in groups) { if ( group.ShortName.Equals("Manager") ) custEvent.EventStatus = 50; else if ( group.ShortName.Equals("Clerical") ) custEvent.EventStatus = 51; } // Raise event on Document object, then save it to invoke operation on server. doc.RaiseEvent(custEvent); doc.Save(RefreshMode.NO_REFRESH); }
Below is an EventActionHandler
implementation that retrieves the value of the EventStatus property set in the client application code above. The CheckStatusEventHandler
class writes an entry to one of two available logs based on the value of the EventStatus property. Note that the EventActionHandler
interface can only be implemented in Java.
Java Example
/* This event handler is invoked as a result of the above method. * A custom event is passed to it, and the event's EventStatus property * is checked to determine which log to write to. */ 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"); File outputFile2 = new File("C:\\Program Files\\FileNet\\ContentEngine\\logs\\clerical.txt"); FileWriter out; // Check status of custom event and write to applicable log. 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); } } }
When an event action configured to run asynchronously is invoked through a subscription, it is placed in a queue as a pending action awaiting execution. (Document classification actions, which run asynchronously, are placed in the same queue.) Represented as a QueueItem object, an action is removed from the queue if its associated event action handler executes successfully. If the action handler fails, execution will be retried as many times as set in the QueueItem
's RetryCount property. The default value of the RetryCount property is six; therefore, up to seven execution attempts will be made, the initial execution attempt and the six retries should execution repeatedly fail. If there is no successful retry, the QueueItem
object remains inactive in the queue with its RetryCount property set to -1.
You can retrieve QueueItem
objects representing pending actions and failed actions. For a failed action, that is, one with a RetryCount property set to -1, you can delete it from the queue with the delete
method. Alternatively, you can fix the event action handler and reset the objects's RetryCount property, which reactivates the action in the queue.
NOTE Although you can safely reset properties of a QueueItem
object that has failed, you should not modify properties of a QueueItem
object that is still waiting to be processed (pending action).
The easiest way to retrieve QueueItem
objects in the queue is with Enterprise Manager, from which you can create SQL searches, or customize packaged search templates for managing entries in the queue (see Concepts: search and bulk operations). However, you can also retrieve QueueItem
objects with the Content Java and .NET APIs.
The following Java and C# samples show how to reactivate inactive QueueItem
objects in the queue.
Using com.filenet.api.query classes, the examples pass a SQL statement specifying the "QueueItem" database table
to be searched. The examples iterate the search results, looking for queue items that are event actions, filtering out any potential document classification actions that might also be in the queue. The RetryCount property for inactive event actions is reset to six.
Java Example
... // Build the SQL select statement String sqlStr = "Select * from QueueItem"; SearchSQL sql = new SearchSQL(sqlStr); SearchScope ss = new com.filenet.api.query.SearchScope(os); // Get all items in the queue QueueItemSet qiSet = (QueueItemSet)ss.fetchObjects(sql, new Integer(1), null, Boolean.TRUE); Iterator iter = qiSet.iterator(); QueueItem qi; // Iterate queue items and reset RetryCount property for EventQueueItem objects 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# Example
... // Build the SQL select statement String sqlStr = "Select * from QueueItem"; SearchSQL sql = new SearchSQL(sqlStr); SearchScope ss = new FileNet.Api.Query.SearchScope(os); // Get all items in the queue IQueueItemSet qiSet = (IQueueItemSet)ss.FetchObjects(sql, 1, null, true); // Iterate queue items and reset RetryCount property for IEventQueueItem objects 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); } } } }