4.14. Domain-specific Tasks
custom work items or custom service nodes.
- work item handler
- The work item handler is a Java class that defines how to execute the custom task type. (Just like all Process elements, Tasks are executed in the Execution Engine (more precisely in the Task Engine), which contains a work item handler class, that defines how to handle the particular work item. Therefore, to allow the Execution Engine to execute your custom work item, you need to create a work item handler class for the custom work item and register it with the Execution Engine.)
- work item definition
- The work item definition defines how the custom task is presented (its name, icon, parameters).
Note
4.14.1. Work item definition
what part (the how part is implemented as a class that implements WorkItemHandler).
- Web Process Designer
- A work item definition is defined as an MVEL construct in a project resource (the custom work item node will appear on the palette; refer to Section 4.14.1.2, “Creating a work item definition”).
- JBoss Developer Studio Process Designer
- The BPMN2 <task> or <task>-type elements can be modified to work with
WorkItemHandlerimplementations.To do so, create aWID_NAME.widfile under theMETA-INFdirectory. (Example:$PROJECT_HOME/src/main/resources/META-INF/WID_NAME.wid). The contents of this file will be the same as the ones that you will create as if under Business Central (Web Process Designer). If there are any icons, create these icons under a folder$PROJECT_HOME/src/main/resources/, and store the icon images files iniconsfolder.Once you save this file, you can use your custom service task with the JBDS Process Designer. You can find your task in the category which is defined inWID_NAME.widfile.
- name unique in the given work item set
- description with arbitrary text
- version number
- parameters with a set of work item parameters used as properties
- displayName used in the palette
- icon with the path to the icon file for the Task element
- category the node is added to in the palette (if the defined category does not exit, a new category is created)
- defaultHandler with the class that implements the WorkItemHandler class and is used to execute the work item
- dependencies the defaultHandler requires for its execution
Important
Example 4.7. Calendar work item definition
import org.drools.core.process.core.datatype.impl.type.StringDataType;
[
[
"name" : "Google Calendar",
"description" : "Create a meeting in Google Calendar",
"version" : "1.0",
"parameters" : [
"FilePath" : new StringDataType(),
"User" : new StringDataType(),
"Password" : new StringDataType(),
"Body" : new StringDataType()
],
"displayName" : "Google Calendar",
"icon" : "calendar.gif",
"eclipse:customEditor" : "org.drools.eclipse.flow.common.editor.editpart.work.SampleCustomEditor",
"category" : "Google",
"defaultHandler" : "org.jbpm.process.workitem.google.calendar.GoogleCalendarWorkItemHandler",
"dependencies" : [
]
]
]4.14.1.1. Work item handler
org.kie.api.runtime.process.WorkItemHandler interface.
Note
- The jbpm-bpm2 module in the org.jbpm.bpmn2.handler package contains the following work item handlers:
- ReceiveTaskHandler (for the BPMN <receiveTask> element)
- SendTaskHandler (for the BPMN <sendTask> element)
- ServiceTaskHandler (for the BPMN <serviceTask> element)
- The jbpm-workitems module in packages within org.jbpm.process.workitem contains work item handlers, some of which are listed below:
- ArchiveWorkItemHandler creates a ZIP archive (it takes a list of files as its parameter, which are included in the archive)
- WebServiceWorkItemHandler
- TransformWorkItemHandler
- RSSWorkItemHandler
- RESTWorkItemHandler
- JavaInvocationWorkItemHandler
- JabberWorkItemHandler
- JavaHandlerWorkItemHandler
- FTPUploadWorkItemHandler
- ExecWorkItemHandler
- EmailWorkItemHandler
executeWorkItem() and abortWorkItem() methods as defined by the WorkItemHandler interface. These are called during runtime on work item execution.
- Information about the Task are extracted from the WorkItem instance.
- The work item business logic is performed.
- The Process instance is informed that the work item execution finished (completed or aborted) using the respective method of the WorkItemManager:
- for completing execution:
import org.kie.api.runtime.process.WorkItemManager; ... WorkItemManager.completeWorkItem(long workItemId, Map<String, Object> results)
- for aborting execution:
import org.kie.api.runtime.process.WorkItemManager; ... WorkItemManager.abortWorkItem(long workItemId, Map<String, Object> results)
WorkItemHandler.abortWorkItem() before it is completed Section 5.1.4.1, “Asynchronous execution”.
4.14.1.2. Creating a work item definition
- In the Project Explorer panel (the
Project Authoringperspective), select your project. - In the perspective menu, click → .
- In the Create new dialogue box, define the definition details:
- In the Name field provide the definition name.
- Click the button.
- A new tab with the work item definition template opens up in the Work Item editor.
Note
Whenever a user creates a new business process in some project, the default WID will be created. Users will be able to reuse or directly alter the WID file whenever necessary. In addition, there will always be a default WID once the BPMN process is created. - In the editor, edit the source of the MVEL work item definition. The definition is stored in the current package.If you are planning to add the work item using the service repository as opposed to adding the work item handler to the classpath, make sure to define its dependencies, category, etc.If you are creating the definition out of Business Central, your project directory structure should be similar to
PROJECT_NAME/src/main/resources/PACKAGE_NAME/WID_NAME.wid(visible in the Repository view).Example 4.8. Example wid file
import org.drools.core.process.core.datatype.impl.type.StringDataType; import org.drools.core.process.core.datatype.impl.type.ObjectDataType; [ [ "name" : "MyTask", "parameters" : [ "MyFirstParam" : new StringDataType(), "MySecondParam" : new StringDataType(), "MyThirdParam" : new ObjectDataType() ], "results" : [ "Result" : new ObjectDataType("java.util.Map") ], "displayName" : "My Task", "icon" : "" ] ] - Upload and assign an icon to the Work Item:
- Click → .
- In the Create new Uploaded file dialogue box, define the resource name and make sure to include the file's extension in the name. Click the option to locate and upload the file (
pngorgif, 16x16 pixels). Click . - Make sure your mouse is positioned within the blank " " of the icon parameter:
"icon" : " "
Click the Select icon to add drop-down and click the icon file. The icon path will appear within the parameter:"icon" : "ExampleIcon.png"
Note
The path to describe the location of an icon can be relative or absolute, as long as the icon can be found using one of these methods. For example, the following paths are supported:"icon" : "ExampleIcon.png" (icon in the same folder as the .wid file) "icon" : "com/test/ExampleIcon.png" (icon relative to .wid file location) "icon" : "../test/ExampleIcon.png" (icon relative to .wid file location) "icon" : "/HR/src/main/resources/ExampleIcon.png" (absolute path to icon)
- In the Process Designer, check if your work item is available in the palette.
4.14.1.3. Creating a work item handler
- Create a maven project with your implementation of a work item handler with the required business logic. Make sure to call the
completeWorkItem()function to finish the business logic execution and add thekie-apiartifact with the6.x.x.redhat-xversion value as the project dependency.Example 4.9. Notification work item handler
package com.sample; import org.kie.api.runtime.process.WorkItem; import org.kie.api.runtime.process.WorkItemHandler; import org.kie.api.runtime.process.WorkItemManager; public class NotificationWorkItemHandler implements WorkItemHandler { public void executeWorkItem(WorkItem workItem, WorkItemManager manager) { String from = (String) workItem.getParameter("From"); String to = (String) workItem.getParameter("To"); String message = (String) workItem.getParameter("Message"); String priority = (String) workItem.getParameter("Priority"); /* Send email. The ServiceRegistry class is an example class implementing the task business logic. */ EmailService service = ServiceRegistry.getInstance().getEmailService(); service.sendEmail(from, to, "Notification", message); /* Notify manager that work item has been completed. The completeWorkItem() call completes the work item execution. */ manager.completeWorkItem(workItem.getId(), null); } public void abortWorkItem(WorkItem workItem, WorkItemManager manager) { // Do nothing, notifications cannot be aborted } }Important
If theWorkItemManageris not notified about the work item completion, the process engine is never notified that your work item node has completed. - Register the work item handler in the
DEPLOY_DIR/business-central.war/WEB-INF/classes/META-INF/CustomWorkItemHandlers.conffile.TheCustomWorkItemHandlers.conffile contains information like the following:[ "Log": new org.jbpm.process.instance.impl.demo.SystemOutWorkItemHandler(), "WebService": new org.jbpm.process.workitem.webservice.WebServiceWorkItemHandler(ksession), "Rest": new org.jbpm.process.workitem.rest.RESTWorkItemHandler() ]
Notice the "Rest" value in the previous file. This indicates theWorkItemHandleris capable of interacting with REST services. It supports both secured/authenticated and open/not authenticated services.This REST value is defined in the project's WID file in the following manner:[ "name" : "Rest", "parameters" : [ //Url - Mandatory resource location to be invoked. "Url" : new StringDataType(), //Method - Defaults to GET and is the HTTP method that will be executed. "Method" : new StringDataType(), //ConnectionTimeout - Defaults to 60 seconds for the connection timeout. "ConnectTimeout" : new StringDataType(), //ReadTimeout - Defaults to 60 seconds for the read timeout. "ReadTimeout" : new StringDataType(), //Username - The username for authentication that overrides the one given on handler initialization. "Username" : new StringDataType(), //Password - The password for authentication that overrides the one given on handler initialization. "Password" : new StringDataType() ], "results" : [ "Result" : new ObjectDataType(), ], "displayName" : "REST", "icon" : "defaultservicenodeicon.png" ]The configuration options displayed about must be given via the work item parameter. The authentication information can be given on handler initialization, but it can be overridden via the work item parameter. - Compile the project. The resulting JAR file should be placed in (
DEPLOY_DIR/business-central.war/WEB-INF/lib/). - Restart the server.
Registering via kmodule.xml
CustomWorkItemHandlers.conf is to configure them with kmodule.xml. This is beneficial in that it avoids a complete server restart.
- Register the work item handler in the menu path
PROJECT_NAME/src/main/resources/META-INF/kmodule.xml - Make sure the work item handler is given as a MVEL expression; for example,
new org.jbpm.wih.CustomHandler()or FQCN expression:org.jbpm.wih.CustomHandler. - Compile the project. Upload the work item handler JAR into Business Central via the Artifact Repository. Then add it as a dependency for the project where the user wants to use this handler.
4.14.1.4. Registering a Work Item handler
WorkItemHandlers are registered in the ksession automatically. However, in order for them to be used in embedded mode, the WorkItemManager registers WorkItemHandler instances. Likewise, in the example below, the NotificationWorkItemHandler needs to be registered in order for it to be used with a process containing a Notification work item:
- Register the work item handler like the following:
/* Create the drools name of the <task> and the custom work item handler instance */ KieSession kieSession = kieBase.newKieSession(); ksession.getWorkItemManager().registerWorkItemHandler( "Notification", new NotificationWorkItemHandler() );
- Look at the BPMN2 syntax for the process. The previous registration example would appear as follows:
<?xml version="1.0" encoding="UTF-8"?> <definitions id="Definition" xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" ... xmlns:tns="http://www.jboss.org/drools"> ... <process isExecutable="true" id="myCustomProcess" name="Domain-Specific Process" > ... <!-- The tns:taskName attribute in the <task> node is necessary for the WorkItemManager to be able to see which WorkItemHandler instance should be used with which task or work item. --> <task id="_5" name="Notification Task" tns:taskName="Notification" > ...
Note
4.14.2. Service repository
Important
Note
4.14.2.1. Importing from a service repository
- Open your Process in the Web Process Designer.
- In the editor menu, click the
button.
- In the Service Repository Connection window, define the location of the repository on the location input line and click .

Figure 4.25. Establishing connection to a service repository
- Double-click the asset to import it.
Important
DEPLOY_DIRECTORY/business-central.war/WEB-INF/classes/META-INF/CustomWorkItemHandler.conf file. If a work item is not registered in the file, it will not be available for use.
4.14.2.2. Setting up a service repository
index.conf file in its root directory.
Repository configuration file
index.conf file must be located in the root directory of the service repository. It contains a list of any directory within the repository that are to be considered directories of the service repository.
Example 4.10. index.conf
Email FileSystem ESB FTP Google Java Jabber Rest RSS Transform Twitter
index.conf file so as to serve as a directory or work item resources. Note that the hierarchical structure of the repository is not shown when browsing the repository using the import wizard, as the category property in the configuration file is used for that.
Work items and their resources
- A work item configuration file is a file with the same name as the parent directory (for example,
Twitter.conf) that contains details about the work item resources in the service repository. The file is an extension of the work item definition file (refer to Section 4.14.1, “Work item definition”). Note, that the configuration file must contain references to any dependencies the work item handler requires. Optionally, it can define the documentation property with a path to documentation and category which defines the category the custom work item is placed under in the repository.Example 4.11. Work item configuration file
import org.drools.core.process.core.datatype.impl.type.StringDataType; [ [ "name" : "Twitter", "description" : "Send a twitter message", "parameters" : [ "Message" : new StringDataType() ], "displayName" : "Twitter", "eclipse:customEditor" : "org.drools.eclipse.flow.common.editor.editpart.work.SampleCustomEditor", "icon" : "twitter.gif", "category" : "Communication", "defaultHandler" : "org.jbpm.process.workitem.twitter.TwitterHandler", "documentation" : "index.html", //Every work item definition should specify dependencies even if it doesn't have one. "dependencies" : [] [ "file:./lib/jbpm-twitter.jar", "file:./lib/twitter4j-core-2.2.2.jar" ] ] ] - All resources referenced in the work item configuration file: icon, documentation, and dependencies.
4.14.3. User Task calls
TaskClient class. The API is intended for developers to allow direct managing of the lifecycle of User Tasks. End users are advised to use the Business Central web application for User Task management.
taskId: ID of the target Task instance usually extracted from the currently selected User Task in the user task list in the user interfaceuserId: ID of the user that is executing the action called by the method; usually the ID of the user that is logged in
org.kie.api.task.TaskService class:
void start(long taskId, String userId); void stop(long taskId, String userId); void release(long taskId, String userId); void suspend(long taskId, String userId); void resume(long taskId, String userId); void skip(long taskId, String userId); void delegate(long taskId, String userId, String targetUserId); void complete(long taskId, String userId, Map<String, Object> results);
Example 4.12. Starting and completing a simple user task
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.process.ProcessInstance;
import org.kie.api.task.TaskService;
import org.kie.api.task.model.TaskSummary;
....
KieSession ksession = runtimeEngine.getKieSession();
TaskService taskService = runtimeEngine.getTaskService();
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
// John is assigned a task and he completes it
List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
TaskSummary task = list.get(0);
logger.info("John is executing task {}", task.getName());
taskService.start(task.getId(), "john");
taskService.complete(task.getId(), "john", null);
...
4.14.4. Actor assignment calls
ActorID or the GroupID parameter, which define the users who can or should execute the User Tasks. It is in the Task List of these users the Task appears.
Example 4.13. Adding user Kris and group Developers on taskSession
EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.task");
TaskService taskService = new TaskService(emf, SystemEventListenerFactory.getSystemEventListener());
TaskServiceSession taskSession = taskService.createSession();
// registering new user and group:
taskSession.addUser(new User("Kris"));
taskSession.addGroup(new Group("Developers"));admin roles as well as your custom roles.
Example 4.14. Requesting the list of tasks the user is a potential owner of
List<String> groups = new ArrayList<String>();
groups.add("sales");
taskClient.getTasksAssignedAsPotentialOwner("sales-rep", groups, "en-UK", taskSummaryHandler);Important
Administrator is the administrator of each Task. It is therefore recommended to always define at least user Administrator when registering the list of valid users with the User Task service.
4.14.4.1. Connecting to custom directory information services
- Create an implementation of the UserGroupInfoProducer interface and provide your own custom callback (see Section 4.14.5.1, “Connecting to LDAP”) and user info implementations according to the needs from the producer.This implementation must be annotated with the @Selectable qualifier for it to be found by Business Central. The listing below shows an example LDAP implementation:
import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Alternative; import javax.enterprise.inject.Produces; import org.jbpm.services.task.identity.LDAPUserGroupCallbackImpl; import org.jbpm.services.task.identity.LDAPUserInfoImpl; import org.jbpm.shared.services.cdi.Selectable; import org.kie.api.task.UserGroupCallback; import org.kie.internal.task.api.UserInfo; @ApplicationScoped @Alternative @Selectable public class LDAPUserGroupInfoProducer implements UserGroupInfoProducer { private UserGroupCallback callback = new LDAPUserGroupCallbackImpl(true); private UserInfo userInfo = new LDAPUserInfoImpl(true); @Override @Produces public UserGroupCallback produceCallback() { return callback; } @Override @Produces public UserInfo produceUserInfo() { return userInfo; } } - Package your custom implementations (the
LDAPUserGroupInfoProducer, theLDAPUserGroupCallbackImpland theLDAPUserInfoImplclasses from the example above) into a bean archive (jar with META-INF/beans.xml so it can be found by CDI container). Add this jar file tobusiness-central.war/WEB-INF/lib. - Modify
business-central.war/WEB-INF/beans.xmland add the implementation (LDAPUserGroupInfoProducerfrom the example above) as an alternative to be used by Business Central.<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd"> <alternatives> <class>com.test.services.producer.LDAPUserGroupInfoProducer</class> </alternatives> </beans>Warning
The use of a customUserGroupInfoProducerrequires internal APIs, which may be broken in future releases. Using a customUserGroupInfoProduceris not recommended or supported by Red Hat. - Restart your server and your custom callback implementation should now be used by Business Central.
4.14.5. LDAP connection
- ldap.bind.user: username used to connect to the LDAP server (optional if LDAP server accepts anonymous access)
- ldap.bind.pwd: password used to connect to the LDAP server (optional if LDAP server accepts anonymous access)
- ldap.user.ctx: context in LDAP with user information (mandatory)
- ldap.role.ctx: context in LDAP with group and role information (mandatory)
- ldap.user.roles.ctx: context in LDAP with user group and role membership information (optional; if not specified, ldap.role.ctx is used)
- ldap.user.filter: filter used to search for user information; usually contains substitution keys {0}, which are replaced with parameters (mandatory)
- ldap.role.filter: filter used to search for group and role information, usually contains substitution keys {0}, which are replaced with parameters (mandatory)
- ldap.user.roles.filter: filter used to search for user group and role membership information, usually contains substitution keys {0}, which are replaced with parameters (mandatory)
- ldap.user.attr.id: attribute name of the user ID in LDAP (optional; if not specified,
uidis used) - ldap.roles.attr.id: attribute name of the group and role ID in LDAP (optional; if not specified
cnis used) - ldap.user.id.dn: user ID in a DN, instructs the callback to query for user DN before searching for roles (optional, by default
false) - java.naming.factory.initial: initial conntext factory class name (by default
com.sun.jndi.ldap.LdapCtxFactory) - java.naming.security.authentication: authentication type (possible values are
none,simple,strong; by defaultsimple) - java.naming.security.protocol: security protocol to be used; for instance
ssl - java.naming.provider.url: LDAP url (by default
ldap://localhost:389; if the protocol is set tosslthenldap://localhost:636)
4.14.5.1. Connecting to LDAP
- programatically: build a
Propertiesobject with the respective LDAPUserGroupCallbackImpl properties and createLDAPUserGroupCallbackImplwith thePropertiesobject as its parameter.Example 4.15.
import org.kie.api.PropertiesConfiguration; import org.kie.api.task.UserGroupCallback; ... Properties properties = new Properties(); properties.setProperty(LDAPUserGroupCallbackImpl.USER_CTX, "ou=People,dc=my-domain,dc=com"); properties.setProperty(LDAPUserGroupCallbackImpl.ROLE_CTX, "ou=Roles,dc=my-domain,dc=com"); properties.setProperty(LDAPUserGroupCallbackImpl.USER_ROLES_CTX, "ou=Roles,dc=my-domain,dc=com"); properties.setProperty(LDAPUserGroupCallbackImpl.USER_FILTER, "(uid={0})"); properties.setProperty(LDAPUserGroupCallbackImpl.ROLE_FILTER, "(cn={0})"); properties.setProperty(LDAPUserGroupCallbackImpl.USER_ROLES_FILTER, "(member={0})"); UserGroupCallback ldapUserGroupCallback = new LDAPUserGroupCallbackImpl(properties); UserGroupCallbackManager.getInstance().setCallback(ldapUserGroupCallback); - declaratively: create the
jbpm.usergroup.callback.propertiesfile in the root of your application or specify the file location as a system property:-Djbpm.usergroup.callback.properties=FILE_LOCATION_ON_CLASSPATHMake sure to register the LDAP callback when starting the User Task server.#ldap.bind.user= #ldap.bind.pwd= ldap.user.ctx=ou\=People,dc\=my-domain,dc\=com ldap.role.ctx=ou\=Roles,dc\=my-domain,dc\=com ldap.user.roles.ctx=ou\=Roles,dc\=my-domain,dc\=com ldap.user.filter=(uid\={0}) ldap.role.filter=(cn\={0}) ldap.user.roles.filter=(member\={0}) #ldap.user.attr.id= #ldap.roles.attr.id=

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.