cancel
Showing results for 
Search instead for 
Did you mean: 

How to find / signal a child execution?

iravanchi
Champ in-the-making
Champ in-the-making
Hi,

I have a process definition that contains an embedded sub-process.
In the sub-process, there's a wait state, and the execution waits for a signal on that.

Now, using the API, I want to find the executionId of the child execution to be able to signal it.
Using this code:
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
returns only one execution, and when I signal it, it throws NullPointerException.

How can I find the child execution and signal it?
6 REPLIES 6

iravanchi
Champ in-the-making
Champ in-the-making
I tried to follow the execution when signalling the parent execution, and why it throws.
Here's what happens:
* In SignalCmd, ExecutionEntity is loaded by ID.
* In the database record, the record corresponding to the parent execution is stored with ACTIVITY_ID_ = null, IS_ACTIVE_ = FALSE
* SignalCmd calls ExecutionEntity.signal(…) on the loaded object from DB
* ExecutionImpl.signal calls ensureActivityInitialized()
* Since the activityId == null, ensureActivityInitialized() doesn't do anything and returns.
* ExecutionImpl.signal then tries to call activity.getActivityBehavior(), and since activity == null (activityId was null) it throws.

I think this is a bug, and even if signalling the parent process is not valid, Activiti should provide a better error message.
And, how should I signal such a process?

-Hamed

jbarrez
Star Contributor
Star Contributor
Could you post your process? The query should return multiple values.

iravanchi
Champ in-the-making
Champ in-the-making
I have my custom elements in my process. But the one affecting this can be my "forEach" process. I've tried to create a forEach activity with a sub-process, similar to what is in embedded sub-process. Here's the code of the forEach activity. Do you think that there's something wrong with it?

public class ForEachSubProcessActivity extends AbstractBpmnActivity implements CompositeActivityBehavior
{
    //
    // Fields

    private String collectionVariableName;
    private String indexVariableName;
    private String itemVariableName;

    //
    // Initialization

    public ForEachSubProcessActivity(String collectionVariableName, String indexVariableName, String itemVariableName)
    {
        this.collectionVariableName = collectionVariableName;
        this.indexVariableName = indexVariableName;
        this.itemVariableName = itemVariableName;
    }

    //
    // Behavior implementation

    @Override
    public void execute(ActivityExecution execution) throws Exception
    {
        if (collectionVariableName == null)
            leave(execution);

        List collection = (List) execution.getVariable(collectionVariableName);
        if (collection == null)
        {
            leave(execution);
            return;
        }

        int currentIndex = 0;
        if (collection.size() < currentIndex + 1)
        {
            leave(execution);
            return;
        }

        Object currentItem = collection.get(currentIndex);

        execution.setVariable(indexVariableName, currentIndex);
        execution.setVariable(itemVariableName, currentItem);

        PvmActivity activity = execution.getActivity();
        ActivityImpl initialActivity = (ActivityImpl) activity.getProperty(BpmnParse.PROPERTYNAME_INITIAL);

        execution.executeActivity(initialActivity);
    }

    @Override
    public void lastExecutionEnded(ActivityExecution execution)
    {
        int currentIndex = (Integer)execution.getVariable(indexVariableName);
        List collection = (List) execution.getVariable(collectionVariableName);

        currentIndex++;
        if (collection.size() < currentIndex + 1)
        {
            // TODO: Remove the variables
            // the following lines wouldn't work. It causes an exception.
//            execution.setVariable(indexVariableName, null);
//            execution.setVariable(itemVariableName, null);

            List<PvmTransition> outgoingTransitions = execution.getActivity().getOutgoingTransitions();
            execution.takeAll(outgoingTransitions, new ArrayList<ActivityExecution>());

            return;
        }
        Object currentItem = collection.get(currentIndex);

        execution.setVariable(indexVariableName, currentIndex);
        execution.setVariable(itemVariableName, currentItem);

        PvmActivity activity = execution.getActivity();
        ActivityImpl initialActivity = (ActivityImpl) activity.getProperty(BpmnParse.PROPERTYNAME_INITIAL);

        execution.executeActivity(initialActivity);
    }
}

iravanchi
Champ in-the-making
Champ in-the-making
The reason it doesn't return multiple results is in the ExecutionQueryImpl. A snippet:

public ExecutionQueryImpl processInstanceId(String processInstanceId) {
    this.executionId = processInstanceId;
    this.onlyProcessInstances = true;
    return this;
  }

I don't realize why would it use processInstanceId for executionId (I know they are the same for root token, but shouldn't filter by ID of execution.)
in the runtime.mapping.xml:
      <if test="executionId != null">
        and E.ID_ = #{executionId}
      </if>
This means only one returned row.
Also, the method sets "onlyProcessInstances" to true. According to the runtime.mapping.xml:
      <if test="onlyProcessInstances">
        E.PARENT_ID_ is null
      </if>

This again means that I won't get my child executions.

In my opinion, ExecutionQueryImpl should have another field called processInstanceId, which should be used by the query method mentioned above.
Am I right?

jbarrez
Star Contributor
Star Contributor
Which version are you using?

I'm looking at trunk now, and this is the code:


  public ExecutionQueryImpl processInstanceId(String processInstanceId) {
    if (processInstanceId == null) {
      throw new ActivitiException("Process instance id is null");
    }
    this.processInstanceId = processInstanceId;
    return this;
  }

iravanchi
Champ in-the-making
Champ in-the-making
I have beta1. Haven't updated my code since.
I guess beta2 should be good. Sorry.

I need to run an update on my checkout.