JBoss Community

Re: Integrating jBPM 5 into web application - architecture

created by Sandra Renaud in jBPM - View the full discussion

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 :

Reply to this message by going to Community

Start a new discussion in jBPM at Community