JBoss Community

Re: Human task API, how to move forward in the workflow ?

created by John Augusto Charnet in jBPM - View the full discussion

Hi Demian,

not sure what type of configuration you want me to share.

If you need any other information, please let me know.

 

Spring 3.0.1

Jbpm 5.1.0-Final

JPA 1.2

Hibernate 3.3.2.GA

/**
 * Todos os direitos reservados para Softway.
 *
 * Data de criacao: 27/06/2011 16:12:28
 */
package br.com.softcomex.components.workflow.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.transaction.TransactionManager;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.SystemEventListener;
import org.drools.SystemEventListenerFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.persistence.jpa.JPAKnowledgeService;
import org.drools.runtime.Environment;
import org.drools.runtime.EnvironmentName;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.process.ProcessInstance;
import org.drools.spi.ProcessContext;
import org.jbpm.process.audit.JPAProcessInstanceDbLog;
import org.jbpm.process.audit.JPAWorkingMemoryDbLogger;
import org.jbpm.process.workitem.wsht.CommandBasedWSHumanTaskHandler;
import org.jbpm.task.Status;
import org.jbpm.task.query.TaskSummary;
import org.jbpm.task.service.TaskClient;
import org.jbpm.task.service.TaskServer;
import org.jbpm.task.service.TaskService;
import org.jbpm.task.service.mina.MinaTaskClientConnector;
import org.jbpm.task.service.mina.MinaTaskClientHandler;
import org.jbpm.task.service.mina.MinaTaskServer;
import org.jbpm.task.service.responsehandlers.BlockingTaskOperationResponseHandler;
import org.jbpm.task.service.responsehandlers.BlockingTaskSummaryResponseHandler;

import br.com.softcomex.components.log.SfwLogger;
import br.com.softcomex.components.log.SfwLoggerFactory;
import br.com.softcomex.components.workflow.service.SfwJbpmWorkFlow;


/**
 * 

* Implementação da classe responsável por criar o ambiente do JBPM. *

* @author João Augusto Charnet * */ public class SfwJbpmWorkFlowImpl implements SfwJbpmWorkFlow {     /**      * Log.      */     private SfwLogger sfwLogger = SfwLoggerFactory.getLogger(getClass());         /**      * Entity Manager Factory injetado.      */     private EntityManagerFactory emf;         /**      * Transação.      */     private TransactionManager transactionManager;         /**      * Sessão da base de conhecimento do JBPM.      */     private StatefulKnowledgeSession kSession;         /**      * Thread do servidor de tarefa humana.      */     private TaskServer humanTaskServerThread;         /**      * Porta do sevidor de tarefa humana.      */     private int humanTaskServerPort = -1;         /**      * Endereço do Servidor de tarefa humana.      */     private String humanTaskServerLocalAddress = "127.0.0.1";         /**      * Lista com os jbpm que precisa ser carregado.      */     private List workFlowResourcesList;         /**      * Responsável por se comunicar com o servidor de tarefas humanas.      */     private TaskClient taskClient;         /**      * Contexto do processo.      */         /**      * Construtor padrão.      */     public SfwJbpmWorkFlowImpl() {     }     @Override     public void prepareSession() {         KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();                 for (String resource : this.workFlowResourcesList) {             kbuilder.add(ResourceFactory.newClassPathResource(resource), ResourceType.BPMN2);         }                 KnowledgeBase kbase = kbuilder.newKnowledgeBase();                 Environment env = KnowledgeBaseFactory.newEnvironment();         env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, this.emf);         env.set(EnvironmentName.TRANSACTION_MANAGER,             this.transactionManager);                 // Human Task         SystemEventListener systemEventListener = SystemEventListenerFactory.getSystemEventListener();                 TaskService taskService = new TaskService(this.emf, systemEventListener);                this.startHumanTaskServer(taskService);                 Properties properties = new Properties();         properties.put("drools.processInstanceManagerFactory", "org.jbpm.persistence.processinstance.JPAProcessInstanceManagerFactory");         properties.put("drools.processSignalManagerFactory", "org.jbpm.persistence.processinstance.JPASignalManagerFactory");         KnowledgeSessionConfiguration config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(properties);                 StatefulKnowledgeSession ksession =             JPAKnowledgeService.newStatefulKnowledgeSession(kbase, config, env);               //this will log in audit tables         JPAWorkingMemoryDbLogger jpaWorkingMemoryLog = new JPAWorkingMemoryDbLogger(ksession);         JPAProcessInstanceDbLog processLog = new JPAProcessInstanceDbLog(ksession.getEnvironment());         KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);                         CommandBasedWSHumanTaskHandler humanTask = new CommandBasedWSHumanTaskHandler(ksession);         humanTask.setConnection(this.humanTaskServerLocalAddress, this.humanTaskServerPort);         ksession.getWorkItemManager().registerWorkItemHandler("Human Task", humanTask);               this.setkSession(ksession);     }     /**      * Inicia o servidor para a tarefa humana.      *      * @param taskService Serviço da tarefa.      */     private void startHumanTaskServer(TaskService taskService) {         if (this.humanTaskServerPort <= 0) {             this.humanTaskServerPort = SfwJbpmWorkFlow.DEFAULT_HUMAN_TASK_SERVER_PORT;         }         this.sfwLogger.debug("Iniciando Human Task Server! ip [ " + this.humanTaskServerLocalAddress + "] port [" + this.humanTaskServerPort +"]");         this.humanTaskServerThread = new MinaTaskServer(taskService, this.humanTaskServerPort);         Thread thread = new Thread(this.humanTaskServerThread);         thread.start();     }     @Override     public void stopHumanTaskServer() throws Exception {        if (this.humanTaskServerThread != null &&            this.humanTaskServerThread.isRunning()) {                       this.taskClient.disconnect();            this.humanTaskServerThread.stop();                       this.sfwLogger.debug("Encerrando Human Task Server!");        }     }     @Override     public void setHumanTaskServerPort(int humanTaskServerPort) {         this.humanTaskServerPort = humanTaskServerPort;     }     @Override     public int getHumanTaskServerPort() {         return humanTaskServerPort;     }         @Override     public EntityManagerFactory getEmf() {             return emf;     }         @Override     public void setEmf(EntityManagerFactory emf) {             this.emf = emf;     }     @Override     public void setkSession(StatefulKnowledgeSession kSession) {         this.kSession = kSession;     }     @Override     public StatefulKnowledgeSession getkSession() {         return kSession;     }     @Override     public void setTransactionManager(TransactionManager transactionManager) {         this.transactionManager = transactionManager;     }     @Override     public TransactionManager getTransactionManager() {         return transactionManager;     }     @Override     public ProcessInstance startProcess(String processId, Map params) {         return this.kSession.startProcess(processId, params);             }     @Override     public void setWorkFlowResourcesList(List workFlowResourcesList) {         this.workFlowResourcesList = workFlowResourcesList;     }     @Override     public List getWorkFlowResourcesList() {         return workFlowResourcesList;     }     @Override     public void addWorkFlowResource(String workFlowResource) {         if (this.workFlowResourcesList == null) {             this.workFlowResourcesList = new ArrayList();         }                 this.workFlowResourcesList.add(workFlowResource);             }     @Override     public String getHumanTaskServerLocalAddress() {             return humanTaskServerLocalAddress;     }         @Override     public void setHumanTaskServerLocalAddress(String humanTaskServerLocalAddress) {             this.humanTaskServerLocalAddress = humanTaskServerLocalAddress;     }     @Override     public ProcessContext getProcessContext() {         ProcessContext procContext = new ProcessContext(this.kSession);         return procContext;     }         /**      * Cria um TaskClient conectando no servido de tarefa humana.      * @return TaskClient TaskClient.      */     private TaskClient createTaskClient() {                 if (this.taskClient == null) {             this.taskClient = new TaskClient(new MinaTaskClientConnector("SfwTaskClient",                                                     new MinaTaskClientHandler(SystemEventListenerFactory.getSystemEventListener())));                         boolean connected = this.taskClient.connect(this.humanTaskServerLocalAddress, this.humanTaskServerPort);             if (!connected) {                 this.sfwLogger.error("Não foi possível conectar no servidor de tarefa humana. Server [" + this.humanTaskServerLocalAddress + "] - Port [" + this.humanTaskServerPort + "]");             }         }         return this.taskClient;     }         @Override     public TaskClient getTaskClient() {             return taskClient;     }         @Override     public void setTaskClient(TaskClient taskClient) {             this.taskClient = taskClient;     }     @Override     public List getTasksByUser(String user) {         this.createTaskClient();                 BlockingTaskSummaryResponseHandler taskSummaryResponseHandler =             new BlockingTaskSummaryResponseHandler();         this.taskClient.getTasksAssignedAsPotentialOwner(user, "en-UK", taskSummaryResponseHandler);         final int oneSec = 1000;         taskSummaryResponseHandler.waitTillDone(oneSec);                 List tasks = taskSummaryResponseHandler.getResults();                 return tasks;     }         /**      * Cria uma TaskClient, caso necessário e retorna um taskResponseHandler      * para se comunicar com o servidor de tarefa humana.      *      * @return BlockingTaskOperationResponseHandler      */     private BlockingTaskOperationResponseHandler createTaskClientAndReturnTaskOperationResponseHandler() {         this.createTaskClient();                 BlockingTaskOperationResponseHandler taskResponseHandler =             new BlockingTaskOperationResponseHandler();         return taskResponseHandler;     }     @Override     public void completeTask(List tasks, String user) {         for (TaskSummary task : tasks) {             this.sfwLogger.debug("Completando tarefa [" + task.getName() + "] do usuário [" + user + "]");             this.completeTask(task, user);         }             }     @Override     public void completeTask(TaskSummary task, String user) {                 BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         this.taskClient.complete(task.getId(), user, null, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);     }     @Override     public void failTask(TaskSummary task, String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();                 this.taskClient.fail(task.getId(), user, null, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);     }     @Override     public void suspendTask(TaskSummary task, String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();                 this.taskClient.suspend(task.getId(), user, taskResponseHandler);     }     @Override     public void startTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         if (!task.getStatus().equals(Status.InProgress)) {                     this.taskClient.start(task.getId(), user, taskResponseHandler);             final int oneSec = 1000;             taskResponseHandler.waitTillDone(oneSec);         }                     }     @Override     public void stopTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         this.taskClient.stop(task.getId(), user, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);     }     @Override     public void releaseTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         this.taskClient.release(task.getId(), user, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);     }     @Override     public void resumeTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         this.taskClient.resume(task.getId(), user, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);     }     @Override     public void skipTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();         this.taskClient.skip(task.getId(), user, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);             }     @Override     public void claimTask(TaskSummary task,         String user) {         BlockingTaskOperationResponseHandler taskResponseHandler =             this.createTaskClientAndReturnTaskOperationResponseHandler();                 this.taskClient.claim(task.getId(), user, taskResponseHandler);         final int oneSec = 1000;         taskResponseHandler.waitTillDone(oneSec);             } }

 


Unit Test case

/**
 * Todos os direitos reservados para Softway.
 *
 * Data de criacao: 28/06/2011 15:18:56
 */
package br.com.softcomex.components.workflow.service.impl;

import java.net.ConnectException;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;

import junit.framework.Assert;

import org.drools.runtime.process.ProcessInstance;
import org.drools.runtime.process.WorkItem;
import org.drools.runtime.process.WorkItemHandler;
import org.drools.runtime.process.WorkItemManager;
import org.drools.spi.ProcessContext;
import org.jbpm.task.query.TaskSummary;
import org.junit.BeforeClass;
import org.junit.Test;

import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;
import br.com.softcomex.components.workflow.service.SfwJbpmWorkFlow;
import br.com.softcomex.test.serviceeao.SfwBaseServiceTestCase;


/**
 * Classe de teste do serviço SfwJbmWorkFlowImpl.
 * 
 * @author João Augusto Charnet *
 */
public class SfwJbpmWorkFlowImplTest extends SfwBaseServiceTestCase {

    /**
     * Serviço.
     */
    @Inject
    private SfwJbpmWorkFlow sfwWorkFlow;

    
    /**
     * Prepara o datasource.
     */
    @BeforeClass
    public static void prepareDatasource() {
        PoolingDataSource ds = new PoolingDataSource();
        ds.setUniqueName("localDataSource");
        ds.setClassName("oracle.jdbc.xa.client.OracleXADataSource");
        ds.setMaxPoolSize(3);
        ds.setAllowLocalTransactions(true);
        
        ResourceBundle rb = ResourceBundle.getBundle("jdbc");
        
        ds.getDriverProperties().put("user", rb.getString("jdbc.username"));
        ds.getDriverProperties().put("password", rb.getString("jdbc.password"));
        ds.getDriverProperties().put("URL", rb.getString("jdbc.url"));
        ds.init();
    }
    
    /**
     * Teste.
     * @throws Exception Exceção.
     */
    @Test
    public void testJbpmWorkFlow() throws Exception {
        
        this.sfwWorkFlow.setTransactionManager(TransactionManagerServices.getTransactionManager());
this.sfwWorkFlow.getTransactionManager().begin();
        //this.sfwWorkFlow.setHumanTaskServerPort(1234);
        this.sfwWorkFlow.addWorkFlowResource("test.bpmn");
        this.sfwWorkFlow.addWorkFlowResource("testHumanTask.bpmn");
        this.sfwWorkFlow.prepareSession();
        
        MyAutomaticHumanSimulatorWorkItemHandler workHandler = new MyAutomaticHumanSimulatorWorkItemHandler();
        TestWorkItemHandler workItemHandler = new TestWorkItemHandler();
        
        
        //this.sfwWorkFlow.getkSession().getWorkItemManager().registerWorkItemHandler("Human Task", workHandler);
        
        Socket socket = new Socket("127.0.0.1", this.sfwWorkFlow.getHumanTaskServerPort());
        Assert.assertNotNull(socket);
        Map params = new HashMap();
        params.put("ator", "Joao");
        params.put("responsible", "Joao");
        //ProcessInstance processInstance = this.sfwWorkFlow.startProcess("test.bpmn", params);
        ProcessInstance processInstance = this.sfwWorkFlow.startProcess("testHumanTask", params);
        
        Thread.currentThread().sleep(3000);
        
        List tasks = this.sfwWorkFlow.getTasksByUser("John");
        
        this.sfwWorkFlow.startTask(tasks.get(0), "John");
        
        this.sfwWorkFlow.completeTask(tasks.get(0), "John");
        
        Thread.currentThread().sleep(5000);
        
        Assert.assertEquals(ProcessInstance.STATE_COMPLETED, processInstance.getState());
        
        this.sfwWorkFlow.stopHumanTaskServer();
        
        try {
            socket = new Socket("127.0.0.1", this.sfwWorkFlow.getHumanTaskServerPort());
            Assert.fail("Esperando exceção, por não ter ninguém escutando na porta do sevidor " + this.sfwWorkFlow.getHumanTaskServerPort());
        } catch (ConnectException excep) {
            Assert.assertTrue(true);
        } finally {
            this.sfwWorkFlow.getTransactionManager().rollback();
        }
    }
    
    
}

 

http://community.jboss.org/servlet/JiveServlet/downloadImage/2-615187-16726/408-442/testHumanTask.JPG

jbpm xml

         <?xml version="1.0" encoding="UTF-8"?>  
<definitions id="Definition"
             targetNamespace="http://www.jboss.org/drools"
             typeLanguage="http://www.java.com/javaTypes"
             expressionLanguage="http://www.mvel.org/2.0"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
             xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
             xmlns:g="http://www.jboss.org/drools/flow/gpd"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:tns="http://www.jboss.org/drools"> 

  <itemDefinition id="_responsibleItem" structureRef="String" /> 

  <process processType="Private" isExecutable="true" id="testHumanTask" name="testHumanTask" > 

    <!-- process variables --> 
    <property id="responsible" itemSubjectRef="_responsibleItem"/> 

    <!-- nodes --> 
    <startEvent id="_1" name="Start" /> 
    <userTask id="_2" name="User Task" > 
      <ioSpecification> 
        <dataInput id="_2_TaskNameInput" name="TaskName" /> 
        <inputSet> 
          <dataInputRefs> _2_TaskNameInput</dataInputRefs> 
        </inputSet> 
        <outputSet> 
        </outputSet> 
      </ioSpecification> 
      <dataInputAssociation> 
        <targetRef> _2_TaskNameInput</targetRef> 
        <assignment> 
          <from xs:type="tFormalExpression"> Test Human Task</from> 
          <to xs:type="tFormalExpression"> _2_TaskNameInput</to> 
        </assignment> 
      </dataInputAssociation> 
      <potentialOwner> 
        <resourceAssignmentExpression> 
          <formalExpression> #{responsible}</formalExpression> 
        </resourceAssignmentExpression> 
      </potentialOwner> 
    </userTask> 
    <scriptTask id="_3" name="Script" scriptFormat="http://www.java.com/java" > 
      <script> System.out.println("Script task :" + new java.util.Date());</script> 
    </scriptTask> 
    <endEvent id="_4" name="End" > 
        <terminateEventDefinition/> 
    </endEvent> 

    <!-- connections --> 
    <sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" /> 
    <sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" /> 
    <sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4" /> 

  </process> 

  <bpmndi:BPMNDiagram> 
    <bpmndi:BPMNPlane bpmnElement="testHumanTask" > 
      <bpmndi:BPMNShape bpmnElement="_1" > 
        <dc:Bounds x="51" y="34" width="48" height="48" /> 
      </bpmndi:BPMNShape> 
      <bpmndi:BPMNShape bpmnElement="_2" > 
        <dc:Bounds x="165" y="35" width="100" height="48" /> 
      </bpmndi:BPMNShape> 
      <bpmndi:BPMNShape bpmnElement="_3" > 
        <dc:Bounds x="176" y="158" width="80" height="48" /> 
      </bpmndi:BPMNShape> 
      <bpmndi:BPMNShape bpmnElement="_4" > 
        <dc:Bounds x="191" y="301" width="48" height="48" /> 
      </bpmndi:BPMNShape> 
      <bpmndi:BPMNEdge bpmnElement="_1-_2" > 
        <di:waypoint x="75" y="58" /> 
        <di:waypoint x="215" y="59" /> 
      </bpmndi:BPMNEdge> 
      <bpmndi:BPMNEdge bpmnElement="_2-_3" > 
        <di:waypoint x="215" y="59" /> 
        <di:waypoint x="216" y="182" /> 
      </bpmndi:BPMNEdge> 
      <bpmndi:BPMNEdge bpmnElement="_3-_4" > 
        <di:waypoint x="216" y="182" /> 
        <di:waypoint x="215" y="325" /> 
      </bpmndi:BPMNEdge> 
    </bpmndi:BPMNPlane> 
  </bpmndi:BPMNDiagram> 

</definitions>                                                                                                                                  

Reply to this message by going to Community

Start a new discussion in jBPM at Community