Using Worklist

     Previous  Next    Open TOC in new window  Open Index in new window  View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Worklist Event-based Services

This section describes advanced topics for use by a Java programmer in Workshop for WebLogic. It provides information about:

 


Task Change Events

Worklist defines task change events that can be triggered when there is a change in the state of a task. Worklist accepts subscriptions for events from interested parties (called listeners) and notifies them when events they have expressed interest in occur. Listeners can then take appropriate actions based on the events that occur to a task.

Event Delivery Paths

The possible paths taken by events generated by Worklist could be the Worklist reporting subsystem, web services listeners, and plain Java listeners.

Figure 5-1 Event Delivery Paths

Event Delivery Paths

Note: The listeners shown in the illustration are all Worklist event listeners and are internal system-level listeners. Custom task event listeners are plugged into this tree via .listener files and are registered as siblings of the Worklist default event listeners.

Events

Worklist defines a set of event types to support both runtime and reporting event scenarios. The assumption is that the only real difference between the two usages of events is that reporting more clearly requires both the old and new values of a change in a task. Runtime use of events could conceivably be satisfied to simply retrieve the current value from the task. We assume that in any case a task property is updated, the consumer of the event will query current property values using the Worklist API.

The following table defines the events that are produced by Worklist in response to various operations on a task. All events contain the following data items (accessible via Java methods on the com.bea.wli.worklist.api.events.data.TaskEvent interface):

The following table lists any additional fields added to a specific event type:

Event Type
When
Extra Fields
Event Object Type
CREATE
Task is created. Will be followed by a step change event and an assigned or claimed event that will arrive separately after the create event.
TaskData, and Initial Property names for task.
(sync listeners only - Initial Property Values)
TaskCreateEvent
ASSIGN
Task is assigned, either directly or as a result of moving to a new step, or taking an assign action on the step.
NewAssigneeList, OldAssigneeList
TaskAssignEvent
CLAIM
Task is claimed, either directly or as a result of moving to a new step, or taking an assign action on the step. If a task is auto-claimed, only the claimed event is sent. Not the assigned event.
NewClaimant, OldClaimant,
(if auto-claimed - NewAssigneeList, OldAssigneeList)
TaskClaimEvent
RETURN
Task is returned
Reason, OldClaimant
TaskReturnEvent
TAKE_ACTION
An action is taken. May be followed by
  • a STEP_CHANGE event after a work action that targets a different step.
  • assign/claim events if the task was assigned/claimed (after arriving at the new step after a work action, or after an assign action).
  • a return event after a return action.
  • complete, abort events after a work action if the new current step is a complete or abort step.
NewStep, OldStep, Action, Property Names for Action
(sync listeners only - NewValue for properties)
TaskStepActionEvent
STEP_CHANGE
The current step of the task changes. This can happen administratively or via a work action.
NewStep, OldStep
TaskStepChangeEvent
SET_USER_PROPERTY
A task plan-defined property is updated directly via WorklistTaskUser.setTaskProperties(). If the property is updated as part of taking an action, the names of the modified props will be represented on the TAKE_ACTION event.
PropertyName
(sync listeners only - OldValue, NewValue)
TaskUpdate PropertyEvent
SUSPEND
A task is suspended
Reason
TaskAdminEvent
RESUME
A task is resumed
Reason
TaskAdminEvent
SET_ERROR
A task is set to error state
Reason
TaskAdminEvent
CLEAR_ERROR
A task is reset from error set
Reason
TaskAdminEvent
COMPLETE
A task is completed
Reason
TaskAdminEvent
ABORT
A task is aborted
Reason
TaskAdminEvent
REACTIVATE
A task is reactivated
Reason, NewCurrentStep, OldCurrentStep
TaskReactivateEvent
SET_CURRENT_STEP
A task has it's current step forcibly set. Will be followed by a STEP_CHANGE event indicating the arrival of the task into the new step.
May be followed by assign, claim, complete, or abort events depending on the new current step.
Reason, OldCurrentStep, NewCurrentStep
TaskSetCurrentStep Event
SET_SYSTEM_PROPERTY
Any system property is set directly via WorklistTaskUser.setTaskProperties() or one of the setTask<Name>() methods.
For information on which system properties generate this type of event, see System Properties and TaskUpdateBuiltInProperty Events.
PropertyName
(sync listeners only - OldValue, NewValue)
TaskUpdateBuiltIn PropertyEvent
STEP_EXPIRE
A step of a task was not completed before its scheduled completion date.
ScheduledExpireDateTime, StepName
TaskStepExpireEvent
TASK_EXPIRE
A task was not completed before its scheduled completion date.
ScheduledExpireDateTime
TaskExpireEvent

System Properties and TaskUpdateBuiltInProperty Events

The following system properties may (when updated) cause a TaskUpdateBuiltInProperty event to be delivered from Worklist. Other system properties are read-only and will not cause update events. These property names match the enumeration values from the Worklist com.bea.wli.worklist.api.taskplan.SystemProperty enumeration.

Controlling Events Per-Task Plan

Various types of BEA-provided event listeners can perform producer-side filtering to limit the number of events sent to their external endpoints. This filtering is controlled by event configuration contained in the EventHandler configuration module. For more information, see EventHandler Modules.

Event Dispatch Modes (Quality of Service)

Worklist defines a Java listener interface (see Custom Task Event Listeners section) that Java clients can use to receive events when changes occur on a task instance. A listener can specify the quality of service it requires from Worklist. This quality of service is defined in terms of:

Synchronous delivery means the listener is called on the stack from the same thread that caused the event to be created. Asynchronous delivery means that the event is placed on a queue and then delivered to the listener on a different thread than the thread that caused the event to be created.

Listeners may indicate their preferred dispatching mode when registering via their .listener file.

A critical listener is a listener that absolutely must receive and process all events for which it has subscribed and which may set an error on the task if the event cannot be consumed successfully. A non-critical listener is a listener that can tolerate lost events and may not successfully process some events without setting an error on the task for the event. Events destined for asynchronous critical listeners are put into a reliable and persistent queue and are delivered even in the face of a server crash. Events for non-critical listeners are delivered with no persistence and are not guaranteed to survive a server crash.

Listeners registered as a synchronous critical listener can exercise some amount of control over task changes by throwing an exception from its onTaskEvent() method. If a synchronous critical listener throws an exception from onTaskEvent(), the current transaction (the one that caused the event in the first place) is rolled back. In this case, the change is effectively undone. The task instance is not put into the error state, because to do so requires a live database transaction that can be committed.

All critical listeners are notified of events before non-critical listeners. If a critical listener throws an exception, no further dispatching of the current event is done (and the transaction holding the task change is rolled back).

Note: System administrators should carefully examine any Worklist application containing .listener files. They should scrutinize any .listener file that registers itself as a synchronous user, as this listener will run under the identity of the user making the updates to the tasks that caused the events. Thus, the listener code can do anything the original user could do. Only trusted code should be allowed to deploy as a synchronous listener.

EventListener Interface

Listeners implement a Java listener interface and are plugged into the event delivery mechanism using this listener implementation. Java listeners must implement the following listener interface:

public interface TaskEventListener {
    /**
     * Get the name assigned to this listener
     */
    public String getName();
    /**
     * Get the name for this listener
     */
    public void setName(String name);
    /**
     * Set any properties configured for this TaskEventListener in the custom
     * module that deployed it. This method is only called if properties are
     * available (example specified in the deployment descriptor for the 
     * custom module).
     * @param properties
     */
    public void setProperties(Map<String, Property> properties);
    /**
     * Initialize any resources needed to start handling events in
     * onTaskEvent().
     * @throws com.bea.wli.worklist.api.ManagementException
     */
    public void initialize()
        throws ManagementException;
    /**
     * Destroy this instance and release any resources obtained in initialize
     * or during calls to onTaskEvent().
     * @throws ManagementException
     */
    public void destroy()
        throws ManagementException;
    /**
     * Handle the given event.
     * @throws VetoException If any error occurs processing the event. How 
     * this exception is handled by Worklist depends on how the listener
     * is registered (sync/async, critical/non-critical)
     */
    public void onTaskEvent(TaskEvent event)
        throws VetoException;
}

where TaskEvent is:

public interface TaskEvent
    extends Serializable {
    /**
     * The type of event this event instance represents. Listeners can use
     * this property for simple filtering. In order to obtain event
     * type-specific properties from the event, listeners should cast this
     * event to the appropriate event class based on the runtime type of this
     * event instance.
     */
    public TaskEvent.Type getEventType();
    /**
     * ID of the task that was changed.
     */
    public String getTaskId();
    /**
     * Name of the task that was changed
     */
    public String getTaskName();
    /**
     * ID of the task that was changed.
     */
    public TaskPlanId getTaskPlanId();
    /**
     * User that created this task.
     */
    public String getCreator();
    /**
     * Current owner at the time this event was created.
     */
    public String getOwner();
    /**
     * Current claimant at the time this event was created.
     */
    public String getClaimant();
    /**
     * Current assignee list at the time this event was created.
     */
    public AssigneeDefinition[] getAssigneeList();
    /**
     * Current admin state at the time this event was created.
     */
    public AdminState.Type getAdminState();
    /**
     * Current working state at the time this event was created.
     */
    public WorkingState.Type getWorkingState();
    /**
     * User name of the user that caused the change.
     */
    public String getCaller();
    /**
     * Timestamp (long value representing local system time).
     */
    public long getTimestamp();
    /**
     * The name of the server upon which this task change occurred.
     */
    public String getServerName();
    /**
     * A summary of the most relevant information in this event, limited to
     * 100 characters.
     */
    public String getSummary();
    /**
     * Enumeration for different types of events. Note that the CLAIM_EXPIRE,
     * START and STOP event types are deprecated and should not be used in new
     * development.
     */
    public enum Type {
        CREATE,
        ASSIGN,
        CLAIM,
        RETURN,
        TAKE_ACTION,
        STEP_CHANGE,
        SET_USER_PROPERTY,
        //PROPERTY_SET_LOCKSTATE,
        SUSPEND,
        RESUME,
        SET_ERROR,
        CLEAR_ERROR,
        COMPLETE,
        ABORT,
        REACTIVATE,
        SET_CURRENT_STEP,
        SET_SYSTEM_PROPERTY,
        CLAIM_EXPIRE_81X, // deprecated
        STEP_EXPIRE,
        TASK_EXPIRE,
        START_81X, // deprecated
        STOP_81X;  // deprecated
        public String getValue() {
            return this.name();
        }
        public static Type getFromOrdinal(int ordinal) {
            Type[] types = Type.class.getEnumConstants();
            for (int i=0; i < types.length; i++) {
                if (types[i].ordinal() == ordinal) {
                    return types[i];
                }
            }
            return types[0];
        }
    };
}
Notes: A listener must be coded with the following points in mind:

So, developers should only register listeners as critical when it is really necessary to the business that the listener receives all events it intends to consume. Also, developers should take precautions not to throw exceptions unless it is absolutely necessary to do so.

Installing EventListeners

See the Deploying Custom Event Listeners section for details.

Event Listener and Run-As Identity

Synchronous listeners (critical or non-critical) run under the identity on the thread that created the event being handled. Asynchronous listeners run under the identity configured for the TaskEventDispatcher MDB (by default this is anonymous, but can be overridden via the WebLogic Server Administration Console).

Note: System administrators should carefully examine any Worklist application containing .listener files. They should scrutinize any .listener file that registers itself as a synchronous user, as this listener will run under the identity of the user making the updates to the tasks that caused the events. Thus, the listener code can do anything the original user could do. Only trusted code should be allowed to deploy as a synchronous listener.

 


EventHandler Modules

The EventHandler module is a configuration module that is used to define configuration for the delivery of reporting, email notification, and other types of events.

An EventHandler module is deployed as part of a Worklist host application. It is a WebLogic Server configuration module that can be added to the host application to configure the delivery of events for tasks of the types defined in that host application.

The configuration of an event handler includes some general information as well as listener-type-specific elements. An event handler defines:

An event subscription also contains general and listener-type-specific elements. An event subscription defines:

The listener type-specific sections are defined for the needs of these types of listeners:

At runtime, event subscriptions in a handler are collected together with the event subscriptions from all other handlers in the application. These subscriptions are additive with each other. The event configuration in a given event handler is merged additively with the configuration of all other event handlers (including the default Worklist event handlers).

Event Handler File

An EventHandler is defined in a .handler file as an XML document. The XML content must conform to a schema for EventHandlers. EventHandler (.handler) files can be edited in the Workshop IDE using the EventHandler editor plug-in.

Note: Once a .handler file exists in an application, you may edit the configuration it contains using Worklist Console. This allows you to make your best judgement for the event types that must be handled, and then fine tune the handling at runtime.

Deployment

The EventHandler module is deployed when the host application (and task plans it contains) are deployed. At runtime, the various listener types consult the deployed EventHandlers to determine if an event is of interest to their type of listener, and if so deliver it to their endpoint. This delivery is controlled and configured by the listener-type-specific configuration in the handler.

For more information, see the Deploying Event Handlers section.

Event Handler Editors

Worklist Console provides a facility to edit event handlers, and the listener-type-specific configuration within them. For more information, see "Changing the Event Handler Details" in Worklist Administration in Using Working Console.

The Workshop for WebLogic IDE has no direct support for editing .handler or .listener, etc. files. However, the IDE registers these types of files as custom modules. This allows them to be deployed automatically (with no other action on the part o the user). However, editing these files is manual, and should be done according to the examples given in the respective sections of this document.

Default Event Configuration

Worklist deploys a single default event handler, called WorklistEventHandler that defines event delivery for the following types of listeners:

This file is included as part of the Worklist J2EE application library and is a global event handler (applies to all task plans). You can use Worklist Console to change the default event configuration in this handler. For more information, see "Changing the Event Handler Details" in Worklist Administration in Using Working Console.

 


Default Reporting Store

An event-based mechanism that allows a customer to detect changes to the Worklist runtime repository and make corresponding changes to their own reporting repository is available. Worklist does not dictate or be aware of, in any way, the design of the customer reporting repository. In addition, an interface for customer-provided reporting repositories is defined to make task history information available to Worklist clients.

For out-of-the-box reporting use, Worklist provides a default reporting repository and a default reporting facility that allows you to glean some amount of long-term reporting information without having to implement your own reporting repository.

Note: If your application requires information that is not easily gleaned from the default reporting repository, consider defining your own reporting repository. You can attach this repository to Worklist events and even disable the default reporting store completely, if desired. For more information, see Task Change Events.

Task History

For some types of tasks, where a task has been is equally as important as where the task was defined to go. In most of these cases, the task can be loosely defined to move through some broadly scoped steps, but in general, the actual path of the task, the human actors it will be associated with, and so on are not known in detail ahead of time.

An example of such a task is the handling of customer service trouble tickets or the resolution and tracking of defects in a software or hardware product. In these cases, there is a general procedure put in place to track all types of trouble and defects, but each case has its own significantly unique considerations. In such a case, the history of a task may be critical to helping human actors that subsequently encounter the task or are associated with it. For example, a software defect may at first appear to be in one software component, but upon investigation by a software engineer attached to the first component, it is determined the defect is in a second software component. Here, the analysis and findings of the first engineer may be critical to the second engineer in finding and fixing the problem.

Task History Provider

A Task History interface is defined as:

package com.bea.wli.worklist.api.config;
/**
 * Defines a provider of task history information. This provider
 * may be registered for all task plans or selected task plans.
 */
public interface TaskHistoryProvider {
    public void setProperties(Property[] props);
    public void initialize()
        throws ManagementException;
    public TaskHistory getTaskHistory(String taskId)
        throws RemoteException, ManagementException;
    public void destroy()
        throws ManagementException;
}
public interface TaskHistory {
    /**
     * Get an iterator over all events that have occurred for this task
     * from the startDate to the endDate (inclusive).
     */
    public TaskEventIterator
    getTaskEvents(Date startDate, Date endDate)
        throws RemoteException, ManagementException;
    /**
     * Reconstruct the state of a task on a given date. The provider
     * should use its history information up to the given date in 
     * constructing the returned TaskData. If providers do not support this
     * they should throw NotSupportedException.
     */
    public TaskData getTaskAtDate(Date date)
        throws NotSupportedException, ManagementException, RemoteException;
}
public interface TaskEventIterator {
    public boolean hasNext()
        throws RemoteException;
    public TaskChangeEvent next()
        throws RemoteException, ManagementException;
}

When you implement the custom reporting repository, you may optionally define your own TaskHistoryProvider implementation and then register that implementation globally or for selected task plans. The TaskHistoryProvider is registered by deploying a TaskHistoryProvider custom module. For more information see the Deploying Custom Task History Providers section for details.

Worklist provides the WorklistTaskUser.getTaskHistory() method as a front-end to the server-side TaskHistoryProvider.

public interface WorklistTaskUser {
    ...
    /**
     * Is the task plan associated with a task history
     * provider. If this returns true, you can reasonably expect to get
     * non-empty results from getTaskEvents().
     */
    public boolean isTaskHistoryProvided(TaskPlan taskType);
    /**
     * Get all events that have occurred, sorted by date, on this task
     * from the start date to the end date (inclusive). If no task history
     * is available for this task, an empty array is returned. This may
     * happen if the date range falls in during a period of inactivity
     * for the task, or it may indicate that no task history information
     * is being captured for tasks of this type.
     */
    public TaskEvent[] getTaskEvents(String taskId,
                                     Date startDate, Date endDate)
        throws ManagementException, RemoteException;
    ...
}

Worklist provides a TaskHistoryProvider implementation for the Worklist default reporting store. This default TaskHistoryProvider is registered automatically as a global provider, thus applying to all task plans.

At most one TaskHistoryProvider can be associated with any given task plan. If a custom TaskHistoryProvider is registered for a given task plan, that provider becomes the sole provider of task history information for that task plan (replacing the default/global TaskHistoryProvider). Registering a global TaskHistoryProvider replaces the default TaskHistoryProvider. This should be done with caution, and only when a global TaskEventListener has been registered that will take responsibility for capturing task events need to generate the task history for all task plans.

Reporting Store Design

The reporting store is intended to provide at least the level of reporting functionality available in Worklist 8.1 with the added benefit of being able to do queries over live and historical data (in 8.1, records that had been archived had to be queried separately from the information in the Worklist runtime store).

The technical design goal of the reporting store is to store as much data as possible with the smallest processing overhead as possible. It is assumed that the reporting process or user interface can absorb the processing hit for focused tasks in the reporting store more easily than the runtime can absorb the processing hit across all events it generates.

Business Goals

The business goal of the reporting store is to support the following general types of queries:

Database Schema

The following diagram shows an example of the reporting store schema. For a few examples of how the reporting store may be used to retrieve data to satisfy the business goals set out in Business Goals, see Sample Queries.

Figure 5-2 Reporting Store Schema

Reporting Store Schema

Sample Queries

Example: Show me everything that has happened with task XYZ to date

select * from WLI_WORKLIST_RPT_TASKEVENT
  where TASK_ID='XYZ'
  order by TIMESTAMP

Example: Who took the action to move task XYZ from step A to step B, and when was it taken?

select e.CALLER, e.TIMESTAMP
  from WLI_WORKLIST_RPT_TASKEVENT e, WLI_WORKLIST_RPT_TASKACTION a
  where e.TASK_ID = 'XYZ' and
        e.TASK_EVENT_ID = a.TASK_EVENT_ID and
        a.OLD_STEP_NAME = 'A' and a.NEW_STEP_ID = 'B'

Example: How long is it taking for Bob to complete CustomerRefund tasks?

select avg(complete.TIMESTAMP - create.TIMESTAMP)
  from WLI_WORKLIST_RPT_TASKEVENT create, WLI_WORKLIST_RPT_TASKEVENT complete,
       WLI_WORKLIST_RPT_TASKINFO info
  where create.EVENT_TYPE = 'TaskCreate' and
        complete.EVENT_TYPE = 'TaskComplete' and
        create.TASK_ID = complete.TASK_ID and
        info.TASK_ID = create.TASK_ID and
        info.TASK_TYPE_ID = 'CustomerTasks:1.0/CustomerRefund:1.0'
        info.OWNER = 'Bob'
  group by info.TASK_ID

Example: How many CustomerRefund tasks have been processed this week?

select count(TASK_ID)
  from WLI_WORKLIST_RPT_TASKEVENT
  where EVENT_TYPE = 'TaskComplete' and
        TASK_TYPE_ID = 'CustomerTasks:1.0/CustomerRefund:1.0' and
        TIMESTAMP > [long millis for start of week] and
        TIMESTAMP < [long millis for end of week]
  group by EVENT_TYPE

Example: Based on the expense reports for this quarter, how much money has been spent on hotel expenses?

Note: This query might use the Hotel Charges property of ExpenseReport tasks. The task plan designer would have to foresee the need to query on hotel expenses and create a field to hold those expenses apart from other information in the expense report document. Let us assume you want to know your hotel expenses were between the first and last day of the month.
select event.TASK_ID, prop.VALUE, event.TIMESTAMP
  from WLI_WORKLIST_RPT_TASKEVENT event, WLI_WORKLIST_RPT_TASKPROPERTY prop
  where event.EVENT_TYPE = 'TaskComplete' and
        event.TASK_TYPE_ID = 'EmployeeTasks:1.0/ExpenseReport:1.0' and
        prop.TASK_ID = event.TASK_ID and
        event.TIMESTAMP > [long millis for the start of month] and
        event.TIMESTAMP < [long millis for the end of month] and
        prop.NAME = 'Hotel Charges'
  order by event.TASK_ID, event.TIMESTAMP
Note: It is assumed here that you cannot actually calculate the amount of the hotel expense in each ExpenseReport task. Some database types allow you to convert field values from one data type to another. In databases that support such conversions, you could convert Hotel Charges to a float or currency value and then group and sum the resulting values.

Reporting Event Filtering

Producer-side filtering allows you to exclude certain event types from being reported into the default reporting store. For more information, see Controlling Events Per-Task Plan.

A reporting event configuration section is defined within the EventHandler event subscription to indicate if the event types for the subscription should be delivered to the default reporting store. If no such configuration is present for a subscription, no reporting events are delivered as a result of handling that subscription at runtime. If no subscription in any handler for the host application defines that a given event types should be delivered to the default reporting store, then the event is ignored by the default reporting store.

The default Worklist event handler defines all event types to be of interest to the default reporting store. If required, this default configuration may be changed using Worklist Console.

 


Email Notification

Worklist provides a measure of control over business tasks involving human interaction. Tasks are associated with human actors in several ways:

These human actors often need to be notified of changes to the tasks they are associated with. The most common example of this is when a task is assigned to a group of human actors. In this case, those actors may not be immediately aware that they have had a task assigned to them. If they regularly have to open Worklist User Portal (or any custom task UI) refresh it regularly, they will see their tasks appear in their Assigned Tasks portlet in the Worklist User Portal. However, if they do not regularly use and refresh their Worklist User Portal, then an alternate method of notification is needed. Most people today have an email client open at all times. Thus, email becomes a powerful tool for notification.

This section provides information about how Worklist support notifications via email.

Worklist allows configuration of email notifications from the task plan definition. This configuration involves choosing the event types that cause an email notification, the actors to whom those notifications should go, and what the body of the email will look like.

Specifying Actors for Email Notification

You can specify actors in terms of their affinity to a task (Creator, Owner, Claimant, Assignee), or by user name (no direct association with the task). In addition, you can use custom email recipient calculators to allow the email address of an actor or actors to be calculated dynamically at runtime. For more information, see Deploying EMail Recipient Calculators.

By specifying a task affinity or user name as an email recipient, you implicitly take responsibility for ensuring that these actors have email addresses configured for them in Worklist Console. For more information, see "Setting the E-mail Address of a User" in Worklist Administration in Using Worklist Console.

Note: The email notification subsystem logs warnings whenever it cannot find the email address for a configured actor.

Email Recipient Calculators

For cases where the proper recipient for a given type of email notification cannot be known in advance, the email address can be calculated to be used dynamically at runtime.

These calculators allow a user to augment the To: list of the e-mail messages that are sent to recipients in response to a Worklist Task Event. For example, there is a Task Plan that defines how to handle the approval of purchase orders. In cases of very expensive purchase orders, perhaps the controller for a business unit should be notified via e-mail when the purchase order is created. The default email notification configuration cannot express this requirement. In this case, the user could implement the EmailRecipientCalculator interface, place the implementation in the application that hosts the Task Plan and then have the implementation return the controller's e-mail address any time a CREATE Task Event is received where the PurchaseOrderAmount property is over a given amount.

Note: The calculator implementation can be parameterized at deployment time (by a custom module descriptor, .email file, in the host application) to allow the amount to be specified, or to pass in some address for an external service that can be used to look up the amount.
/**
 * Defines a pluggable implementation of a calculator that can produce the
 * email addresses of actors that are to receive email notifications for
 * a given TaskEvent. This interface is really only intended to provide a 
 * simple facility for augmenting the To: list for emails that are already 
 * getting sent from the default email subsystem in Worklist. If you need 
 * to control the subject, body, or other attributes of emails being sent, 
 * you should define your own custom event listener from which you can send * custom emails.
 * <p>
 * Implementations of this interface MUST provide a public
 * default (no arg) constructor. Implementations must make no assumptions 
 * about the lifecycle of their instances nor their relationship to other 
 * instances. Lifecycle is controlled entirely via the initialize() and
* destroy() methods.
 */
public interface EmailRecipientCalculator {
    /**
     * Set any properties configured for this EmailRecipientCalculator in the
     * custom module that deployed it. This method is only called if properties
     * are available (e.g. specified in the deployment descriptor for the custom
     * module). Note this method (if called at all) is called prior to the
     * call to the initialize lifecycle method.
     * @param properties
     */
    public void setProperties(Property[] properties);
    /**
     * Initialize any resources needed to start calculating email addresses in
     * getEmailRecipientsForEvent().
     * @throws com.bea.wli.worklist.api.ManagementException
     */
    public void initialize()
        throws ManagementException;
    /**
     * Destroy this instance and release any resources obtained in initialize
     * or during calls to getEmailRecipientsForEvent().
     * @throws ManagementException
     */
    public void destroy()
        throws ManagementException;
    /**
     * Calculate the email addresses for any actors that should receive email
     * notification for the given event. If no email notifications are to be
     * sent, this method may return null or an empty array.
     * @param event The event for which email notifications are to be sent.
     * @param currentRecipients This is a set of email addresses to which
     *        the email for this event will already be sent. This set is a
     *        copy of the set that will be used to populate the To: list on the
     *        email, so adding/removing items in this set has no effect.
     * @return An array of email addresses for actors that should get email
     *         notifications in response to the event. These actors will
     *         receive an email with a pre-determined subject and body. The
     *         body will contain a URL to the task that caused this event. The
     *         URL may optionally be calculated by installing a
     *         TaskURLCalculator.
     * @throws ManagementException If any error occurs calculating recipients.
     *         This error will be logged to the server log, but otherwise
     *         will not alter the handling of this event.
     * @see TaskURLCalculator
     */
    public String[] getEmailRecipientsForEvent(TaskEvent event,
                                               Set<String> currentRecipients)
        throws ManagementException;
}

To install an email recipient calculator implementation that implements the above interface, define a custom module in your host application that defines the class name of the implementation and any properties needed to initialize that instance before it can calculate recipients. For more information, see Deploying EMail Recipient Calculators.

EMail Delivery Mechanism

E-mail is sent using the JavaMail API. The mail session that is to be used for sending the e-mails is indicated in the Worklist System Instance configuration in Worklist console. This configuration is the name of a mail session configured in WebLogic Server (via the WebLogic Server Administration Console). For more information, see "Changing the Worklist System Instance Configuration" in Worklist Administration in Using Worklist Console, Create a Mail Session in The WebLogic Server Administration Console help and Programming JavaMail with WebLogic Server in Developing Applications with WebLogic Server.

Make sure that the JavaMail session must define the name of the SMTP host to which Worklist will deliver emails. This is done by specifying a session property of the name:

mail.smtp.host=<SMTP Host name or IP Address>

For example, a Microsoft Exchange server or ISP SMTP server can be specified here.

Note: The email notification subsystem logs errors when a configured JavaMail session cannot be found at runtime.

Event Types

Worklist can deliver a number of different event types in response to changes on a task. Worklist defines the most common events of interest to human actors to be:

If no specific event type configuration is given for a task plan, the above list is assumed. Task plan designers and Worklist administrators are free to modify this list as required by their specific business cases.

By default, each of the above event types are configured to be sent to a specific set of human actors associated with the task that was changed. The following table describes the default e-mail recipients for each event type and the email template that is used to create the subject and body of the e-mail. Again, task plan designers and Worklist administrators are free to modify this configuration if needed.

By default, email templates are localized to the default locale of the server (not the e-mail client). Event notifications can be configured to be delivered in other locales, if required.

Note: This default configuration specifies a JavaMail session with a JNDI name of WorklistMailSession. You must define a JavaMail session of this name in order to utilize this default configuration. For more information, see Create a Mail Session in The WebLogic Server Administration Console help

Calculating Task URLs

Each email template (body template) shown in the previous table has a marker for a URL that may be used to navigate directly to the task UI of the task. The TaskURLCalculator interface is available for this purpose.

public interface TaskURLCalculator {
    public URL getURLForTask(String taskId)
        throws ManagementException;
}

A custom module that allows individual Worklist host applications to specify their own custom URL calculator. This is necessary if the Worklist host application also provides a custom Worklist or Task UI that requires a specific or custom URL for navigation to the task. Only one TaskURLCalculator can be registered at any given time.

Worklist provides a default TaskURLCalculator implementation that calculates URLs appropriate for use with the default Worklist User Portal.

A new method is available in WorklistTaskUser in the Worklist API to calculate the URL for a task (using the registered or default calculator)

public interface WorklistTaskUser {
    ...
    public URL getURLForTask(String taskId)
        throws ManagementException, RemoteException;
    ...
}

Email Templates

Table 5-1 lists the text templates that are used for as the subject and body of the e-mail message. Information from the underlying Worklist task event is substituted into the templates to generate the full text that goes into the e-mail message.

These templates are defined in the WorklistEMail text formatter file and are localized into any language supported by WebLogic Integration. If required, you can customize these template by directly editing the WorklistEmailTextFormatter.properties file located in the worklist.jar file.

Email Notification Configuration and EventHandler Modules

The configuration for email notification is defined in a listener-type-specific section of an EventHandler module. This module is also used to define configuration for reporting events and other types of events. For more information, see EventHandler Modules.

The email configuration of an event handler maps task event types to the actors who should receive e-mail notification when events of a given type occur. Mapping event types to actors for any task plan augments (not replaces) the default event notification configuration for that task plan. In other words, the email configuration given in the configuration module is merged with the default configuration for a given task plan.

 


MessageBroker and JPD Integration

Worklist may be used directly from a Worklist Portal, or via Worklist API. One of the primary interfaces to Worklist in this API is the Worklist controls. Worklist controls are primarily hosted within WebLogic Integration Process Definitions (JPD). Controls are sufficient to ensure a robust integration in cases where the JPD instantiates or knows the task IDs of the tasks it will work with. However, sometime the JPD does not know the task IDs it will work with, and in some cases, a user may want the creation or modification of a task to cause the creation of a JPD instance.

In such scenarios, JPD MessageBroker is used to deliver messages to a JPD from event channels. These channels can have a semantic attached to them and allow message filters to control delivery of these messages to consumers. This is an ideal mechanism to allow existing JPD instances to become aware of task instances as needed (by responding to events of a given type from a given task plan for instance). This mechanism, via static subscriptions, also allows a JPD instance to be created in response to a task event.

Worklist Channel

Worklist delivers events to a MessageBroker channel when changes occur to tasks of any type using the following Worklist channel:

/WorklistEvent

So, a JPD may define a MessageBroker static or dynamic subscription using the /WorklistEvent channel name (and any relevant header fields in a filter) to receive Worklist events it is interested in. This channel is a rawdata channel and has messages with a body that is a serialized TaskEvent instance. The actual runtime type of the TaskEvent instance depends on the event type for the event. For more information, see Task Change Events.

You need to deserialize the bytes of the MessageBroker message using ObjectInputStream.readObject(), and cast the resulting object to a TaskEvent. An example JPD is given below:

@com.bea.wli.jpd.Process(
        process="<process name=\"WorklistControlStatefulControlReceive\">\n" +
                "  <clientRequest name=\"Client Request\" method=\"clientRequest\"/>\n" +
                "</process>"
)
public class HandleTaskEvent implements com.bea.jpd.ProcessDefinition
{
    public String _x0;
    static final long serialVersionUID = 1L;
    
    @MessageBroker.StaticSubscription(channelName = "/WorklistEvent",
                                      messageMetaData="{meta}",
                                      messageBody = "{body}")
    public void clientRequest(TaskEventMetadataDocument meta,
                              Object body)
        throws IOException, ClassNotFoundException {
        RawData rawData = (RawData)body;
        ByteArrayInputStream bais = new ByteArrayInputStream(rawData.byteValue());
        ObjectInputStream ois = new ObjectInputStream(bais);
        TaskEvent event = (TaskEvent)ois.readObject();
        System.out.println("## Got TaskEvent in JPD: " + event.getSummary());
        this._x0 = event.getSummary();
    }
}

Event Types

Events are delivered to the Worklist MessageBroker channel as they occur in the Worklist engine. The MessageBroker listener is capable of sending any defined task event to MessageBroker. By default, only the following events are delivered via MessageBroker

Event delivery may be customized on a per-task plan or global basis. For more information, see MessageBroker Event Configuration and EventHandler Modules.

Message Header Fields

Each task event posted to MessageBroker is posted to a single Worklist channel. This message has a number of header fields to allow filtering of messages at the point of consumption in the JPD. The various message header fields are:

This message header fields are delivered as an XMLBean event metadata object of the type

com.bea.wli.worklist.xml.TaskEventMetadataDocument

as defined in the Worklist.xsd schema

Note: This schema is available from Workshop for WebLogic IDE by creating a Worklist application with a utility project and adding system schemas to that project. The XMLBean is available in the worklist-client.jar public jar file).
Example Process:
package process;
import java.util.Date;
import com.bea.jpd.ProcessDefinition;
import com.bea.jpd.JpdContext;
import org.apache.beehive.controls.api.bean.Control;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
@com.bea.wli.common.XQuery(prolog="declare namespace ns0 = \"http://www.bea.com/wli/worklist/xml\";")
@com.bea.wli.jpd.Process(process = 
"<process name=\"StaticMBWithNoXQuery\">" + 
"  <clientRequest name=\"Subscription\" method=\"subscription\"/>" + 
"  <perform name=\"Print Event Info\" method=\"perform\"/>" + 
"</process>")
public class StaticMBWithAndFilterValue implements ProcessDefinition {
    public com.bea.wli.worklist.xml.TaskEventMetadataDocument _e1;
    public com.bea.data.RawData _rd;
    @com.bea.wli.jpd.Context
    JpdContext context;
    static final long serialVersionUID = 1;
    @com.bea.wli.control.broker.MessageBroker.StaticSubscription(xquery = "fn:concat($metadata/ns0:taskPlanId,  $metadata/ns0:eventType)", filterValueMatch = "/Loans/Loan Approval:1.0:LoanAppCREATE", channelName = "/WorklistEvent", messageBody = "{x0}", messageMetaData = "{x1}")
    public void subscription(com.bea.data.RawData x0,
                             com.bea.wli.worklist.xml.TaskEventMetadataDocument x1) {
        // #START: CODE GENERATED - PROTECTED SECTION - you can safely add code above this comment in this method. #//
        // input transform
        // parameter assignment
        this._rd = x0;
        this._e1 = x1;
        // #END  : CODE GENERATED - PROTECTED SECTION - you can safely add code below this comment in this method. #//
    }
    public void perform() throws Exception {
        Date dt = new Date();
        StringBuffer sb = new StringBuffer();
        sb.append("\n\n[" + dt.getTime() + "]\t ++++++++ StaticMBWithAndFilterValue : GOT MB Event in JPD with Filter Value Match +++++ " + new Date());
        sb.append("[" + dt.getTime() + "]\t Event Info: " + this._e1);
        sb.append("[" + dt.getTime() + "]\t Is Raw Data NULL? " + (this._rd == null ? true : false));
        sb.append("[" + dt.getTime() + "]\t ----------------------------------------------------------------------------");
        try {
            ByteArrayInputStream baos =
                new ByteArrayInputStream(_rd.byteValue());
            ObjectInputStream ois = new ObjectInputStream(baos);
            TaskEvent event = (TaskEvent)ois.readObject();
            sb.append("[" + dt.getTime() + "]\t Event object summary: " + event.getSummary());
        } catch (Exception e) {
            sb.append("[" + dt.getTime() + "]\t Event object (error): " + e.toString());
        }
        System.out.println(sb);
    }
}     

MessageBroker Event Configuration and EventHandler Modules

Task events are delivered to MessageBroker via an EventHandler. By default, Worklist defines a single EventHandler with a default event configuration. For more information, see Event Types. However, Worklist administrators can modify this configuration globally or for specific task plans using Worklist Console. For more information, see "Changing the Event Handler Details" in Worklist Administration in Using Worklist Console.

The configuration for MessageBroker event delivery is defined as part of an EventHandler module. This module is also used to define configuration for email notification, reporting events and other types of events. For more information, see EventHandler Modules.

The MessageBroker event configuration of an event handler indicates task event types that are to be sent to MessageBroker. Indicating an event type within the MessageBroker event configuration enables that event for delivery via MessageBroker. Enabling event types for any task plan augments (not replaces) the default event notification configuration for that task plan. In other words, the configuration given in the configuration module is merged with the default configuration for a given task plan.

 


Custom Task Event Listeners

Worklist allows you to listen to runtime events (see Task Change Events) and take any action in response to those events. Your listener can request synchronous or asynchronous event delivery and can request to be registered as a critical or non-critical listener. For more information, see Event Dispatch Modes (Quality of Service).

Your custom task event listener implements the TaskEventListener interface (see Task Change Events). You can then register your listener by including a .listener file in your application. For more information, see Deploying Custom Event Listeners.

 


Custom Assignment Handlers

You can assign users to specific tasks using Worklist. These default assignment facilities should be sufficient for a large number of assignment scenarios. However, in some cases, the default assignment facilities in Worklist may not be enough. In these cases, you can provide a custom assignment handler that allows you to control the assignment process for your tasks.

Custom assignment handlers take full control of the assignment process. They may be appropriate in cases where special load balancing or availability checking logic is required. A custom assignment handler can be applied to specific task plans or globally to all task plans.

Note: Only one global assignment handler can be present at any given time, so this option should be used carefully. Applying a global assignment handler overrides any previously applied handler (including the default Worklist assignment handler).

A custom assignment handler must implement the following interface:

com.bea.wli.worklist.api.config.AssignmentHandler

and must provide a public default (no arg) constructor. Custom assignment handlers must not expect to control how many instances of the handler that are instantiated nor the lifecycle of any given instance. The lifecycle of a given handler instance is controlled via the initialize() and destroy() lifecycle methods.

A summary of this interface is as follows. For more information about the complete interface, see the Worklist API JavaDoc available at http://download.oracle.com/docs/cd/E13214_01/wli/docs92/worklist.javadoc/index.html

/**
 * Describes an assignment algorithm that can be used to assign a task
 * of a given type to users as candidates for claiming the task. This algorithm
 * may optionally choose to claim the task in the name of a designated
 * candidate user. Implementations of this interface MUST provide a public
 * default (no arg) constructor. Implementations must make no assumptions about
 * the lifecycle of their instances nor their relationship to other instances.
 * Lifecycle is controlled entirely via the initialize() and destroy() methods.
 */
public interface AssignmentHandler {
    /**
     * Request object passed to an assignment handler when Worklist is
     * requesting the assignment of a task.
     */
    public class Request {
        private String _taskId;
        private String[] _candidateUserIds;
        private CandidateListHandling _handling;
        private boolean _availabilityCheckEnabled;
        private WorkloadRequest _workloadRequest;
        ...
    }
    /**
     * Response object an assignment handler returns describing the assignment
     * decision that has been made for the task.
     */
    public interface Response {
        /**
         * Assignee list as calculated by the assignment handler, or
         * null to accept the assignee list that was used to generate the
         * candidate user id list.
         */
        AssigneeDefinition[] getNewAssigneeList();
        /**
         * The user id of the user who should be made the claimant of the task,
         * or null if no claimant was chosen.
         */
        String getClaimant();
    }
    /**
     * Set any properties that were configured with this assignment
     * handler. Note that the value should be obtained from the default value
     * of the provided properties.
     * @param props
     */
    public void setProperties(Property[] props);
    /**
     * Initialize this instance in preparation for calls on assignTask()
     * @throws ManagementException if any error occurs that would prevent
     *         this instance from properly handling calls to assignTask()
     */
    public void initialize()
        throws ManagementException;
    /**
     * Make assignment decisions for the given task. The given list of
     * candidate claimant user names may be used by this method, or ignored.
     * The candidate user name list is derived from the assignee list for the
     * current step of the task, or the assignee list passed to
     * WorklistTaskAdmin.assignTask(). This method MUST NOT actually modify
     * the task to reflect the claimant it chooses (if any) or cause any
     * other side effects to the task. Assignment decisions are communicated
     * back to the caller via the returned Response instance.
     * @param request A Request instance containing the information needed to
     *        assign a task.
     * @return A Response instance indicating any newly calculated assignee
     *         list to be used for this task, and any claimant chosen for the
     *         task.
     * @throws AssignmentException if any authorization or logical error happens
     *         during assignment.
     * @throws ManagementException If any other error occurs during assignment.
     */
    public Response
    assignTask(Request request)
        throws AssignmentException, ManagementException;
    ...
    /**
     * Release any resources obtained in the call to initialize or calls to
     * assignTask().
     * @throws ManagementException If any error occurs releasing resources.
     */
    public void destroy()
        throws ManagementException;
}

The assignment handler implementation is registered by deploying an assignment handler configuration module within the Worklist host application. For more information, see Deploying Custom Assignment Handlers.

At runtime, a registered assignment handler is invoked via its assignTask method. It receives a candidate list, the ID of the task that is being assigned and parameters that are intended as hints to guide the execution of the custom assignment handler. The handling and enableLoadBalancingAvailabilityCheck parameters may be used by the assignment handler, but this is not required.

The assignment handler is free to make use of any information in the task (including its type, properties, and so on.) in making assignment and claim decisions. Any decision made by the handler is communicated back to the caller of the assignTask() method via the returned Response instance.

The Response object can define a newly calculated assignee list (null indicates the old list should still be used) and any claimant for the task (null means no claimant was chosen). The assignment handler must not attempt to force the claiming of the task (for example, by calling WorklistTaskUser.claimTask()) or call any method in the Worklist API that causes side effects on the task.

The assignment handler's assignTask() method is used by Worklist to handle applying any updated assignee list or claimant information to the task after the return.

Note: An assignment handler configuration module can specify configuration properties that may be used by the assignment handler at runtime. Such properties may parameterize and control the behavior of the handler at runtime. Any configuration properties specified for the assignment handler are provided to the assignment handler implementation at the time the handler instance is created via a call to the setProperties() method. For more information, see Deploying Custom Assignment Handlers.

  Back to Top       Previous  Next