Manually complete a Stage in CMMN with autoComplete=false

Hello,

i’m new to CMMN and i have written a GUI Application like in this underwriting-example. There it is really simple to get the active and enabled tasks with:

List caseExceutions = engine.getCaseService()
.createCaseExecutionQuery()
.caseInstanceId(this.caseInstance.getId())
.list();

Then they used CaseExecution Object to check it:

for (CaseExecution caseExecution : caseExecutions) {
if (caseExcecution.isActive()) {
activeCaseExecutions.add(caseExecution);
} else if (caseExcecution.isEnabled()) {
this.enabledCaseExecutions.add(caseExecution);
}
}

Let’s say i have a more complex case instance with two Stages named “s1” and “s2” with a set of tasks. I would like to give the responsibility to the user to complete a stage ( manually with a button), once it is possible. This button should only be rendered, if it is possible. I know from the above code, that a stage would be in this list as a CaseExecution object with type “stage” / “casePlanModel”

  1. How do i check if a stage can be completed? Is it possible from an CaseExecution-Object or in another handy way?
    The OMG specification says, that a stage can be completed if: There are no Active children, AND all required (requiredRule evaluates to “true”) children are in {Disabled, Completed, Terminated, Failed}_
    Do i have to iterate through all children elements of the stage and check their status? If so, how can i do it? Or do you have a better approach?

  2. If we assume the stage is completable: How do complete the stage? Do i have to disable tasks manually before or can i complete a stage in a cascading way?

I’m in my Master Thesis and there i have a much more complex CMMN Case. So this would be really important for me.

Thanks a lot for your help =)

Hi Andy,

Re 1) The public API does not offer a check to verify whether a stage can be completed or not. You have to implement it by your own.

Do i have to iterate through all children elements of the stage and check their status? If so, how can i do it? Or do you have a better approach?
Yes. You have to retrieve all case executions and check their status (but only of case executions which are children of the corresponding stage). Unfortunately I have not a better approach.

Re 2) You can use “CaseService#completeCaseExecution()”. This will complete the stage (if it is possible, if not it will throw an exception). The child executions in the stage “AVAILABLE” and “ENABLED” will be deleted by the engine, you do not have to disable the tasks manually before.

Does it help you?

Cheers,
Roman

Good morning Roman,
thanks for your quick answer.

  1. I have tried to implement the function, which should check, if a stage can be completed. I iterate through all child elements of a case Execution (i hope so). I would be very grateful, if you can look at it, because i’m a little bit unsure about it:

    public boolean isCompletable(CaseExecution stageExecution) {
    boolean isCasePlanModel = stageExecution.getActivityType().equals(CmmnModelConstants.CMMN_ELEMENT_CASE_PLAN_MODEL);
    boolean isStage = stageExecution.getActivityType().equals(CmmnModelConstants.CMMN_ELEMENT_STAGE);
    if (isStage || isCasePlanModel) {
    // Approach to get only childrens?
    List childrens = this.engine.getCaseService()
    .createCaseExecutionQuery()
    .caseExecutionId(stageExecution.getId())
    .list();

             // remove the first, because it is not a child?
             if (childrens.size() > 0) {
                 childrens.remove(0);
             }
             for (CaseExecution child : childrens) {
                 // A Stage can be completed, if there are no Active children -> active leads to false
                 if (child.isActive()) {
                     return false;
                 }
                 // AND all required (requiredRule evaluates to “true”) children are in {Disabled, Completed, Terminated, Failed}_
                 // all other status -> leads to false
                 else if(child.isRequired() && child.isAvailable()){
                     return false;
                 }
             }
             return true;
         }
    

Is it correct in this way or did i miss something?

  1. You said, if a stage can be completed:

The child executions in the stage “AVAILABLE” and “ENABLED” will be
deleted by the engine, you do not have to disable the tasks manually
before
What did you mean with deleting? In which transition state they are after that?

Thanks a lot again =)

Hi Andy,

Re 1)
The following code snippet will not return the children of the given stage case execution. It will return an array which contains only the stage case execution itself.
List<CaseExecution> childrens = this.engine.getCaseService() .createCaseExecutionQuery() .caseExecutionId(stageExecution.getId()) .list();

To get the children of the stage, you could try the following approach:
List<CaseExecution> executions = this.engine.getCaseService() .createCaseExecutionQuery() .caseExecutionId(stageExecution.getCaseInstanceId()) .list(); List<CaseExecution> children = new ArrayList<CaseExecution>(); for (CaseExecution execution : executions) { if (stageExecution.getId().equals(execution.getParentId()) { children.push(execution); } }

I would change the this guard
if(child.isRequired() && child.isAvailable()){ return false; }
as follows
if(child.isRequired() && !child.isDisabled()){ return false; }

Re 2)
When the parent stage is removed, then the children are also remove. If the children were in the state “AVAILABLE” or “ENABLED” then they will simply deleted and they do not perform any state transition.

Cheers,
Roman