2.4. Events Listeners

The session provides methods for registering and removing listeners. A ProcessEventListener can be used to listen to process-related events, such as starting or completing a process, entering or leaving a node, etc. The different methods of the ProcessEventListener class are shown in the following example. An event object provides access to related information, such as the process instance and node instance linked to the event. This API can be used to register event listeners.

Example 2.2. ProcessEventListener Class

public interface ProcessEventListener {

  void beforeProcessStarted( ProcessStartedEvent event );
  void afterProcessStarted( ProcessStartedEvent event );
  void beforeProcessCompleted( ProcessCompletedEvent event );
  void afterProcessCompleted( ProcessCompletedEvent event );
  void beforeNodeTriggered( ProcessNodeTriggeredEvent event );
  void afterNodeTriggered( ProcessNodeTriggeredEvent event );
  void beforeNodeLeft( ProcessNodeLeftEvent event );
  void afterNodeLeft( ProcessNodeLeftEvent event );
  void beforeVariableChanged(ProcessVariableChangedEvent event);
  void afterVariableChanged(ProcessVariableChangedEvent event);

}
'Before' and 'after' events typically act like a stack, which means that any events that occur as a direct result of the previous event will occur between the 'before' and the 'after' of that event. For example, if a subsequent node is triggered as result of leaving a node, the 'NodeTriggered' events will occur in between the 'beforeNodeLeftEvent' and the 'afterNodeLeftEvent' of the node that is left (as the triggering of the second node is a direct result of leaving the first node). This triggering allows us to derive cause relationships between events more easily. Similarly, all 'NodeTriggered' and 'NodeLeft' events that are the direct result of starting a process will occur between the 'beforeProcessStarted' and 'afterProcessStarted' events. In general, if you just want to be notified when a particular event occurs, you should be looking at the 'before' events only (as they occur immediately before the event actually occurs). When only looking at the 'after' events, one might get the impression that the events are fired in the wrong order; however, this only occurs because the 'after' events are triggered as a stack ('after' events will only fire when all events that were triggered as a result of this event have already fired). 'After' events should only be used if you want to make sure that all processing related to this event has ended; for example, when you want to be notified when the starting of a particular process instance has ended, an 'after' event would be ideal.
Also note that not all nodes always generate 'NodeTriggered' or 'NodeLeft' events. Depending on the type of node, some nodes might only generate 'NodeLeft' events; other events might only generate 'NodeTriggered' events. 'Catching' intermediate events, for example, are not generating 'triggered' events (they are only generating 'left' events as they are not really triggered by another node, rather activated from outside). Similarly, 'throwing' intermediate events do not generate 'left' events (they only generate 'triggered' events, as they have not really left because they have no outgoing connection).
An event listener is provided that can be used to create an audit log (either to the console or a file on the file system). This audit log contains all the events that occurred at runtime. Note that these loggers should only be used for debugging purposes.
The following logger implementations are supported by default:

Table 2.1. Supported Loggers

Type Description Required Arguments
Console Output is written to the console when the logger is closed or the number of events reaches a predefined level. The knowledge session to be logged
File Output is written to a file in XML.
The knowledge session to be logged
The name of the log file to be created
Threaded File Output is written to a file after a specified interval; this is useful to visualize the progress in realtime during debugging.
The knowledge session to be logged
The name of the log file to be created
The interval (in milliseconds) to save the events.
The KnowledgeRuntimeLoggerFactory lets you add a logger to your session, as shown in the following example. You should always close the logger at the end of your application.

Example 2.3. KnowledgeRuntimeLogger

KnowledgeRuntimeLogger logger =
    KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "test" );
// add invocations to the process engine here,
// e.g. ksession.startProcess(processId);
...
logger.close();
The log file that is created by the file-based loggers contains an XML-based overview of all the events that occurred at runtime. It can be opened in JBoss Developer Studio using the Audit View in the Drools plug-in; through Audit View the events are visualized as a tree. Events that occur between the 'before' and 'after' events are shown as children of that event. The following screenshot shows a simple example where a process is started; this results in the activation of the Start node, an Action node and an End node, after which the process completes.
This image depicts an example process where a Start node and an End node are executed.