Defining the assignee

591 views
Skip to first unread message

stefa...@gmx.net

unread,
Sep 18, 2015, 12:34:41 AM9/18/15
to camunda BPM users
Hello,

I managed to do the tutorial. There, the assignee is defined directly in the user task. Now I want to test the use of pools and lanes in the example-bpmn.

Is it sufficient to give the pool/lane the name of a user e.g. john or peter and then to draw the user task into the lane?

Is there any documentation on this?
Cheers!
Stefan

thorben....@camunda.com

unread,
Sep 18, 2015, 2:31:32 AM9/18/15
to camunda BPM users, stefa...@gmx.net
Hi Stefan,

No, this is not sufficient since in BPMN lanes are not restricted to representing people performing work (although they are often used for this purpose). See [1] for how to assign users to tasks.

Cheers,
Thorben

[1] http://docs.camunda.org/manual/7.3/api-references/bpmn20/#tasks-user-task-user-assignment

stefa...@gmx.net

unread,
Sep 18, 2015, 9:11:25 AM9/18/15
to camunda BPM users
Hi Torben,

thanks for the prompt reply. Does that mean, if I change the role of a lane I have to adapt every assignee in every single user task manually?

Isn't there a more elegant way?

Stefan

thorben....@camunda.com

unread,
Sep 18, 2015, 9:52:26 AM9/18/15
to camunda BPM users, stefa...@gmx.net
Hi Stefan,

You can also define the assignee via a variable that you hand over when starting the process or you can resolve it from a Spring or CDI bean. This can be done by using an EL expression in the assignee field, for example ${assignee} where assignee is a String process variable or ${bean.getAssignee()} where bean is a variable/Spring bean/CDI bean that exposes a method #getAssignee. There are examples of this in the BPMN reference I linked before. You could probably even write logic that dynamically extracts the lane name from the BPMN XML and returns the name.

Cheers,
Thorben
Message has been deleted
Message has been deleted

stefa...@gmx.net

unread,
Sep 26, 2015, 2:55:50 PM9/26/15
to camunda BPM users
Hi Thorben,

my perfekt setting would be: Just in the bpmn-file are all definitions. Within the User Task I would like to set the assignee = ,Name of the lane I am in'

Is that possible possible without any external code outside the bpmn file?

Cheers,
Stefan

thorben....@camunda.com

unread,
Sep 28, 2015, 4:32:43 AM9/28/15
to camunda BPM users, stefa...@gmx.net
Hi Stefan,


Is that possible possible without any external code outside the bpmn file?

In short: No, not without custom code.

However, it should be possible to implement a generic solution without changing every process definition. I implemented this as an example here: https://github.com/ThorbenLindhauer/camunda-engine-unittest/tree/lane-assignee

Basically, you have to use a parse listener that replaces the task decorator that is used at runtime to determine a task's assignee. The decorator implementation accesses the current BPMN element to determine the current lane and its name. Note that this uses internal API, so there's no guarantee this will work with future Camunda versions. Also, be aware that this is not the most robust implementation ;). The task listener should probably do some validation, etc.

Cheers,
Thorben

Matthias Brenner

unread,
Sep 29, 2015, 3:48:24 AM9/29/15
to camunda BPM users, stefa...@gmx.net
Hello Thorben,
I had a look at the code you posted here. You use a TaskDecorator, which is inserted by a user task parse handler. The old decorator is removed, no calls are forwared to the old decorator.
Isn't there the danger to loose some functionality which could be available within the replaced decorator?

I did a similar implementation by using a ExecutionListener on the start event, which as added by the user task parse handler.

Can you provide a statement to compare both methods?

Kind regards
Matthias

thorben....@camunda.com

unread,
Sep 29, 2015, 3:59:16 AM9/29/15
to camunda BPM users, stefa...@gmx.net
Hi Matthias,

Since my approach uses internal API and not a public API extension point of the BPM platform, there is certainly the possibility to break functionality. Another, probably more robust implementation could wrap the existing task decorator or make a super call under certain conditions. I recommend writing tests for the functionality you want to achieve (or that you fear to break) if you do such a thing, which I didn't do in the example for convience reasons.

To compare it with your execution listener implementation, could you please share the listener code?

Cheers,
Thorben

Matthias Brenner

unread,
Sep 29, 2015, 7:50:36 AM9/29/15
to camunda BPM users, stefa...@gmx.net
Hello Thorben,

I modified your example like this:

```java
public class TaskAssigneeParseListener extends AbstractBpmnParseListener {

    @Override
    public void parseUserTask(final Element userTaskElement, final ScopeImpl scope,
            final ActivityImpl activity) {

        final ActivityBehavior behavior = activity.getActivityBehavior();
        if (behavior instanceof UserTaskActivityBehavior) {
            ((UserTaskActivityBehavior) behavior)
                    .getTaskDefinition()
                    .addTaskListener(
                            TaskListener.EVENTNAME_CREATE, new LaneAssigneTaskListener());
        }
    }
}
```
and than the listener (TaskListener)
```java

/**
 * Set the assignee from the lane
 *
 * @author Matthias Brenner
 *
 */
public class LaneAssigneTaskListener implements TaskListener {

    public void notify(final DelegateTask delegateTask) {

        final String assignee = getLaneIdOfTask(delegateTask);
        delegateTask.setAssignee(assignee);
    }

    private String getLaneIdOfTask(final DelegateTask delegateTask) {
        final String key = ((TaskEntity)delegateTask).getTaskDefinition().getKey();
        String assignee = null;
        final DelegateExecution execution = delegateTask.getExecution();
        final ExecutionEntity executionEntity = (ExecutionEntity)execution;
        final List<LaneSet> laneSets = executionEntity.getProcessDefinition().getLaneSets();
        for (final LaneSet laneSet : laneSets){
            for (final Lane lane : laneSet.getLanes()){
                for (final String nodeId : lane.getFlowNodeIds()){
                    if (nodeId.equals(key))
                        assignee = lane.getName();
                }
            }
        }
        return assignee;
    }
}
```

thorben....@camunda.com

unread,
Sep 29, 2015, 8:37:21 AM9/29/15
to camunda BPM users, stefa...@gmx.net
Hi Matthias,

That's a valid solution too. There is a subtle difference though. Consider the implementation of UserTaskActivityBehavior [1]:

1: Create a task entity
2: Apply decorator
3: Fire history "create" event
4: Invoke task "create" listeners in any order

Your approach is valid if it is not important that the history "create" event contains the correct assignee and that other, preceding task listeners might not access the assignee. I'm also not sure if we update the task assignee correctly in the history when you change it immediately afterwards in the task listener.

Cheers,
Thorben

[1] https://github.com/camunda/camunda-bpm-platform/blob/master/engine/src/main/java/org/camunda/bpm/engine/impl/bpmn/behavior/UserTaskActivityBehavior.java#L43-L52
Reply all
Reply to author
Forward
0 new messages