-
1. Re: Human task API, how to move forward in the workflow ?
calca Jul 12, 2011 1:10 PM (in response to jcharnet)I have made something similar in a test, it may help you:
How are you checking that your next task in not getting called?
Demian
-
2. Re: Human task API, how to move forward in the workflow ?
tsurdilovic Jul 12, 2011 2:39 PM (in response to jcharnet)Look at the HumanTaskExample example in jbpm-examples module : https://github.com/droolsjbpm/jbpm/blob/master/jbpm-examples/src/main/java/org/jbpm/examples/humantask/HumanTaskExample.java.
-
3. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 13, 2011 9:45 AM (in response to calca)Thansk for your reply.
I took a look at your example Demian, and also I've already had looked at jbpm examples like Tihomir had suggested. Apparently there is not any difference in the way I'm using the Task Client API.
The way I'm checking if the next task is getting called is by debug. Mas next task has a task handler, and I have a breakpoint in this task handler.
If I create a custom task handler for the human task, and call the completeWorkItem method, my next task does get called. So I know that there is nothing wrong with this next task.
My environment is:
Spring for the model and transactions ( I do not configure any jbpm in spring )
JPA - Hibernate for persistence.
I'm also persisting the workflow in the database with JPAKnowledgeService and CommandBasedWSHumanTaskHandler.
Any other ideas I could try ?
Thanks,
John
-
4. Re: Human task API, how to move forward in the workflow ?
calca Jul 13, 2011 10:06 AM (in response to jcharnet)Hi John.
Are you using the Console Logger? What is it logging after you call complete?
If possible, could you please provide a test that shows this error with you configurations?
Thanks,
Demian
-
5. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 13, 2011 10:42 AM (in response to calca)Here is the complete log.
It has hibernate statements and the jbpm console logger.
I can't see through the jbpm console logger, anything related to the complete task. But if you see the hibernate statemens, you will find some updates to the task table, the last update sets the status to Completed.
Thanks
Hibernate:
select
task0_.id as col_0_0_,
deadline1_.id as col_1_0_,
deadline1_.deadline_date as col_2_0_
from
Task task0_,
Deadline deadline1_
where
(
deadline1_.id in (
select
startdeadl2_.id
from
Deadline startdeadl2_
where
task0_.id=startdeadl2_.Deadlines_StartDeadLine_Id
)
or deadline1_.id in (
select
enddeadlin3_.id
from
Deadline enddeadlin3_
where
task0_.id=enddeadlin3_.Deadlines_EndDeadLine_Id
)
)
and deadline1_.escalated=0
order by
deadline1_.deadline_date
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE RULEFLOW VARIABLE CHANGED ator=Joao process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
AFTER RULEFLOW VARIABLE CHANGED ator=Joao process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE RULEFLOW STARTED process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE PROCESS NODE TRIGGERED node:Start[id=1] process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE PROCESS NODE EXITED node:Start[id=1] process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE PROCESS NODE TRIGGERED node:Hello World[id=2] process:test.b[id=test.bpmn]
Hello world!
Date: Wed Jul 13 11:31:50 BRT 2011
BEFORE RULEFLOW VARIABLE CHANGED action=Hello process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
AFTER RULEFLOW VARIABLE CHANGED action=Hello process:test.b[id=test.bpmn]
Context: org.drools.spi.ProcessContext@d68b39
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE PROCESS NODE EXITED node:Hello World[id=2] process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
BEFORE PROCESS NODE TRIGGERED node:User Task[id=9] process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
AFTER PROCESS NODE TRIGGERED node:User Task[id=9] process:test.b[id=test.bpmn]
AFTER PROCESS NODE TRIGGERED node:Hello World[id=2] process:test.b[id=test.bpmn]
AFTER PROCESS NODE TRIGGERED node:Hello World[id=2] process:test.b[id=test.bpmn]
AFTER PROCESS NODE TRIGGERED node:Start[id=1] process:test.b[id=test.bpmn]
AFTER PROCESS NODE TRIGGERED node:Start[id=1] process:test.b[id=test.bpmn]
AFTER RULEFLOW STARTED process:test.b[id=test.bpmn]
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
user_.id
from
OrganizationalEntity user_
where
user_.id=?
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
select
hibernate_sequence.nextval
from
dual
Hibernate:
insert
into
Task
(allowedToDelegate, taskInitiator_id, priority, activationTime, actualOwner_id, createdBy_id, createdOn, documentAccessType, documentContentId, documentType, expirationTime, faultAccessType, faultContentId, faultName, faultType, outputAccessType, outputContentId, outputType, parentId, previousStatus, processInstanceId, skipable, status, workItemId, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
I18NText
(language, text, id)
values
(?, ?, ?)
Hibernate:
insert
into
I18NText
(language, text, id)
values
(?, ?, ?)
Hibernate:
insert
into
I18NText
(language, text, id)
values
(?, ?, ?)
Hibernate:
insert
into
Content
(content, id)
values
(?, ?)
Hibernate:
update
Task
set
allowedToDelegate=?,
taskInitiator_id=?,
priority=?,
activationTime=?,
actualOwner_id=?,
createdBy_id=?,
createdOn=?,
documentAccessType=?,
documentContentId=?,
documentType=?,
expirationTime=?,
faultAccessType=?,
faultContentId=?,
faultName=?,
faultType=?,
outputAccessType=?,
outputContentId=?,
outputType=?,
parentId=?,
previousStatus=?,
processInstanceId=?,
skipable=?,
status=?,
workItemId=?
where
id=?
Hibernate:
update
I18NText
set
Task_Descriptions_Id=?
where
id=?
Hibernate:
update
I18NText
set
Task_Names_Id=?
where
id=?
Hibernate:
insert
into
PeopleAssignments_BAs
(task_id, entity_id)
values
(?, ?)
Hibernate:
insert
into
PeopleAssignments_PotOwners
(task_id, entity_id)
values
(?, ?)
Hibernate:
update
I18NText
set
Task_Subjects_Id=?
where
id=?
Hibernate:
select
task0_.id as col_0_0_,
task0_.processInstanceId as col_1_0_,
i18ntext4_.text as col_2_0_,
subjects3_.text as col_3_0_,
i18ntext5_.text as col_4_0_,
task0_.status as col_5_0_,
task0_.priority as col_6_0_,
task0_.skipable as col_7_0_,
task0_.actualOwner_id as col_8_0_,
task0_.createdBy_id as col_9_0_,
task0_.createdOn as col_10_0_,
task0_.activationTime as col_11_0_,
task0_.expirationTime as col_12_0_
from
Task task0_
left outer join
OrganizationalEntity user1_
on task0_.createdBy_id=user1_.id
left outer join
OrganizationalEntity user2_
on task0_.actualOwner_id=user2_.id
left outer join
I18NText subjects3_
on task0_.id=subjects3_.Task_Subjects_Id,
I18NText i18ntext4_,
I18NText i18ntext5_,
OrganizationalEntity organizati6_
where
organizati6_.id=?
and (
organizati6_.id in (
select
potentialo9_.entity_id
from
PeopleAssignments_PotOwners potentialo9_
where
task0_.id=potentialo9_.task_id
)
)
and i18ntext4_.language=?
and (
i18ntext4_.id in (
select
names10_.id
from
I18NText names10_
where
task0_.id=names10_.Task_Names_Id
)
)
and (
subjects3_.language=?
or (
select
count(subjects11_.Task_Subjects_Id)
from
I18NText subjects11_
where
task0_.id=subjects11_.Task_Subjects_Id
)=0
)
and (
i18ntext5_.language=?
and (
i18ntext5_.id in (
select
descriptio12_.id
from
I18NText descriptio12_
where
task0_.id=descriptio12_.Task_Descriptions_Id
)
)
or (
select
count(descriptio13_.Task_Descriptions_Id)
from
I18NText descriptio13_
where
task0_.id=descriptio13_.Task_Descriptions_Id
)=0
)
and (
task0_.status in (
'Created' , 'Ready' , 'Reserved' , 'InProgress' , 'Suspended'
)
)
and (
task0_.expirationTime is null
)
Hibernate:
select
user0_.id as id10_0_
from
OrganizationalEntity user0_
where
user0_.id=?
and user0_.DTYPE='User'
Hibernate:
select
task0_.id as id15_3_,
task0_.allowedToDelegate as allowedT2_15_3_,
task0_.taskInitiator_id as taskIni23_15_3_,
task0_.priority as priority15_3_,
task0_.activationTime as activati4_15_3_,
task0_.actualOwner_id as actualO24_15_3_,
task0_.createdBy_id as createdBy25_15_3_,
task0_.createdOn as createdOn15_3_,
task0_.documentAccessType as document6_15_3_,
task0_.documentContentId as document7_15_3_,
task0_.documentType as document8_15_3_,
task0_.expirationTime as expirati9_15_3_,
task0_.faultAccessType as faultAc10_15_3_,
task0_.faultContentId as faultCo11_15_3_,
task0_.faultName as faultName15_3_,
task0_.faultType as faultType15_3_,
task0_.outputAccessType as outputA14_15_3_,
task0_.outputContentId as outputC15_15_3_,
task0_.outputType as outputType15_3_,
task0_.parentId as parentId15_3_,
task0_.previousStatus as previou18_15_3_,
task0_.processInstanceId as process19_15_3_,
task0_.skipable as skipable15_3_,
task0_.status as status15_3_,
task0_.workItemId as workItemId15_3_,
user1_.id as id10_0_,
user2_.id as id10_1_,
user3_.id as id10_2_
from
Task task0_
left outer join
OrganizationalEntity user1_
on task0_.taskInitiator_id=user1_.id
left outer join
OrganizationalEntity user2_
on task0_.actualOwner_id=user2_.id
left outer join
OrganizationalEntity user3_
on task0_.createdBy_id=user3_.id
where
task0_.id=?
Hibernate:
update
Task
set
allowedToDelegate=?,
taskInitiator_id=?,
priority=?,
activationTime=?,
actualOwner_id=?,
createdBy_id=?,
createdOn=?,
documentAccessType=?,
documentContentId=?,
documentType=?,
expirationTime=?,
faultAccessType=?,
faultContentId=?,
faultName=?,
faultType=?,
outputAccessType=?,
outputContentId=?,
outputType=?,
parentId=?,
previousStatus=?,
processInstanceId=?,
skipable=?,
status=?,
workItemId=?
where
id=?
Hibernate:
select
task0_.id as id15_3_,
task0_.allowedToDelegate as allowedT2_15_3_,
task0_.taskInitiator_id as taskIni23_15_3_,
task0_.priority as priority15_3_,
task0_.activationTime as activati4_15_3_,
task0_.actualOwner_id as actualO24_15_3_,
task0_.createdBy_id as createdBy25_15_3_,
task0_.createdOn as createdOn15_3_,
task0_.documentAccessType as document6_15_3_,
task0_.documentContentId as document7_15_3_,
task0_.documentType as document8_15_3_,
task0_.expirationTime as expirati9_15_3_,
task0_.faultAccessType as faultAc10_15_3_,
task0_.faultContentId as faultCo11_15_3_,
task0_.faultName as faultName15_3_,
task0_.faultType as faultType15_3_,
task0_.outputAccessType as outputA14_15_3_,
task0_.outputContentId as outputC15_15_3_,
task0_.outputType as outputType15_3_,
task0_.parentId as parentId15_3_,
task0_.previousStatus as previou18_15_3_,
task0_.processInstanceId as process19_15_3_,
task0_.skipable as skipable15_3_,
task0_.status as status15_3_,
task0_.workItemId as workItemId15_3_,
user1_.id as id10_0_,
user2_.id as id10_1_,
user3_.id as id10_2_
from
Task task0_
left outer join
OrganizationalEntity user1_
on task0_.taskInitiator_id=user1_.id
left outer join
OrganizationalEntity user2_
on task0_.actualOwner_id=user2_.id
left outer join
OrganizationalEntity user3_
on task0_.createdBy_id=user3_.id
where
task0_.id=?
Hibernate:
select
subtaskstr0_.Task_Id as Task4_1_,
subtaskstr0_.id as id1_,
subtaskstr0_.id as id16_0_,
subtaskstr0_.name as name16_0_,
subtaskstr0_.DTYPE as DTYPE16_0_
from
SubTasksStrategy subtaskstr0_
where
subtaskstr0_.Task_Id=?
Hibernate:
update
Task
set
allowedToDelegate=?,
taskInitiator_id=?,
priority=?,
activationTime=?,
actualOwner_id=?,
createdBy_id=?,
createdOn=?,
documentAccessType=?,
documentContentId=?,
documentType=?,
expirationTime=?,
faultAccessType=?,
faultContentId=?,
faultName=?,
faultType=?,
outputAccessType=?,
outputContentId=?,
outputType=?,
parentId=?,
previousStatus=?,
processInstanceId=?,
skipable=?,
status=?,
workItemId=?
where
id=?
Hibernate:
select
task0_.id as id15_3_,
task0_.allowedToDelegate as allowedT2_15_3_,
task0_.taskInitiator_id as taskIni23_15_3_,
task0_.priority as priority15_3_,
task0_.activationTime as activati4_15_3_,
task0_.actualOwner_id as actualO24_15_3_,
task0_.createdBy_id as createdBy25_15_3_,
task0_.createdOn as createdOn15_3_,
task0_.documentAccessType as document6_15_3_,
task0_.documentContentId as document7_15_3_,
task0_.documentType as document8_15_3_,
task0_.expirationTime as expirati9_15_3_,
task0_.faultAccessType as faultAc10_15_3_,
task0_.faultContentId as faultCo11_15_3_,
task0_.faultName as faultName15_3_,
task0_.faultType as faultType15_3_,
task0_.outputAccessType as outputA14_15_3_,
task0_.outputContentId as outputC15_15_3_,
task0_.outputType as outputType15_3_,
task0_.parentId as parentId15_3_,
task0_.previousStatus as previou18_15_3_,
task0_.processInstanceId as process19_15_3_,
task0_.skipable as skipable15_3_,
task0_.status as status15_3_,
task0_.workItemId as workItemId15_3_,
user1_.id as id10_0_,
user2_.id as id10_1_,
user3_.id as id10_2_
from
Task task0_
left outer join
OrganizationalEntity user1_
on task0_.taskInitiator_id=user1_.id
left outer join
OrganizationalEntity user2_
on task0_.actualOwner_id=user2_.id
left outer join
OrganizationalEntity user3_
on task0_.createdBy_id=user3_.id
where
task0_.id=?
Hibernate:
select
workitemin0_.workItemId as workItemId3_0_,
workitemin0_.creationDate as creation2_3_0_,
workitemin0_.name as name3_0_,
workitemin0_.processInstanceId as processI4_3_0_,
workitemin0_.state as state3_0_,
workitemin0_.OPTLOCK as OPTLOCK3_0_,
workitemin0_.workItemByteArray as workItem7_3_0_
from
WorkItemInfo workitemin0_
where
workitemin0_.workItemId=?
Hibernate:
select
names0_.Task_Names_Id as Task5_1_,
names0_.id as id1_,
names0_.id as id11_0_,
names0_.language as language11_0_,
names0_.text as text11_0_
from
I18NText names0_
where
names0_.Task_Names_Id=?
-
6. Re: Human task API, how to move forward in the workflow ?
williajd Jul 13, 2011 12:05 PM (in response to jcharnet)I've had similar problems where I thought tasks were not being created, but they were. Have you checked in the database to see if the next task has been created?
Is the next task assigned to a user or a group?
-
7. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 13, 2011 12:13 PM (in response to williajd)Hi James.
My next task is not a Human Task, it is a <task> ...</task>, that I have attached a Task Handler to it. If I change this task to a script task, and make my script task write a simple System.out, nothing get's printed to the console.
So I still presume that my next task is not getting called.
thanks
-
8. Re: Human task API, how to move forward in the workflow ?
williajd Jul 13, 2011 12:16 PM (in response to jcharnet)Hi John,
Have you tried making it a human task and see if it get to that point? At least then you would know that your code moving the process forward is work so there must be something wrong with the script task or configuration.
Just a thought.
-
9. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 13, 2011 12:37 PM (in response to williajd)Just tried your idea James, but my next task (modified to be a human task), did not get called.
It looks like I'm missing some configuration or something.
-
10. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 13, 2011 4:00 PM (in response to jcharnet)I've made some massive debug, and what I found out was that after the task client api complete method is executed, I get to a point where the method completeWorkItem is executing. This method tries to join an existing transaction, and I'm getting the following error:
javax.persistence.TransactionRequiredException: No local transaction to join
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.doJoinTransaction(ExtendedEntityManagerCreator.java:407)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at $Proxy56.joinTransaction(Unknown Source)
at org.drools.persistence.jpa.JpaPersistenceContextManager.beginCommandScopedEntityManager(JpaPersistenceContextManager.java:66)
at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:287)
at org.drools.command.impl.CommandBasedStatefulKnowledgeSession$1.completeWorkItem(CommandBasedStatefulKnowledgeSession.java:149)
at org.jbpm.process.workitem.wsht.CommandBasedWSHumanTaskHandler$GetCompletedTaskResponseHandler.execute(CommandBasedWSHumanTaskHandler.java:259)
Is there any configuration problems with my environment ?
Spring is in control of my EntityManagerFactory and in my test unit I'm using bitronix.tm.TransactionManagerServices.getTransactionManager().
Any ideas ?
Thanks
-
11. Re: Human task API, how to move forward in the workflow ?
trh3037 Jul 13, 2011 10:34 PM (in response to jcharnet)I've had similar problems .
I am looking forward to someone can solve this problem.
-
12. Re: Human task API, how to move forward in the workflow ?
calca Jul 14, 2011 2:53 AM (in response to jcharnet)Hi John,
could you please share your configuration, and if possible your test case?
Thanks,
Demian
-
13. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 14, 2011 9:40 AM (in response to calca)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.addWorkFlowResource("test.bpmn"); this.sfwWorkFlow.addWorkFlowResource("testHumanTask.bpmn"); this.sfwWorkFlow.prepareSession(); MyAutomaticHumanSimulatorWorkItemHandler workHandler = new MyAutomaticHumanSimulatorWorkItemHandler(); TestWorkItemHandler workItemHandler = new TestWorkItemHandler(); Socket socket = new Socket("127.0.0.1", this.sfwWorkFlow.getHumanTaskServerPort()); Assert.assertNotNull(socket); Map params = new HashMap(); params.put("responsible", "John"); 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(); } } }
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>
-
14. Re: Human task API, how to move forward in the workflow ?
jcharnet Jul 22, 2011 7:54 AM (in response to jcharnet)I got it to work. Not the ideal way though.
I had to create my EntityManagerFactory in my JUnit test with Persistence.createEntityManagerFactory.
I cannot use my spring configuration to create the entity manager, and to handle the transaction.
Now this brings me to a new question. When I run my web application, will I get this same error ?
Thanks for all the help !
John