Is it possible to delegate a task to another group or set of groups in jBPM6 ?

Solution Unverified - Updated -

Environment

  • Red Hat JBoss BPM Suite (BPMS)
    • 6.x

Issue

  • The requirement is to delegate a Task to another group different to the default task definition group(s).
  • It is possible to delegate a task to a group or a set of groups? How can it be achieved if possible?

Resolution

As per the WS-HT 1.1 specification whose section 4.10.3 Delegating or Forwarding a Human Task and page 59 tells the definition of Delegation operation of a task:

4.10.3 Delegating or Forwarding a Human Task
Task‟s potential owners, actual owner or business administrator can delegate a task to another user, making that user the actual owner of the task, and also adding her to the list of potential owners in case she is not, yet. A task can be delegated when it is in an active state (Ready,Reserved,InProgress), and transitions the task into the Reserved state. Business data associated with the task is kept.
...

Thus, as per this specification, a Task's potential owners, actual owner or business administrator can delegate a task to another user , not to a group or set of groups.

Diagnostic Steps

  • Even going through the source code of jBPM6 one can see that it is also adhering to the same definition provided in the WS-HT specification, in perspective of Task delegation feature. Here is a gist of the code flow for reference.
package org.jbpm.services.task.impl.command;
...
import org.jbpm.services.task.commands.DelegateTaskCommand;
...
public class CommandBasedTaskService implements InternalTaskService, EventService<TaskLifeCycleEventListener> {

    private CommandService executor;
    private TaskEventSupport taskEventSupport;

    public CommandBasedTaskService(CommandService executor, TaskEventSupport taskEventSupport) {        
        this.executor = executor;
        this.taskEventSupport = taskEventSupport;
    }

    @Override
    public <T> T execute(Command<T> command) {
        return executor.execute(command);
    }
    ...
    public void delegate(long taskId, String userId, String targetUserId) {
        executor.execute(new DelegateTaskCommand(taskId, userId, targetUserId));
    }
        ...

This calls for org.jbpm.services.task.commands.DelegateTaskCommand class's DelegateTaskCommand(long,String,String) constructor.

package org.jbpm.services.task.commands;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.kie.internal.command.Context;

/**
*Operation.Delegate 
        : [ new OperationCommand().{ 
                status = [ Status.Ready ],
                allowed = [ Allowed.PotentialOwner, Allowed.BusinessAdministrator  ],
                addTargetUserToPotentialOwners = true,            
                newStatus = Status.Ready,
                exec = Operation.Claim
            },
            new OperationCommand().{ 
                status = [ Status.Reserved, Status.InProgress ],
                allowed = [ Allowed.Owner, Allowed.BusinessAdministrator ],
                addTargetUserToPotentialOwners = true,                         
                newStatus = Status.Ready,
                exec = Operation.Claim
            } ],
 */
@XmlRootElement(name="delegate-task-command")
@XmlAccessorType(XmlAccessType.NONE)
public class DelegateTaskCommand extends UserGroupCallbackTaskCommand<Void> {

    /**
     * 
     */
    private static final long serialVersionUID = 5656199063761548979L;

    public DelegateTaskCommand() {
    }

    public DelegateTaskCommand(long taskId, String userId, String targetEntityId) {
        this.taskId = taskId;
        this.userId = userId;
        this.targetEntityId = targetEntityId;
    }

    public Void execute(Context cntxt) {
        TaskContext context = (TaskContext) cntxt;
        doCallbackUserOperation(userId, context);
        doCallbackUserOperation(targetEntityId, context);
        doUserGroupCallbackOperation(userId, null, context);
        context.getTaskInstanceService().delegate(taskId, userId, targetEntityId);
        return null;

    }
}

Internally the execute(..) method calls the TaskInstanceServiceImpl.delegate(..) method.

public class TaskInstanceServiceImpl implements TaskInstanceService {
...
    private LifeCycleManager lifeCycleManager;
...

    public void delegate(long taskId, String userId, String targetUserId) {
        lifeCycleManager.taskOperation(Operation.Delegate, taskId, userId, targetUserId, null, null);
    }
...

Looking into the signature of LifeCycleManager.taskOperation(...) , it says that the last parameter in the taskOperation method accepts List of Groups, which in case of delegation is null.

package org.jbpm.services.task.internals.lifecycle;
import java.util.List;
import java.util.Map;

import org.kie.internal.task.api.model.Operation;
import org.kie.internal.task.exception.TaskException;

/**
 *
 */
public interface LifeCycleManager {
    public void taskOperation(final Operation operation, final long taskId, final String userId,
                              final String targetEntityId, final Map<String, Object> data,
                              List<String> groupIds) throws TaskException;
}

Hence, as it is visible the delegation operation only performs the assignment of task to a user only not for groups.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments