10 Replies Latest reply on Jun 1, 2011 2:41 AM by frankee787

    Advice regarding complex proccess modeling

    fabiomsouto

      Hello,

      I've pointed out already some questions a few days ago, but our team decided to take it back to the drawing board, because we're a bit confused, so we were wondering if anyone more experienced could help.

      We are currently trying to implement a document authorization and reviewing system, using jBPM. We are having some trouble defining the flow however.

      What seems difficult to us is how to:

      - Control the flow of the document through the organization. The document is read, forwarded to one or several people, then some of those people can forward the document too for further reading and commenting. We're having some trouble defining this flow.

      - The document can be read by several people at the same time or an order can be defined, meaning that from a group of 3 people, for example, (X, Y and Z), only Y can read the document after X and Z can read after Y. How can we define this flow as well?

      The main problem is that we can't tell in advance what people will be treating the document and if they will be doing it on a sequential or parallel way. what we now are the activities we want to perform on the document and in which sequence they occur.

      Modeling all the different routes a document may take, combining all the activities we want to perform, doesn't seem like a good approach to the problem. This would result in a huge process definition or many process definitions creating a maintenance and usability problem.

      Is there a design pattern to help solve this situation? Could someone more experienced give us some hints?

      Thank you very much.

        • 1. Re: Advice regarding complex proccess modeling
          saraswati.santanu

          Hi,
          did you consider using Assignment handler?

          If you implement "Read Document" as a task node and add an assignment handler to it, which can execute whatever business logic it needs to, to decide whether X, Y or Z or all of them or none of them can do "Read" task.

          ...
          <task name="read" >
           <assignment-handler class="org.jbpm.examples.ReadAssignTask">
           </assignment-handler>
           <transition to="decide" />
          </task>
          <decision name="decide">
           <handler class="org.jbpm.examples.DecideWhatToDo" />
           <transition name="read again" to="read" />
           <transition name="read done" to="next node" />
          </decision>
          ...
          


          • 2. Re: Advice regarding complex proccess modeling
            fabiomsouto

            Hi,

            Thank you for your reply. It was helpful.
            We are using the Assignment Handler right now.

            Now we would like to create several instances of the 'Review' task, one for each user. How can we garantee that the next task will only start executing when all of the 'Review' tasks are done? We are using jBPM4.

            • 3. Re: Advice regarding complex proccess modeling
              fabiomsouto

              Sorry for double posting. Is it possible to do this using a custom ActivityBehaviour?

              • 4. Re: Advice regarding complex proccess modeling
                saraswati.santanu

                How about creating sub-tasks in you actual task? Signalling flag will be false for the sub-tasks by default. So it will not transit to the next node till you call complete on the super task.

                The following code may be used when the review task becomes active

                Task reviewTask = taskService.createTaskQuery()
                 .activityName("Review")
                 .processInstanceId(processInstanceId)
                 .uniqueResult();
                
                for (String userId:userIds) {
                 TaskImpl subTask = reviewTask.createTask("Review for user "+userId)
                 .addCandidateUser(userId);
                
                 reviewTask.addSubTask(subTask);
                }
                


                When an user performs review then you can execute something like this:
                //somehow get the review task
                Task reviewTask = taskService.createTaskQuery()
                 .activityName("Review")
                 .processInstanceId(processInstanceId)
                 .uniqueResult();
                
                //some get the sub task for this user
                Task reviewSubTask = taskService.createTaskQuery()
                 .activityName("Review for user "+userId)
                 .processInstanceId(processInstanceId)
                 .uniqueResult();
                
                //complete the sub task
                taskService.completeTask(reviewSubTask.getId());
                
                //remove sub task from the super task
                reviewTask.removeSubTask(reviewSubTask);
                
                //if there exists not sub task then move on
                if (reviewTask.getSubTasks().isEmpty()) {
                 taskService.completeTask(reviewTask.getId());
                }
                

                This is just an idea I got now. I have never tried this. So the code may not be accurate. Let me know if it works.

                You may need to create a node altogether if you need to implement your own activity behaviour. You cannot really assign your own behaviour to the existing Task node of Jbpm. This also can be an approach to solve this problem.

                • 5. Re: Advice regarding complex proccess modeling
                  fabiomsouto

                  Thank you for your help. It has helped us a lot to think a bit more and know jbpm.

                  We are trying to follow a similar solution to yours, but, when we try to create a new subtask on a task, an exception occurs:

                  
                  09:41:12,935 SEV | [BaseJbpmTestCase] TEST THROWS EXCEPTION: no environment to get org.jbpm.pvm.internal.session.DbSession
                  org.jbpm.api.JbpmException: no environment to get org.jbpm.pvm.internal.session.DbSession
                   at org.jbpm.pvm.internal.env.EnvironmentImpl.getFromCurrent(EnvironmentImpl.java:197)
                   at org.jbpm.pvm.internal.env.EnvironmentImpl.getFromCurrent(EnvironmentImpl.java:190)
                   at org.jbpm.pvm.internal.task.TaskImpl.createSubTask(TaskImpl.java:231)
                   at org.jbpm.pvm.internal.task.TaskImpl.createSubTask(TaskImpl.java:243)
                   at org.teste.TratarDoc.testTratarDoc(TratarDoc.java:63)
                   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                   at java.lang.reflect.Method.invoke(Unknown Source)
                   at junit.framework.TestCase.runTest(TestCase.java:164)
                   at org.jbpm.test.BaseJbpmTestCase.runTest(BaseJbpmTestCase.java:80)
                   at junit.framework.TestCase.runBare(TestCase.java:130)
                   at junit.framework.TestResult$1.protect(TestResult.java:106)
                   at junit.framework.TestResult.runProtected(TestResult.java:124)
                   at junit.framework.TestResult.run(TestResult.java:109)
                   at junit.framework.TestCase.run(TestCase.java:120)
                   at junit.framework.TestSuite.runTest(TestSuite.java:230)
                   at junit.framework.TestSuite.run(TestSuite.java:225)
                   at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
                   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
                   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
                   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
                   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
                   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
                  ### EXCEPTION ###########################################
                  
                  


                  The piece of code is the following

                  
                   for (String responsavel : responsaveis) {
                   TaskImpl subTask = tratarTask.createSubTask("Tratar para" + responsavel);
                   subTask.setAssignee(responsavel);
                  
                   taskService.saveTask(subTask);
                  
                   tratarTask.addSubTask(subTask);
                   }
                  
                  
                  
                  


                  It goes mad when we call createSubTask(). What are we doing wrong? :-(

                  • 6. Re: Advice regarding complex proccess modeling
                    saraswati.santanu

                    Hi,
                    This is a pretty late response. Out on a trip an could not access for few days.

                    The way you are creating sub tasks may not work. You should use command service to get your job done instead of using direct methods on tasks. Command service will ensure all the interceptors are invoked before a call is made to your command. One such interceptor will create a DBSession for you. A sample code should look like this:

                     Task task = //get the parent task somehow
                     //create a new task which is a child of the task above
                     Task subTask = taskService.newTask(task.getId());
                     subTask.setName(subTaskName);
                     //this is important as this call will add this task to the sub task
                     //set of the parent task. I believe this should have been done
                     //during the previous call, but atleast now, it does not happen
                     ((TaskImpl)task).addSubTask((TaskImpl)subTask);
                    


                    Also there is a method in taskService to get sub tasks of a task, try using that when you need to get the sub tasks.


                    • 7. Re: Advice regarding complex proccess modeling

                      Hi,

                      Is there a similar API in JBPM3 that allows subTask creation for an existing task?

                      Any help would be appreciated.

                      • 8. Re: Advice regarding complex proccess modeling
                        kukeltje

                        no, not a similar api. You have to do it low level

                        • 9. Re: Advice regarding complex proccess modeling
                          mihai007

                          any idea about how to be notified when a subtask ends?

                          I mean I define a task in process xml, then an assignment handler for the task. There I set assignee as null and create 2 subtasks each assigned to a different user.

                           

                          When the users complete the subtask I would like to be notified so that I could close the main task and so the process goes on.

                          In xml is easy, I just do:

                          <on event="end">
                            <event-listener class="ABC" />
                          </on>
                          

                           

                          But how can I add such an event to a subtask that was created during run-time?

                           

                          P.S: having a timer to check endlessly for subtasks end does not count as it is not a viable solution.

                           

                          Oh and using the jbpm 4.3 with the solution presented by Santanu Saraswati to create the sub tasks

                          • 10. Re: Advice regarding complex proccess modeling
                            frankee787

                            How would it be possible to do the same thing in jBPM5 ?