Hello Lisa and Anand,
I can't give you my application but this is the relevant code concerning the task management :
I use maven so I have these dependencies in the POM :
<!-- jbpm -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>5.4.0.Final</version>
</dependency>
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-bpmn2</artifactId>
<version>5.4.0.Final</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-flow</artifactId>
<version>5.4.0.Final</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jbpm</groupId>
<artifactId>jbpm-human-task-core</artifactId>
<version>5.4.0.Final</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
Then, the two java classes :
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import org.drools.KnowledgeBase;
import org.drools.SystemEventListenerFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.Resource;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.EnvironmentName;
import org.drools.runtime.StatefulKnowledgeSession;
import org.jbpm.process.workitem.email.EmailWorkItemHandler;
import org.jbpm.task.Group;
import org.jbpm.task.User;
import org.jbpm.task.identity.UserGroupCallbackManager;
import org.jbpm.task.service.TaskService;
import org.jbpm.task.service.TaskServiceSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import static org.junit.Assert.*;
@Stateless
@LocalBean
public class KnowledgeSessionProducer implements Serializable{
private static final long serialVersionUID = -4494168896880405667L;
private Logger log = LoggerFactory.getLogger(KnowledgeSessionProducer.class);
private KnowledgeRuntimeLogger logger;
@PersistenceUnit(unitName = "org.jbpm.task")
private EntityManagerFactory emf;
public @PostConstruct void init(){
log.debug("init of KnowledgeSessionProducer ...");
TaskService taskService = new TaskService(emf, SystemEventListenerFactory.getSystemEventListener());
TaskServiceSession taskSession = taskService.createSession();
// Add users
@SuppressWarnings("rawtypes")
Map vars = new HashMap();
InputStream usersin = KnowledgeSessionProducer.class.getResourceAsStream( "/LoadUsers.mvel" );
if(usersin != null) {
Reader reader = new InputStreamReader( usersin );
@SuppressWarnings("unchecked")
Map<String, User> users = ( Map<String, User> ) TaskService.eval( reader, vars );
log.debug("Users to load in db : ...");
for ( User user : users.values() ) {
taskSession.addUser( user );
log.debug(" - "+user);
}
}
InputStream groupsin = KnowledgeSessionProducer.class.getResourceAsStream( "/LoadGroups.mvel" );
if(groupsin != null) {
Reader reader = new InputStreamReader( groupsin );
@SuppressWarnings("unchecked")
Map<String, Group> groups = ( Map<String, Group> ) TaskService.eval( reader, vars );
log.debug("Groups to load in db : ...");
for ( Group group : groups.values() ) {
taskSession.addGroup( group );
log.debug(" - "+group);
}
}
// try to get the usergroup callback properties
InputStream usergroupsin = KnowledgeSessionProducer.class.getResourceAsStream( "/jbpm.usergroup.callback.properties" );
if(usergroupsin != null) {
Properties callbackproperties = new Properties();
try {
// Properties.load(Reader) is a JDK 6 method
callbackproperties.load(usergroupsin);
UserGroupCallbackManager.getInstance().setCallbackFromProperties(callbackproperties);
System.out.println("Task service registered usergroup callback ...");
} catch (Exception e) {
System.out.println("Task service unable to register usergroup callback ...");
}
}
taskSession.dispose();
System.out.println("Task service started correctly!");
System.out.println("Task service running ...");
}
@Produces
@ApplicationScoped
public StatefulKnowledgeSession produceKnowledgeSession(){
log.debug("produce the KnowledgeSession ...");
//Create the knowledgeBase
/*This factory is used to build the knowledge base resources that are held collectively in KnowledgePackages.*/
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
//Add all processes to the knowledgeBuilder
List<Resource> resources = getProcessDefinitionList();
for (Resource resource : resources) {
kbuilder.add(resource, ResourceType.BPMN2);
}
/*Create a new KnowledgeBase from the knowledge packages that have been added to this builder.
* An exception is thrown if there are any errors.*/
// assertFalse( kbuilder.hasErrors() );
if ( kbuilder.hasErrors() ) {
log.error( kbuilder.getErrors().toString() );
}
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
/*Create a new StatefulKnowledgeSession using the default session configuration.
* Don't forget to dispose() session when you are done.
*
* StatefulKnowledgeSession is the most common way to interact with the engine.
* A StatefulKnowledgeSession allows the application to establish an iterative conversation with the engine,
* where the state of the session is kept across invocations.*/
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
logger = KnowledgeRuntimeLoggerFactory.newThreadedFileLogger(ksession, "loggerFile", 1000);
/*A work item manager is responsible for finding the right work item handler when a work item should be executed
* and should be notified when this work item has been completed (or aborted).
*
* Register the given handler for all work items of the given type of work
* This part is done in the LocalHumanTaskService*/
// ksession.getWorkItemManager().registerWorkItemHandler("Human Task", handler );
ksession.getEnvironment().set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
/*
* Register WorkItem Handler for Email
*/
//EmailWorkItemHandler emailHandler = new EmailWorkItemHandler();
//ksession.getWorkItemManager().registerWorkItemHandler("Email", emailHandler);
return ksession;
}
public KnowledgeRuntimeLogger getLogger(){
return this.logger;
}
private List<Resource> getProcessDefinitionList(){
List<Resource> resourceList = new ArrayList<>();
resourceList.add(ResourceFactory.newClassPathResource("workflows/MyFlow.bpmn2"));
/**
* TODO
* add all other process here
*/
return resourceList;
}
}
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Event;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import org.drools.runtime.StatefulKnowledgeSession;
import org.jboss.seam.security.Identity;
import org.drools.runtime.process.ProcessInstance;
import org.jbpm.task.Status;
import org.jbpm.task.query.TaskSummary;
import org.jbpm.task.service.local.LocalHumanTaskService;
import org.jbpm.workflow.instance.WorkflowProcessInstance;
import com.st.ams.tools.ClaimEventListener;
import com.ste.ws.authentication.seam.api.UserLDAP;
/**
* Linked to the task management view
*
*/
public @Named @SessionScoped class TaskManager implements Serializable{
private static final long serialVersionUID = 7768657778155604411L;
protected @Inject Identity identity;
private @Inject StatefulKnowledgeSession kSession;
private @Inject Event<ClaimEventListener> event;
private List<Status> listStatus = new ArrayList<Status>();
public org.jbpm.task.TaskService getTaskService(){
return LocalHumanTaskService.getTaskService(kSession);
}
private List<TaskSummary> userTaskList = new ArrayList<TaskSummary>();
private Map<String, List<TaskSummary>> groupTaskMap = new HashMap<String, List<TaskSummary>>();
private TaskSummary manageTask;
private List<String> groups;
public @PostConstruct void init(){
System.out.println("init task manager ...");
//Load user tasks
listStatus.clear();
listStatus.add(Status.Reserved);listStatus.add(Status.InProgress);
System.out.println("load task list for user : "+((UserLDAP)identity.getUser()).getUser().getLogin());
userTaskList = new ArrayList<TaskSummary>(getTaskService().getTasksAssignedAsPotentialOwnerByStatus(
((UserLDAP)identity.getUser()).getUser().getLogin(),
listStatus,
"en-UK"));
//Load groups and tasks for each group
groups = new ArrayList<String>();
for(String grp : ((UserLDAP)identity.getUser()).getUser().getGroups()){
groups.add(grp);
groupTaskMap.put(grp, getGroupTasks(grp));
}
}
public List<TaskSummary> getUserTaskList() {
if((userTaskList == null) || userTaskList.isEmpty()){
listStatus.clear();
listStatus.add(Status.Reserved);listStatus.add(Status.InProgress);
//Trick because UserGroupCallBackImpl is not properly implemented
//TODO correction
Set<TaskSummary> set = new HashSet<TaskSummary>(getTaskService().getTasksAssignedAsPotentialOwnerByStatus(
((UserLDAP)identity.getUser()).getUser().getLogin(),
listStatus,
"en-UK"));
userTaskList = new ArrayList<TaskSummary>(set);
}
return userTaskList;
}
/**
* In order to refresh the user task list
* This function allow to clear the content of the list
*/
public void clearUserTaskList(){
userTaskList.clear();
}
/**
* In order to refresh the groups task list
* This function allow to clear the content of all lists
*/
public void clearAllGroupTaskList(){
List<String> keys = new ArrayList<>(groupTaskMap.keySet());
for(String grp : keys){
clearGroupTaskList(grp);
}
}
/**
* In order to refresh the group task list
* This function allow to clear the content of the list
*/
public void clearGroupTaskList(String group){
groupTaskMap.put(group, null);
}
/**
* return all group tasks available for the user
* @return List<TaskSummary>
*/
public List<TaskSummary> getAllGroupTaskList() {
List<TaskSummary> allGroupTask = new ArrayList<TaskSummary>();
Iterable<List<TaskSummary>> mapValues = groupTaskMap.values();
for(List<TaskSummary> entry : mapValues){
allGroupTask.addAll(entry);
}
return allGroupTask;
}
public List<String> getUserGroups(){
if((groups == null) || groups.isEmpty()){
groups = new ArrayList<String>();
for(String grp : ((UserLDAP)identity.getUser()).getUser().getGroups()){
groups.add(grp);
}
}
return groups;
}
/**
* return tasks available for the group
* @param group
* @return List<TaskSummary>
*/
public List<TaskSummary> getGroupTaskList(String group){
if((groupTaskMap.get(group) == null) || groupTaskMap.get(group).isEmpty()){
groupTaskMap.put(group, getGroupTasks(group));
}
return groupTaskMap.get(group);
}
/**
* return tasks available for the group
* @param group
* @return List<TaskSummary>
*/
public List<TaskSummary> getGroupTasks(String group){
listStatus.clear();
listStatus.add(Status.Ready);
//Trick because UserGroupCallBackImpl is not properly implemented
//TODO correction
Set<TaskSummary> set = new HashSet<TaskSummary>(getTaskService().getTasksAssignedAsPotentialOwnerByStatus(group, listStatus, "en-UK"));
return new ArrayList<TaskSummary>(set);
}
public void removeGroup(String group){
groups.remove(group);
}
public void addGroup(String group){
if((group != null) && !group.isEmpty())
groups.add(group);
}
public void addGroupTask(String group){
groupTaskMap.put(group, getGroupTasks(group));
}
/**
* Start a new processInstance of an existing Process
* and set the variables of this instance
* @param processId, map of variables, id of the requestor
* @return ProcessInstance created
*/
public ProcessInstance startProcess(String processId, Map<String, Object> parameters){
ProcessInstance p = kSession.startProcess(processId,parameters);
return p;
}
/**
* Return the WorkflowProcessInstance associated to a Task
* This instance allow to access the map of variables
* @return WorkflowProcessInstance managed
*/
public WorkflowProcessInstance getWorkflowProcessInstance(long processInstanceId){
return (WorkflowProcessInstance)kSession.getProcessInstance(processInstanceId);
}
/**
* Start a new processInstance of an existing Process
* @param processId
* @return ProcessInstance created
*/
public ProcessInstance startProcess(String processId){
return kSession.startProcess(processId);
}
/**
* When a user claim a task, the task go to RESERVED state
* Then we call start and the task goes to IN_PROGRESS state
* and is not visible for others
* @param task
*/
public void claimTask(TaskSummary task){
addMessage("task "+task.getId()+" claimed");
setManageTask(task);
getTaskService().claim(task.getId(),
((UserLDAP)identity.getUser()).getUser().getLogin());
getTaskService().start(task.getId(), ((UserLDAP)identity.getUser()).getUser().getLogin());
event.fire(new ClaimEventListener());
}
/**
* return a task to group task
* @param task
*/
public void revokeTask(TaskSummary task){
addMessage("task "+task.getId()+" revoked");
setManageTask(task);
getTaskService().release(task.getId(),
((UserLDAP)identity.getUser()).getUser().getLogin());
}
public void completeTask(TaskSummary task, Object results){
getTaskService().completeWithResults(task.getId(),
((UserLDAP)identity.getUser()).getUser().getLogin(), results);
}
/**
* The current manage task
* @return TaskSummary
*/
public TaskSummary getManageTask() {
return manageTask;
}
/**
* Set the currently manage task
* (save it during the session)
* @param manageTask
*/
private void setManageTask(TaskSummary manageTask) {
this.manageTask = manageTask;
}
/**
* faces message rendered
* @param message to display
*/
public void addMessage(String summary) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, summary, null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
You have to implement the UserGroupCallBackImpl. (See the doc for that : http://docs.jboss.org/jbpm/v5.4/userguide/ch.human-tasks.html#d0e5419)
You have to register your implementation of usergroupcallback by creating a file jbpm.usergroup.callback.properties in the folder resources.
jbpm.usergroup.callback=com.your.package.path.with.dot.MyUserGroupCallbackImpl
https://community.jboss.org/servlet/JiveServlet/downloadImage/2-796530-20279/252-141/resources.png
The persistence.xml must be configured like this :