Task deadline handling

184 views
Skip to first unread message

Lance Leverich

unread,
Jan 10, 2017, 3:28:00 PM1/10/17
to jBPM Development
First, let me state that this is in regards to versions 6.4/6.5 of jBPM. It may not be applicable to the upcoming version 7.0, as I have not investigated that version. My current client is using version 6.4.0.Final, and I have verified that the following is still true in version 6.5.0.Final.

Second, let me ask the root question...Is there a simple way to replace/change the behavior of the task deadline service? I know about creating my own implementation of the NotificationListener, and registering it. However, that does not address the ability to affect the mechanism(s) for escalation/reassignment (at least not directly). And that is the challenge I face. The following text talks about why I need the ability to do this, and what I've done in my effort to make this change myself, without forking the jBPM code base. Unfortunately, I've hit a rather significant roadblock to the approach I describe below; which has prompted me to ask the above question. 

My current client wants to have tasks assigned in an automated fashion. That means that when a task is being created, a set of business rules is used to first determine candidates for assignment, then other rules rank the candidates for suitability, and finally a candidate is selected as the actual owner of the task. The actual owner is being assigned via the task service's delegate method. This all works well for the initial assignment of the task. But when we add SLA information (i.e. deadlines), the code that is meant to handle the task reassignment is not functioning as desired. 

From the execute method found in the org.jbpm.services.task.commands.ExecuteDeadlinesCommand class:

                   if (!escalation.getReassignments().isEmpty()) {
                       
                       taskEventSupport.fireBeforeTaskReassigned(task, ctx);
                       
                       // get first and ignore the rest.
                       Reassignment reassignment = escalation.getReassignments().get(0);
                       logger.debug("Reassigning to {}", reassignment.getPotentialOwners());
                       ((InternalTaskData) task.getTaskData()).setStatus(Status.Ready);
                       
                       List<OrganizationalEntity> potentialOwners = new ArrayList<OrganizationalEntity>(reassignment.getPotentialOwners());
                       ((InternalPeopleAssignments) task.getPeopleAssignments()).setPotentialOwners(potentialOwners);
                       ((InternalTaskData) task.getTaskData()).setActualOwner(null);
                       taskEventSupport.fireAfterTaskReassigned(task, ctx);
                   }

As can be seen in the above code snippet, the reassignment information is being retrieved (actually, it's only looking at the first reassignment object...any others are disregarded), and used to create an updated list of potential owners. The highlighted line illustrates the fact that the task is then left in the Ready state, without anyone assigned. Now, it seems like this should be a simple situation to remedy. My first attempt to do so has, however, hit a snag. I'll start by explaining my first attempt to change the behavior involved the following steps...
  1. Create a replacement for the ExecuteDeadlinesCommand class. We'll call it DeadlineExecutorCommand, and it extends the ExecuteDeadlinesCommand class, overriding the execute method to add our own desired behavior.
  2. Determine who was creating the ExecuteDeadlinesCommand object, and somehow cause it to create our object instead. 
    1. Instances of the ExecuteDeadlinesCommand object are created by objects that are created from classes defined within the org.jbpm.services.task.impl.TaskDeadlinesServiceImpl class
      1. The ScheduledTaskDeadline class is used if there is not a GlobalTimerService available. A replacement class was created, that overrides the call method, so that a DeadlineExecutor command is created instead of the ExecuteDeadlinesCommand.
      2. The TaskDeadlineJob and TaskDeadlineJobContext classes are used if there is a GlobalTimerService. A class was created, to replace the TaskDeadlineJob class. The replacement class overrides the execute method, to create DeadlineExecutorCommand objects instead of ExecuteDeadlinesCommand objects. 
    2. A replacement of the TaskDeadlinesServiceImpl class (nominally named DeadlineServiceImpl) was created, so that the schedule/unschedule methods could be overridden. These methods are what were creating the original ScheduledTaskDeadline and TaskDeadlineJob objects. The replacement class creates our new version of those objects.
  3. Determine what was creating the TaskDeadlinesServiceImpl object(s), and somehow cause it to create our DeadlineServiceImpl object.
This is the point where we run into issues. I saw that in the org.jbpm.services.task.HumanTaskConfigurator, as part of the getTaskService method, the TaskDeadlinesServiceImpl is getting initialized. That's easy enough to remedy; create my own version of the HumanTaskConfigurator, and have it initialize the DeadlineServiceImpl instead.

Ahh...if only the AddTaskCommand used the deadlines service that was initialized as part of the getTaskService method. Instead, the AddTaskCommand's execute method uses the passed in TaskContext object to get a TaskDeadlinesServiceImpl object, by calling new TaskDeadlinesServiceImpl to get an instance of the deadline service. This means that the replacement classes are not actually used within the context of the executing process/task. While creating the replacement classes was not difficult, it appears that getting those classes to be used is difficult.

In conclusion, I'll reiterate the foundational question. Is there a simple way to replace/change the task deadline behavior, especially as it relates to the escalation/reassignment functionality?

Maciej Swiderski

unread,
Jan 11, 2017, 1:31:50 AM1/11/17
to Lance Leverich, jBPM Development
Lance,

the simplest solution I see to described issue is to use TaskEventListener and implement afterTaskReassignmentEvent method (https://github.com/droolsjbpm/jbpm/blob/6.5.x/jbpm-human-task/jbpm-human-task-core/src/main/java/org/jbpm/services/task/lifecycle/listeners/TaskLifeCycleEventListener.java#L34) that way you will get access to task instance that you can then alter to your needs like change its state or potential owners based on rules etc.

Long term, as using event listener for this is a bit of abuse, we could externaize the logic within the ExecuteDeadlineCommand to be pluggable similar to notification listeners. So users can plug in their own implementation for reassignment. Feel free to create jira for this if you find it relevant.

Maciej

--
You received this message because you are subscribed to the Google Groups "jBPM Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jbpm-development+unsubscribe@googlegroups.com.
To post to this group, send email to jbpm-development@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jbpm-development/f61fa981-0cec-42a5-9eaa-480da835e4a5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages