5 Replies Latest reply on Jan 16, 2012 6:10 AM by leo87601

    [jbpm5.1]Can get the current nodeId,correctly??

    leo87601

      Dear all,

      We want to get the current node name after completed a task.But it is not working correctly some time.

      we found the error happen here.

      long nodeId = wfInstance.getNodeInstances().iterator().next().getNodeId();

       

      BTW, Before we setted the persistence, this issue does not happen.

       

      The data seem had problem too,  we found that the PROCESSINSTANCEINFO's lastmodificationdate(12:44:36) is the same as the pending node's log time, but the workflow had been run into Qualified at 12:44:43.

      We can not see the processinstancebytearray, so not sure the processintanceinfo had been updated correctly or not?

       

      select * from nodeinstancelog where processinstanceid =134 order by id desc;

       

      ID  TYPE  NODEINSTANCEID  NODEID  PROCESSINSTANCEID  PROCESSID  LOG_DATE  NODENAME 
      683059134LeadProcess2011-11-28 12:44:43.048Qualified
      682148134LeadProcess2011-11-28 12:44:43.048Gateway
      681048134LeadProcess2011-11-28 12:44:43.048Gateway
      680135134LeadProcess2011-11-28 12:44:43.033Pending
      679035134LeadProcess2011-11-28 12:44:36.36Pending



      SELECT * FROM PROCESSINSTANCEINFO where iNSTANCEID =134;

       

      INSTANCEID  LASTMODIFICATIONDATE  LASTREADDATE  PROCESSID  PROCESSINSTANCEBYTEARRAY  STARTDATE  STATE  OPTLOCK 
      1342011-11-28 12:44:36.3762011-11-28 12:57:39.437LeadProcessaced00057765000852756c65466c6f770000000000000086000b4c65616450726f6365737300000001000000000000000400000000001200000000000000030000000000000005001b00000000000000fd00000000000100000000000000020006616374696f6e0000000074000750656e64696e67770c0006757365724964000000007400056b72697376


       

      Environment : Jboss 5.1,  h2 database, windows 2003. we are using the default setting of jbpm-5.1.0.Final-installer-full.zip

       

      Here is our code of complete task.

      public ProcessInstanceBO completeUserTask(long instanceId, String toState){

       

      ProcessInstance instance = ksession.getProcessInstance(instanceId);  // init process by instanceid

      WorkflowProcessInstance wfInstance = ((WorkflowProcessInstance)instance);

      // get currently Node instances

      Iterator<NodeInstance> iterator = wfInstance.getNodeInstances().iterator();

      NodeInstance nodeInstance = iterator.next();              

      // compelte workitem.

      final long workItemId = workItemNodeInstance.getWorkItemId();

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

      results.put(this.ACTION, toState);

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

      ksession.getWorkItemManager().abortWorkItem(workItemId);

      // retrieve the process instance again.

      instance = ksession.getProcessInstance(instanceId);

      WorkflowProcessInstance wfInstance = (WorkflowProcessInstance) instance;

      //retrieve the current node again. we expect that , here is the next step's nodeid, but it doesn't work correctly every time. some time it still in the last stage.

      long nodeId = wfInstance.getNodeInstances().iterator().next().getNodeId();

      logger.debug("Process current node id: " + nodeId );

      WorkflowProcess wfProcess = (WorkflowProcess) readKnowledgeBase().getProcess(wfInstance.getProcessId());

      //We cannot get the correct Node name because.

                          Node node = wfProcess.getNode(nodeId);

      ....

      }

       

      We are confusing on this issue, please help. Thanks a lots.

        • 1. Re: [jbpm5.1]Can get the current nodeId,correctly??
          leo87601

          The problem had been fixed after we made the StatefulKnowledgeSession as a singleton object.

           

          private  StatefulKnowledgeSession getStatefulKnowledgeSession() throws Exception {

          ///////////  when we add this return and never dispose the ksession, the problem seems disappare.

                              if ( ksession != null && ksession.getWorkItemManager()!=null ){

                                        return ksession;

                              }

          /////////

            KnowledgeBase kbase = readKnowledgeBase();

            ksession = JPAKnowledgeService.newStatefulKnowledgeSession(kbase, null, env);

            CommandBasedWSHumanTaskHandler humanTaskHandler = new CommandBasedWSHumanTaskHandler(ksession);  

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

            SystemEventListenerFactory.setSystemEventListener(new SystemEventListener());

            TaskClient taskClient = new TaskClient(new MinaTaskClientConnector("MinaConnector",

            new MinaTaskClientHandler(SystemEventListenerFactory.getSystemEventListener())));

            taskClient.connect("127.0.0.1", 9123);

            humanTaskHandler.setClient(taskClient);

            humanTaskHandler.connect();

            return ksession;

           

          }

           

          But currently solution, we cannot load the newer snapshot easliy. Any Idea of this problem?

          • 2. Re: [jbpm5.1]Can get the current nodeId,correctly??
            salaboy21

            If you are using persistence, this doesn't seem as a good idea. because you will keep a dirty version of the session in memory.

            In your first post you add this lines:

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

            ksession.getWorkItemManager().abortWorkItem(workItemId);

             

            Why are you doing that?

            • 3. Re: [jbpm5.1]Can get the current nodeId,correctly??
              leo87601

              Thank you for you relpy Mauricio Salatino.

               

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

              ksession.getWorkItemManager().abortWorkItem(workItemId);

               

              That's a mistaken by our developer. I had fixed it before.

               

              Here is the backgroud of this project.

              We are developing a web application with JBPM5.1, we might have a few "startProcess" and "completeWorkitem" requests at the same time. We have using Jmeter simulate our pressure ,10 concurrency user request on the same time.

               

              At the beginning,we using the persistence implementation,we try to create a Ksession for every request and dispose() every time, we found nearly 50% error on the JBPM db(the Error case the same my first post).The error scenario is the workflow stay at the last status and cannot be completed, evan it shown Qualified  in log table, but our when we using the API to check the process instance, it still Pending. We have no idea to fix those data and these kind of data also be found on ur UAT environment(withoutsimulateion testing) .

               

              After that we try to made the Ksession as a singlton object as my second post. The problem had been fixed. we can past the 10 concurrency user Jmeter testing.

              We have following questions:

              1. As you mention that, what's the best implementation of Ksession, if we using persistence? (we are using the SQL Server 2005)

              1.1 Should the Ksession be shared for different requests? Or we should created different Ksession for each process instance?

               

              1.2.Are we correcly that create a Ksession for every request and dispose() every time? If yes, should we created a new taskclient every time?  (we are using the jbpm-installer's task-service as Humen task)

               

              2. How to fix the error data as above error case happen? please check the attachment(error_data+query.zip). Are there any way to change the PROCESSINSTANCEBYTEARRAY ?

               

              3. What happens when we have a process definition deployed, many executions are not yet finished and we have a new version of the process definition that we want to deploy?

              Our requriement is that  When a newer version is deployed, newly created instances will be started in the newest version, while older process instances keep on executing in the older process defintions.

              3.1 Will the JBPM 5 API achieve this kind of process versioning requirement?

              3.2 As we found that the snapshot might one of the way to achieve this, but we found that should be a bit complex, we need record the mapping with the process instance and package URL. Are there any idea of this?



              • 4. Re: [jbpm5.1]Can get the current nodeId,correctly??
                salaboy21

                Ok, so you have tons of questions.. I will start from the bottom..

                3.X It works in the way you want out of the box.

                2. you never need to fix that table, never touch that table because it contains internal information from the engine, users should never touch that.

                1. It depends on what you are doing with the session. If you create one session per process it will work. if you have concurrent threads trying to modify a field in a database one of them will fail and the other will win.. that will happen in any database and not only in jBPM. For that reason you are seeing errors in the console, but the state keeps consistent with the executed code. What you can do is to implement a retry mechanisms if one call fails because another concurrent one was processed at that time. If you want more specific answers on these topics I think that you should contact us for consulting services..

                 

                Cheers

                • 5. Re: [jbpm5.1]Can get the current nodeId,correctly??
                  leo87601

                  Thanks for you suggestion and we had tried to implement them, but we found following problem:

                  3.X It works in the way you want out of the box.

                  For the Process Versioning,  the process instance's data is working fine, but process Definition is stored in Kbase, and we try to add both version on the same Kbase,but the Ksession don't know which version they should work with. It always work with the last one which we added into the Kbase.Attachment is our testing casees for this problem.


                  Do the Process Definition (Kbase) and Ksession mapping should be maintanced by ourselves?

                  Should we share the Kbase for diferent version snapshot?

                  If Yes, I'm worry the older process request and newer process request happen concurrently, how should we handle that?

                   

                  2.you never need to fix that table, never touch that table because it contains internal information from the engine, users should never touch that.

                  1. It depends on what you are doing with the session. If you create one session per process it will work. if you have concurrent threads trying to modify a field in a database one of them will fail and the other will win.. that will happen in any database and not only in jBPM. For that reason you are seeing errors in the console, but the state keeps consistent with the executed code

                   

                  We found that the JBPM5 doesn't raise any exception when concurrent request and there are  different status in the Process Instance and Node Instance,and the work item cannot be completed any more. For this problem,I think we have some way to fix error, no matter we fix them by changing db or invoking JBPM's API.  Would you mind let me know how to do that in JBPM5?

                   

                  How to use the Ksession and Humantaskhandler?

                  When we change the implmentation to each process instance have one Ksession and dispose by the end of every request, we found the CommandBasedWSHumanTaskHandler can not be shared. (the Same problem on this chinese blog https://community.jboss.org/thread/170916)

                  handler = new CommandBasedWSHumanTaskHandler(ksession);

                  ksession.getWorkItemManager().registerWorkItemHandler("Human Task",handler);

                  I had changed the souce code to public void setKsession(KnowledgeRuntime session) and set the session in the existing handler:

                  handler.setSsession(ksession);

                  ksession.getWorkItemManager().registerWorkItemHandler("Human Task",

                  );

                   

                  It works fine after above changing, it should not be a good solution, do you have any idea for this? On our loading testing, when the server are handled 700+ objects, it became very slowly.