1 2 Previous Next 20 Replies Latest reply on Mar 4, 2013 5:41 AM by obon

    JBPM 5.4.0-Final: Human Task variable mapping is not working

    vchmakov

      Hi,

       

      I’m not sure as to what is going on…

      I have an SE application with JBPM 5.2.0 successfully running in production.

      Now I’m trying to switch to JBPM 5.4.0 and from SE to EE. To be honest not everything went smoothly, but I was able to sort out most of the issues and started testing of my workflows. Variable mapping/assignment when Human Task is finished is not working. For some reason all variables which are supposed to be assigned from the task output map are getting null-ed. There is no exception thrown. Am I missing something?

       

      Any help is appreciated.

       

      Thanks,

       

      Vladimir

        • 1. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
          swiderski.maciej

          description that you provided makes me believe that your human task work item is not completed but aborted which causes that the variables are not set based on the outcome. Do you use LocalTaskService?

           

          HTH

          • 2. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
            vchmakov

            Hi Maciej,

             

            Yes, I’m using LocalTaskService. What makes you believe that the task is aborted -the transaction completed but not aborted and the task is marked/persisted as Completed?

             

            Thanks,

             

            Vladimir

             

            • 3. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
              swiderski.maciej

              Vladimir, the issue with local task service that you could experience is when you have different instances of it used for creating the task (via LocalHTWorkItemHandler) and completing it. If they are two different instances their persistence context is not shared and thus when task is completed it sends an completed event to the engine which is received by LocalHTWorkItemHandler and it checks if the task is in state Completed - which in case of not shared persistence context it won't be and thus proceeding to abort work item instead of completing it.

              So on the task service side everything is ok but engine gets outdated values so it proceeds but not in the way you expect.

               

              HTH

              • 4. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                vchmakov

                Hi Maciej,

                 

                That is exactly what is going on. However, as far as I understand and according to the examples coming with the JBPM deployment:

                1)      The instance of the LocalHTWorkItemHandler is attached to the session and is purposed for the HT engine’s event handling. As far as I can see it does not possess the persistence context but rather shares it with the Drools’s one when rule’s RHS starts the process and the process reaches the wait/persisted state.

                 

                    private void registerHumanTaskHandler(StatefulKnowledgeSession session) {

                        if (taskServer != null) {

                            logger.info("Registering Human Task Handler...");

                            LocalHTWorkItemHandler humanTaskHandler = new LocalHTWorkItemHandler(createTaskService(), session);

                            humanTaskHandler.setLocal(true);

                            humanTaskHandler.connect();

                            session.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

                            logger.info("OK.");

                        }

                    }

                 

                 

                2)      When user completes a task from the Web form the event is delivered to the engine. In my case it is a Message Queue event which I process in MDB. Then I create a fresh instance of the LocalTaskService and complete the task. According to the examples provided with the JBPM installation and the source code of the LocalTaskService it is a recommended way to avoid reusing of the Entity Manager.

                 

                 

                    private void registerHumanTaskHandler(StatefulKnowledgeSession session) {

                        if (taskServer != null) {

                            logger.info("Registering Human Task Handler...");

                            LocalHTWorkItemHandler humanTaskHandler = new LocalHTWorkItemHandler(createTaskService(), session);

                            humanTaskHandler.setLocal(true);

                            humanTaskHandler.connect();

                            session.getWorkItemManager().registerWorkItemHandler("Human Task", humanTaskHandler);

                            logger.info("OK.");

                        }

                    }

                 

                    private void createTaskServer() throws Exception {

                        logger.info("Creating Task Server...");

                        if (persistenceManager != null) {

                            taskServer = new TaskService(persistenceManager.getTaskEntityManagerFactory(),

                                    SystemEventListenerFactory.getSystemEventListener());

                        }

                        else {

                            throw new IllegalArgumentException("createTaskServer() - Persistence Manager must be created for this operation");

                        }

                        logger.info("OK.");

                    }

                 

                    private org.jbpm.task.TaskService createTaskService() {

                        logger.debug("Creating Task Service...");

                        if (taskServer != null) {

                            return new LocalTaskService(taskServer);

                        }

                        else {

                            throw new IllegalArgumentException("Task Server is not yet created");

                        }

                    }

                 

                    private void processCompleteTaskCommand(BvCompleteTaskCommand command) throws Exception {

                        logger.trace("Processing TaskCompleteCommand()...");

                        final String userId = command.getUserId();

                        final String wf_userId = WORKFLOW_USERID;

                        logger_processes.debug("Completing task id={}, userId={}", command.getTaskId(), userId);

                 

                        org.jbpm.task.TaskService taskService = createTaskService();

                 

                        taskService.start(command.getTaskId(), wf_userId);

                 

                        Object data = command.getData();

                        if (data != null) {

                            taskService.completeWithResults(command.getTaskId(), wf_userId, data);

                        }

                        else {

                            logger_processes.debug("**** data is NULL");

                            taskService.complete(command.getTaskId(), wf_userId, null);

                       }

                        logger_processes.debug("  - task id={}, userId={} completed.", command.getTaskId(), userId);

                        logger.trace("Processing TaskCompleteCommand(). OK.");

                    }

                 

                 

                It seems to me that I’m misunderstanding something…

                 

                Thanks,

                 

                Vladimir

                 

                • 5. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                  swiderski.maciej

                  The issue here is that LocalHTWorkItemHandler has single (always active) instance of LocalTaskService and unfortunately it is shared with TaskCompletedHandler (that is inherited from GenericHTHandler). Which puts us in situation where after some time task is about to be completed and to do so new LocalTaskService instance is created that does the complete operation on task service and sends an event to the runtime engine. That event is received by TaskCompletedHandler and uses LocalTaskService instance from LocalHTWorkItemHandler. That gives us:

                  1. new instance of LocalTaskService (LTS1) that is created to complete task with persistence context PC1

                  2. always active instance of LocalTaskService (LTS2) taken from LocalHTWorkItemHandler inside TaskCompletedHandler class which was persistence context PC2

                   

                  when LTS2 checks task status by loading it from db (PC2) it has out of date information as the LTC1 has not yet committed it's changes (flushed from PC1) and thus proceeding with abort of work item handler.

                   

                  A workaround for this would be to extend LocalHTWorkItemHandler and override registerForEvent method to register your own TaskCompletedHandler that will get new LocalTaskService for every event it is going to process. With that persistence contexts will be shared on hibernate session level since they run as part of the same JTA transaction and where created for that transaction.

                   

                  HTH

                  • 6. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                    vchmakov

                    Hi Maciej,

                     

                    Your proposed approach works fine in terms that the my process now sees the result values. However, when the time comes for the session to complete the tasks is fails. I suspect the reason for this is the same – different persistent context.

                     

                            private void handleCompletedTask(long taskId) {

                     

                    // currentClient is a reference to my LocalTaskService instance I create for completeting the tasks

                     

                                Task task = currentClient.getTask(taskId);

                                long workItemId = task.getTaskData().getWorkItemId();

                                if (task.getTaskData().getStatus() == Status.Completed) {

                                    String userId = task.getTaskData().getActualOwner().getId();

                                    Map<String, Object> results = new HashMap<String, Object>();

                                    results.put("ActorId", userId);

                                    long contentId = task.getTaskData().getOutputContentId();

                                    if (contentId != -1) {

                                        Content content = currentClient.getContent(contentId);

                                        Object result = ContentMarshallerHelper.unmarshall(content.getContent(), session.getEnvironment());

                                        results.put("Result", result);

                                        if (result instanceof Map) {

                                            Map<?, ?> map = (Map<?, ?>) result;

                                            for (Map.Entry<?, ?> entry : map.entrySet()) {

                                                if (entry.getKey() instanceof String) {

                                                    results.put((String) entry.getKey(), entry.getValue());

                                                }

                                            }

                                        }

                    è  fails here

                                        session.getWorkItemManager().completeWorkItem(task.getTaskData().getWorkItemId(), results);

                                    }

                                    else {

                                        session.getWorkItemManager().completeWorkItem(workItemId, results);

                                    }

                                }

                                else {

                                    logger_processes.debug("session.getWorkItemManager().abortWorkItem()");

                                    session.getWorkItemManager().abortWorkItem(workItemId);

                                }

                            }

                     

                    processTaskCommand() error:: com.thoughtworks.xstream.io.StreamException:  : only whitespace content allowed before start tag and not B (position: START_DOCUMENT seen B... @1:1)

                                    at com.thoughtworks.xstream.io.xml.XppReader.pullNextEvent(XppReader.java:124) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.AbstractPullReader.readRealEvent(AbstractPullReader.java:148) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.AbstractPullReader.readEvent(AbstractPullReader.java:141) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.AbstractPullReader.move(AbstractPullReader.java:118) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.AbstractPullReader.moveDown(AbstractPullReader.java:103) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.XppReader.<init>(XppReader.java:63) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.io.xml.AbstractXppDriver.createReader(AbstractXppDriver.java:58) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:895) [xstream-1.4.1.jar:]

                                    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:886) [xstream-1.4.1.jar:]

                                    at org.drools.process.core.datatype.impl.type.ObjectDataType.readValue(ObjectDataType.java:77) [drools-core-5.5.0.Final.jar:5.5.0.Final]

                                    at org.jbpm.workflow.instance.node.WorkItemNodeInstance.triggerCompleted(WorkItemNodeInstance.java:223) [jbpm-flow-5.4.0.Final.jar:5.4.0.Final]

                                    at org.jbpm.workflow.instance.node.HumanTaskNodeInstance.triggerCompleted(HumanTaskNodeInstance.java:90) [jbpm-flow-5.4.0.Final.jar:5.4.0.Final]

                                    at org.jbpm.workflow.instance.node.WorkItemNodeInstance.workItemCompleted(WorkItemNodeInstance.java:309) [jbpm-flow-5.4.0.Final.jar:5.4.0.Final]

                                    at org.jbpm.workflow.instance.node.WorkItemNodeInstance.signalEvent(WorkItemNodeInstance.java:285) [jbpm-flow-5.4.0.Final.jar:5.4.0.Final]

                                    at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.signalEvent(WorkflowProcessInstanceImpl.java:342) [jbpm-flow-5.4.0.Final.jar:5.4.0.Final]

                                    at org.drools.persistence.jpa.processinstance.JPAWorkItemManager.completeWorkItem(JPAWorkItemManager.java:121) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]

                                    at org.drools.command.runtime.process.CompleteWorkItemCommand.execute(CompleteWorkItemCommand.java:69) [drools-core-5.5.0.Final.jar:5.5.0.Final]

                                    at org.drools.command.runtime.process.CompleteWorkItemCommand.execute(CompleteWorkItemCommand.java:32) [drools-core-5.5.0.Final.jar:5.5.0.Final]

                                    at org.drools.command.impl.DefaultCommandService.execute(DefaultCommandService.java:36) [drools-core-5.5.0.Final.jar:5.5.0.Final]

                                    at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:373) [drools-persistence-jpa-5.5.0.Final.jar:5.5.0.Final]

                                    at org.drools.command.impl.CommandBasedStatefulKnowledgeSession$1.completeWorkItem(CommandBasedStatefulKnowledgeSession.java:150) [drools-core-5.5.0.Final.jar:5.5.0.Final]

                                    at BvLocalHTWorkItemHandler$TaskCompletedHandler.handleCompletedTask(BvLocalHTWorkItemHandler.java:96)

                     

                    It seems like either I need to put Drools and Task Service inside the same persistent context or split the transaction boundaries between Drools and Task Service. The second one is in fact a recommended way here which has been previously discussed in another posts, but I strongly disagree with the Task Service decoupling idea.

                     

                    Any other thoughts/ideas?

                     

                    Thanks,

                     

                    Vladimir

                     

                    • 7. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                      swiderski.maciej

                      Looking at the stack trace I think it is failing due to missing data type definition and it assumes Object and that's why it tries to use xstram to build object out of string. So if you declare structureRef for all your itemDefinitions that are used as process variables this error should go away.

                       

                      HTH

                      • 8. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                        vchmakov

                         

                        Hi Maciej,

                         

                        After some changes I think now I have both the runtime and the local Task Server working in the same transaction and sharing the same persistence context. I found that perhaps LocalHTWorkItemHandler.setClient() can be used instead of overriding of the TaskCompleteHandler to make Complete Task command working in the same persistence context. Please correct me if I’m wrong on this. All my process variables are objects – java.lang.String, java.lang.Integer etc. Is this what you mean in your reply above? The error did not go away. Any other ideas as to why this may be happening?

                         

                        Thanks,

                         

                        Vladimir

                         

                        • 9. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                          swiderski.maciej

                          Vladimir, using setClient can have side effects in concurrent cases e.g. when at the same time new task is created and another is completed. Two threads will use the same LocalTaskService instance which could lead to some unexpected results.

                           

                          The error you are seeing could be caused by not declared type of you process variables, take a look here at line 14, you'll see it declares String as structureRef so that informs the engine how to deal with that variable.You can declare java.lang.String as FQN too. Once you have that it should proceed with setting variables properly.

                           

                          HTH

                          1 of 1 people found this helpful
                          • 10. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                            vchmakov

                            Hi Maciej,

                             

                            1)     I’d agree with you on the first statement, but we are talking about an instance of the LocalTaskService which is linked to a knowledge session. Session is not thread safe according to the documentation and therefore I wouldn’t allow two threads working with a single instance of the session.

                            2)     I’ve converted all my workflow files from .rl format to .bpmn one and now everything is working fine. Have I missed an announcement that the .rl format is not supported anymore or it is a bug/regression?

                             

                            Thanks,

                             

                            Vladimir

                             

                            • 11. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                              swiderski.maciej

                              vchmakov wrote:

                               

                               

                              1)     I’d agree with you on the first statement, but we are talking about an instance of the LocalTaskService which is linked to a knowledge session. Session is not thread safe according to the documentation and therefore I wouldn’t allow two threads working with a single instance of the session.

                              Just keep in mind that LocalTaskService register its events on the global TaskService instance so that means you can experience situation that many sessions can be informed about completion of a task.

                               

                               

                              vchmakov wrote:

                               

                              2)     I’ve converted all my workflow files from .rl format to .bpmn one and now everything is working fine. Have I missed an announcement that the .rl format is not supported anymore or it is a bug/regression?

                               

                               

                              Nothing that I am aware of, rule flow is still supported and there are quite few tests for it in the code base, especially for modules that are higher in the hierarchy than jbpm-bpmn2 module. So it should work without changes. What issues did you encounter?

                               

                              HTH

                              • 12. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                                vchmakov

                                Hi Maciej,

                                 

                                1)      Thank you for the tip – I did not know that and can now see that this may really cause problems in production on a high level of load.

                                2)      The only issue described above – stream error when completing a task.

                                 

                                Thank you for your help!

                                 

                                Vladimir

                                 

                                • 13. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                                  swiderski.maciej

                                  could you attach a sample that fails with the stream error?

                                   

                                  Cheers

                                  • 14. Re: JBPM 5.4.0-Final: Human Task variable mapping is not working
                                    vchmakov

                                    Hi Maciej,

                                     

                                    Attached is a .rf workflow file which was causing me some head ache. Hope this is enough for your investigation.

                                     

                                    Thanks,

                                     

                                    Vladimir

                                     

                                    1 2 Previous Next