Bonita Engine Event handlers
An event handler is an extension to the engine that is configured to run when a specified event occurs.
For Enterprise, Performance, Efficiency, and Teamwork editions only. |
You can add event handlers for several purposes and you can configure which events you want to catch. We strongly recommend that you add only appropriate handlers and carefully code the handler filters to handle only those events that you are interested in.
An event is a change to any object in the database (user, activity, processDefinition,… ). You can create an event handler to track any change to any object in the database and take the appropriate action. For example:
-
Catch PROCESSINSTANCE_CREATED to detect that a process instance has started, and notify the process supervisor.
-
Catch FLOWNODE_INSTANCE_CREATED to detect that a human task is available, and send email to all the users elligible to perform it.
-
Catch HIDDEN_TASK_CREATED to detect that a service task becomes available, and start an external system that is required to complete the task.
At the end of this page there is a list of all the events.
In a cluster environment, Event handlers must be Serializable (implements Serializable and have all its fields serializable or transient) because they are shared with other nodes of the cluster. |
Example: deploy an event handler
This example shows an event handler that detects changes in the state of activity instances.
create a maven project for event handler jar
pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.bonitasoft.example</groupId>
<artifactId>event-handler-example</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<bonita.version>{varVersion}.0</bonita.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.bonitasoft.engine</groupId>
<artifactId>bonita-server</artifactId>
<version>${bonita.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Create event handler class:
Create a class that implements SHandler<SEvent>
.
src/main/java/org/bonitasoft/example/EventHandlerExample.java:
package org.bonitasoft.example;
import java.util.UUID;
import org.bonitasoft.engine.events.model.SEvent;
import org.bonitasoft.engine.events.model.SHandler;
import org.bonitasoft.engine.events.model.SHandlerExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EventHandlerExample implements SHandler<SEvent> {
private static Logger logger = LoggerFactory.getLogger(EventHandlerExample.class);
private final String identifier = UUID.randomUUID().toString();
public EventHandlerExample() {
}
@Override
public void execute(SEvent event) throws SHandlerExecutionException {
logger.info("ExampleHandler: executing event {}", event.getType())
// add your business logic here
}
@Override
public boolean isInterested(SEvent event) {
logger.info("ExampleHandler - event {} - asks if we are interested in handling this event instance",
event.getType())
// add your business logic here
// for this example purpose, assume we are always interested
return true;
}
@Override
public String getIdentifier() {
return identifier;
}
}
Deploy jar
-
Build event-handle-example-1.0-SNAPSHOT.jar using
mvn clean install
maven command. -
Copy event-handle-example-1.0-SNAPSHOT.jar in webapps/bonita/WEB-INF/lib/ folder (for tomcat bundle)
Register an event handler
An event handler is registered on an event by adding an entry to the appropriate map. The list of handlers registered can be extended in the bonita-tenant-sp-custom.xml
file:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- add event handler bean definition -->
<bean id="myEventHandlerExample" class="org.bonitasoft.example.EventHandlerExample">
</bean>
<bean id="eventHandlers" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="targetMapClass">
<value>java.util.HashMap</value>
</property>
<property name="sourceMap">
<map>
<entry key="PROCESSINSTANCE_STATE_UPDATED" value-ref="myEventHandlerExample"/>
</map>
</property>
</bean>
</beans>
Test it
Restart web server and run a basic process and check bonita log file in folder tomcat/logs:
INFOS: THREAD_ID=78 | HOSTNAME=gt | ExampleHandler: event PROCESSINSTANCE_STATE_UPDATED - asks if we are interested in handling this event instance ... INFOS: THREAD_ID=78 | HOSTNAME=gt | ExampleHandler: executing event PROCESSINSTANCE_STATE_UPDATED
Filter an event
An event handler contains a filter, isInterested
, which detects the relevant instances of the event.
The example below shows how to use the State Id of a flow node to filter for a particular state (in this case, failed).
Flownode State Ids are defined in the subclasses of org.bonitasoft.engine.core.process.instance.api.states.FlowNodeState
.
There is no exhaustive list; the set of states is extensible without notice.
public boolean isInterested(SEvent event) {
boolean isInterested = false;
// Get the object associated with the event
Object eventObject = event.getObject();
// Check that event is related to a task
if (eventObject instanceof SFlowNodeInstance) {
SFlowNodeInstance flowNodeInstance = (SFlowNodeInstance) eventObject;
// Verify that state of the task is failed. See
// FailedActivityStateImpl
isInterested = (flowNodeInstance.getStateId() == 3);
}
return isInterested;
}
Event handlers are recursive, that is, if an event handler itself modifies something and triggers an event, the relevant event handler is called. This means you might need to include loop detection in your event handler.
Event list
This is a snapshot of the events used in the Engine.
Service |
Events |
ActivityInstanceServiceImpl |
ACTIVITYINSTANCE_CREATED, HUMAN_TASK_INSTANCE_ASSIGNEE_UPDATED, ACTIVITYINSTANCE_STATE_UPDATED, ACTIVITY_INSTANCE_TOKEN_COUNT_UPDATED, HIDDEN_TASK_CREATED, HIDDEN_TASK_DELETED, PENDINGACTIVITYMAPPING_CREATED, PENDINGACTIVITYMAPPING_DELETED |
ActorMappingServiceImpl |
ACTOR_CREATED, ACTOR_DELETED, ACTOR_UPDATED, ACTOR_MEMBER_CREATED, ACTOR_MEMBER_DELETED |
CategoryServiceImpl |
CATEGORY_CREATED, CATEGORY_DELETED, CATEGORY_UPDATED |
CommandServiceImpl |
COMMAND_CREATED, COMMAND_DELETED, COMMAND_UPDATED |
SCommentServiceImpl |
COMMENT_CREATED, COMMENT_DELETED |
ConnectorInstanceServiceImpl |
CONNECTOR_INSTANCE_CREATED, CONNECTOR_INSTANCE_DELETED, CONNECTOR_INSTANCE_STATE_UPDATED, CONNECTOR_INSTANCE_UPDATED |
DependencyServiceImpl |
DEPENDENCY_CREATED, DEPENDENCYMAPPING_CREATED, DEPENDENCY_DELETED, DEPENDENCYMAPPING_DELETED, DEPENDENCY_UPDATED, DEPENDENCYMAPPING_UPDATED |
DocumentMappingServiceImpl |
DOCUMENTMAPPING_CREATED, DOCUMENTMAPPING_DELETED, DOCUMENTMAPPING_UPDATED |
SEventInstanceServiceImpl |
EVENT_INSTANCE_CREATED, EVENT_TRIGGER_INSTANCE_CREATED, EVENT_TRIGGER_INSTANCE_DELETED, MESSAGE_INSTANCE_CREATED, MESSAGE_INSTANCE_DELETED, MESSAGE_INSTANCE_UPDATED |
ExternalIdentityMappingServiceImpl |
EXTERNAL_IDENTITY_MAPPING_CREATED, EXTERNAL_IDENTITY_MAPPING_DELETED |
FlowNodeInstanceServiceImpl |
FLOWNODE_INSTANCE_DELETED |
GatewayInstanceServiceImpl |
GATEWAYINSTANCE_CREATED, GATEWAYINSTANCE_HITBYS_UPDATED, GATEWAYINSTANCE_STATE_UPDATED |
IdentityServiceImpl |
GROUP_CREATED, GROUP_DELETED, GROUP_UPDATED, METADATA_CREATED, METADATA_DELETED, METADATA_UPDATED, METADATAVALUE_CREATED, METADATAVALUE_DELETED, METADATAVALUE_UPDATED, ROLE_UPDATED, ROLE_CREATED, ROLE_DELETED, USER_UPDATED, USER_CREATED, USER_DELETED, USER_CONTACT_INFO_UPDATED, USER_CONTACT_INFO_CREATED, USER_CONTACT_INFO_DELETED, USERMEMBERSHIP_UPDATED, USERMEMBERSHIP_CREATED, USERMEMBERSHIP_DELETED |
JobServiceImpl |
JOB_DESCRIPTOR_CREATED, JOB_DESCRIPTOR_DELETED, JOB_PARAMETER_CREATED, JOB_PARAMETER_DELETED, JOB_LOG_CREATED, JOB_LOG_DELETED |
JobWrapper |
JOB_COMPLETED, JOB_EXECUTING |
ProcessDefinitionServiceImpl |
PROCESSDEFINITION_CREATED, PROCESSDEFINITION_DELETED, PROCESSDEFINITION_DEPLOY_INFO_UPDATED, PROCESSDEFINITION_IS_DISABLED_UPDATED, PROCESSDEFINITION_IS_ENABLED_UPDATED, PROCESSDEFINITION_IS_RESOLVED_UPDATED |
ProcessInstanceServiceImpl |
PROCESS_INSTANCE_CATEGORY_STATE_UPDATED, PROCESSINSTANCE_CREATED, PROCESSINSTANCE_DELETED, PROCESSINSTANCE_STATE_UPDATED, PROCESSINSTANCE_UPDATED |
ProfileServiceImpl |
PROFILE_CREATED, PROFILE_DELETED, PROFILE_UPDATED, ENTRY_PROFILE_CREATED, ENTRY_PROFILE_DELETED, ENTRY_PROFILE_UPDATED, PROFILE_MEMBER_DELETED |
ReportingServiceImpl |
REPORT_CREATED, REPORT_DELETED |
SupervisorMappingServiceImpl |
SUPERVISOR_CREATED, SUPERVISOR_DELETED |
ThemeServiceImpl |
THEME_CREATED, THEME_DELETED, THEME_UPDATED |