Persist Java Collection types from Java Delegate in service task

I have a service task and configured a Java Delegate. From Java Delegate, i want to persist the collection type ArrayList. I’m getting exception when i try to store ArrayList.

List<String> list = new ArrayList<>();
list.add("camunda");
list.add("jbpm");
list.add("activiti");
list.add("flowable");

How to persist this list in Java Delegate/Listeners?

what error are you getting?

@Niall the variable itself not getting persisted.

org.camunda.bpm.engine.ProcessEngineException: Unknown property used in expression: ${list}. Cause: Cannot resolve identifier ‘list’
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:63)
at org.camunda.bpm.engine.impl.el.JuelExpression.getValue(JuelExpression.java:51)
at org.camunda.bpm.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.resolveNrOfInstances(MultiInstanceActivityBehavior.java:107)
at org.camunda.bpm.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.execute(MultiInstanceActivityBehavior.java:64)

code:

@Component("loggerDelegate")
public class LoggerDelegate implements JavaDelegate {

  @Override
  public void execute(DelegateExecution execution) throws Exception {
    log.info("Start -> Logger delegate to bypass the activity");
    List<String> list = new ArrayList<>();
    list.add("camunda");
    list.add("jbpm");
    list.add("activiti");
    list.add("flowable");
    execution.setVariable("list", list);
    log.info("End -> Logger delegate to bypass the activity");
  }

}

Looks like that exception is not being thrown from the code that creates the list, but a multi-instance somewhere in your process that expects the list variable to exist. Does that make sense in your process model?

I was passing the list to multi instance to iterate and create an task instance for each element in the list.

And the list is created before the multi instance , I assume?

yeah. problem is persisting the list. In service task i’m trying to save the list. consider the below model for example.

image

I have tried ObjectValue , VariableMap, TypedValue, but no luck

Is the expression for the list used in a listener on the user task by any chance? And is that listener on the create event? Then the user task probably needs to be async before

Ehh sorry no, I see you use it as the collection for the mi task. Try making the service task async after.

1 Like

yeah. i made it async to save the list. List is used for multi instance task creation.

will try this

Hi @aravindhrs,

Other than making the service task async after, you can set the list as a transient variable.

Transient variables are not saved into the database and exist only during the current transaction.

https://docs.camunda.org/manual/latest/user-guide/process-engine/variables/#transient-variables

Note that the created elementVariable of the multi instance activity will be a persistent variable.

I can set, suppose if i have asyncBefore or asyncAfter between any of the tasks, for the variable which was been set scope=transient, will be accessed in further tasks?

Consider this, i will set “list” as transient variable in payload service, following a service task which is marked as asyncBefore, still can i access the transient variable in MI task? I hope not, because whenever task entity is persisted, transient variables will be removed at save point.

Hi @aravindhrs,

Transient variables exist only during the current transaction. And as async add transaction boundaries, transient variables would not exist any more.

yeah. That’s why i want to persist the collection in process variable.

It’s a silly mistake i made. Solved it by changing from List type to Collection type. After checking the code in MultiInstanceActivityBehavior.java found it :slight_smile:

image

@Component("loggerDelegate")
public class LoggerDelegate implements JavaDelegate {

  @Override
  public void execute(DelegateExecution execution) throws Exception {
    Collection<String> list = new ArrayList<>();
    list.add("camunda");
    list.add("jbpm");
    list.add("activiti");
    list.add("flowable");
    execution.setVariable("list", list);
  }
}

Hi @aravindhrs,

I don’t think this is the reason as List is considered as instance of Collection type.

I faced the same issue long back when I try to set candidate users from task Listener. Then I set the reference type as Collection and it worked.

For example, in task listener when we set a list of users as candidateUsers, i hope it should be of type “Collection”:

<bpmn:userTask id=“Task_0jrayd5” camunda:candidateUsers="${candidateUsers}" />

Other than that there’s no issue in storing the collection types.

If it’s as you descrive then I’d consider it a serious bug. But I can hardly believe that this has been unnoticed for so long!