In previous chapter we implemented a jBPM project to understand simple hello world. In this tutorial we will try to understand what is jBPM human task.
1. Tech Stack
We should have the following software to create/import a jBPM Project.
- Java 1.7 or higher version
- Eclipse IDE for Enterprise Java Developers
- jBPM7 plugin should install with eclipse IDE
2. Human Task
jBPM supports a special human task node inside processes for modeling this interaction with human users. This human task node allows process designers to define the properties related to the task that the human actor needs to execute, like for example the type of task, the actor(s), or the data associated with the task.
jBPM also includes a so-called human task service, a back-end service that manages the life cycle of these tasks at runtime. The jBPM implementation is based on the WS-HumanTask specification. Note however that this implementation is fully pluggable, meaning that users can integrate their own human task solution if necessary.
In order to have human actors participate in your processes
- you first need to include human task nodes inside your process to model the interaction with human actors,
- Integrate a task management component (like for example the WS-HumanTask based implementation provided by jBPM) and
- Have end users interact with a human task client to request their task list and claim and complete the tasks assigned to them.
3. Let’s Start
For our example here, we will create a process with a human task node and then execute/call a human task using org.kie.api.task.TaskService. We will create the Eclipse Maven project as follows
Download counts: 513
- After downloading, unzip the project.
- Go to Eclipse IDE -> File -> Import -> Maven -> Existing Maven project -> Select the project.
Added two human task nodes that are task 1 and task 2 in the BPM process
If you double-click on the Task 1 node, the corresponding node properties window will appear (see below). Let us see what these properties do
- Actors: The actors that are responsible for executing the human task. A list of actor id’s can be specified using a comma (‘,’) as separator.
- Group: The group id that is responsible for executing the human task. A list of group id’s can be specified using a comma (‘,’) as separator.
- Name: The display name of the node.
- TaskName: The name of the human task. This name is used to link the task to a Form. It also represent the internal name of the Task that can be used for other purposes.
- Comment: A comment associated with the human task. Here you can use expressions.
- Content: The data associated with this task.
- Priority: An integer indicating the priority of the human task.
- Skippable: Specifies whether the human task can be skipped, i.e., whether the actor may decide not to execute the task.
- On entry and on exit actions: Action scripts that are executed upon entry and exit of this node, respectively.
Properties window of the Human Task 1 node, the task is assigned to ‘john’
Properties window of the Human Task 2 node, the task is assigned to ‘mary’
ProcessMain.java is a standalone program and contains the code to execute BPMN files. All BPMN files are loaded into kiebase as processes. We need to pass the respective process IDs to the jBPM engine to execute them.
ProcessMain.java class has processTask method. It performs a human task using org.kie.api.task.TaskService.
package com.hi.techpoints;
import java.util.List;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeEnvironmentBuilder;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.manager.RuntimeManagerFactory;
import org.kie.api.task.TaskService;
import org.kie.api.task.model.TaskSummary;
import org.kie.internal.runtime.manager.context.EmptyContext;
import org.kie.test.util.db.PersistenceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* jBPM Human Task program
*
* @author elavarasan_pk
*/
public class ProcessMain {
private static final Logger log = LoggerFactory.getLogger(ProcessMain.class);
public static final void main(String[] args) throws Exception {
// 1. Create ProcessMain object
ProcessMain processMain = new ProcessMain();
// 2. Load *.bpmn file into the knowledge base
KieBase kbase = processMain.readKnowledgeBase();
// 3. Create a jBPM RuntimeManager
RuntimeManager runtimeManager = processMain.createRuntimeEnvironment(kbase);
// 4. Get RuntimeEngine out of manager
RuntimeEngine runtimeEngine = runtimeManager.getRuntimeEngine(EmptyContext.get());
// 5. Create KieSession from runtimeEngine - already initialized *.bpmn file on the environment
KieSession ksession = runtimeEngine.getKieSession();
// 6. Start a humantaskprocess instance here
ksession.startProcess("com.hi.techpoints.process.humantaskprocess");
log.info("Process started ...");
// 7. Process human task
processMain.processTask(runtimeEngine);
// 8. At Last dispose the runtime engine
runtimeManager.disposeRuntimeEngine(runtimeEngine);
System.exit(0);
}
private KieBase readKnowledgeBase() throws Exception {
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
return kContainer.getKieBase("kbase");
}
public RuntimeManager createRuntimeEnvironment(KieBase kbase) {
Properties properties = new Properties();
properties.put("driverClassName", "org.h2.Driver");
properties.put("className", "org.h2.jdbcx.JdbcDataSource");
properties.put("user", "sa");
properties.put("password", "");
properties.put("url", "jdbc:h2:tcp://localhost/~/jbpm-db");
properties.put("datasourceName", "jdbc/jbpm-ds");
PersistenceUtil.setupPoolingDataSource(properties);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa");
RuntimeEnvironmentBuilder builder = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder().entityManagerFactory(emf).knowledgeBase(kbase).persistence(false);
return RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(builder.get());
}
private void processTask(RuntimeEngine runtimeEngine) {
// 1. Get Task service
TaskService taskService = runtimeEngine.getTaskService();
// 2. Let john execute Task 1
List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
TaskSummary task = list.get(0);
log.info("John is executing task: {}", task.getName());
taskService.start(task.getId(), "john");
taskService.complete(task.getId(), "john", null);
// 3. Let mary execute Task 2
list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
task = list.get(0);
log.info("Mary is executing task: {}", task.getName());
taskService.start(task.getId(), "mary");
taskService.complete(task.getId(), "mary", null);
}
}
Basically, org.kie.api.task.TaskService has a life cycle to execute the human task. See the link to learn more about TaskService
After running the program, we get the output as