Starting process instance and updating a task

I would like to start a process instance and make changes to a resulting task, e.g. change task name. Is it possible to do it in one Java API call?

Hello @nomadus,

That is possible, e.g. for a UserTask you could define a TaskListener:

public class ChangeNameTaskListener implements TaskListener {

	@Override
	public void notify(DelegateTask delegateTask) {
		delegateTask.setName("New Task Name");
	}
}

Then there is also this possible, e.g. for a JavaDelegate:

execution.getBpmnModelElementInstance().setName("New Name");

Best, McAlm

1 Like

Currently, I am doing

public void startProcess(String name) {
ProcessInstance processInstance = engine.getRuntimeService()
                    .startProcessInstanceByKey(key, "APP-" + newTaskDetail.getId());

            TaskService taskService = engine.getTaskService();
            List<Task> taskList = taskService.createTaskQuery()
                    .processInstanceId(processInstance.getId()).list();
            Task existingTask = taskList.get(0);
            existingTask.setName(name);
            taskService.saveTask(existingTask);
}

And synchronizing the resulting task with the needed data. The name is dynamic, which means I have to somehow pass the name string to the task. I can’t think how to pass that string with Listener or Java delegate.

Hi @nomadus,

if you pass the new task name as a transient variable (Process Variables | docs.camunda.org) it will be accessible in the task listener and not saved in the database.

If you have some asynchonous continuation between process instance start and the task listener, you have to use a regular process variable.

Hope this helps, Ingo

Thanks Ingo! I shall give it a try

Hi @Ingo_Richtsmeier,

I believe transient variables would be lost in the context of task listener as user task considered as a wait state.

Keep in mind that the name is passed from the start event.

What I did is, I created a custom entity, taskDetail, and persist it with all the variables coming as a RequestBody, see below.

 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
            TaskDetail newTaskDetail = taskDetailService.createTask(taskDetail);

            Map<String, Object> variables = new HashMap<>();
            variables.put("taskDetailId", newTaskDetail.getId());

            ProcessInstance processInstance = engine.getRuntimeService()
                    .startProcessInstanceByKey(key, "APP-" + newTaskDetail.getId(), variables);

In the task listener, I have access to above variable
_Logger.info("The task details are: " + taskDelegate.getVariable(“taskDetailId”));

and I could retrieve the details from the database and synchronize BPM task.

Hi @hassang,

your comment teased my curiosity as you may be right and I quickly created a test case for this.

This is the listener code:

package org.camunda.bpm.unittest;

import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.delegate.TaskListener;

public class RenameTaskListener implements TaskListener {

  @Override
  public void notify(DelegateTask delegateTask) {
    delegateTask.setName((String) delegateTask.getVariable("newName"));
  }
}

and this is the junit test, which runs successfully:

public class SimpleTestCase {

  @Rule
  public ProcessEngineRule rule = new ProcessEngineRule();

  @Test
  @Deployment(resources = {"testProcess.bpmn"})
  public void shouldExecuteProcess() {
    // Given we create a new process instance
    ProcessInstance processInstance = runtimeService().startProcessInstanceByKey("testProcess", Map.of("newName", Variables.stringValue("my name", true)));
    // Then it should be active
    assertThat(processInstance).isActive();
    // And it should be the only instance
    assertThat(processInstanceQuery().count()).isEqualTo(1);
    // And there should exist just a single task within that process instance
    assertThat(task(processInstance)).isNotNull();
    assertThat(task().getName()).isEqualTo("my name");
    assertThat(processInstance).variables().doesNotContainKey("newName");

    // When we complete that task
    complete(task(processInstance));
    // Then the process instance should be ended
    assertThat(processInstance).isEnded();
  }
}

The user task is persisted after the create listener has been executed.

The process model is attached: testProcess.bpmn (2.6 KB)

Hope this helps, Ingo

2 Likes

Hi @Ingo_Richtsmeier,

Thanks a lot… Interesting to know.
I thought even on create event it wouldn’t work.