Workflow Processing for Cases

A Case is a process instance which allows grouping any set of other process instances as subprocesses. Any added process instance will have the Case set as its root process. Only root processes can be added to a Case. Adding a Case to a Case is not valid. For details on Case process instances concepts, refer to chapter Case - Grouping Processes.

A Case supports the following functionality to create and modify the Case structure:

Additional functionality on Cases and Case Data is provided, like setting any primitive value as descriptor of the Case or modifying the name specified on creation. The following sections describe this functionality:

Creating a Case

When creating a Case, a Case name and member process instances have to be specified. By calling the createCase method of the WorkflowService the Case is created with the specified name and members.

For Example:

ProcessInstance memberProcessInstance1 = wfs.startProcess("{CaseModel}CaseProcess1", null, true);

long[] members = {memberProcessInstance1.getOID()};
ProcessInstance caseProcessInstance1 = wfs.createCase("Case1", members);

The required permission to execute this method is createCase.

Attaching a ProcessInstance to a Case

To add additional members to a Case the method joinCase of the WorkflowService can be used.

Example usage:

ProcessInstance memberProcessInstance2 = wfs.startProcess("{CaseModel}CaseProcess2", null, true);

long[] members2 = {memberProcessInstance2.getOID()};
ProcessInstance caseProcessInstance2 = wfs.joinCase(caseProcessInstance1.getOID(),

Detaching a ProcessInstance from a Case

Removing a process instance from the Case is possible with the leaveCase method of the WorkflowService. The specified process instances are removed from the Case hierarchy and are again root processes.

Example usage:

long[] members3 = {memberProcessInstance1.getOID()};
ProcessInstance caseProcessInstance3 = wfs.leaveCase(caseProcessInstance2.getOID(), members3);

Merging (Joining) Cases

Merging (or joining) Cases is done by using the mergeCases method of the WorkflowService. After the call the target Case will contain all process instances which were contained in the other specified Cases. Note that process attachments will also get merged to the target Case.

Example usage:

long[] sources = {caseProcessInstance1.getOID()};
ProcessInstance targetCaseProcessInstance2 = wfs.mergeCases(targetCaseProcessInstance.getOID(),

Delegating a Case

A created Case is automatically delegated to the creator of the Case. The owner of the Case will be able to delegate the Case to any other participant using the existing delegateToParticipant method of the WorkflowService.

Example usage:

ParticipantInfo participant = getModel().getParticipant("{CaseModel}Org1");
ActivityInstance delegatedAi = wfs.delegateToParticipant(ai.getOID(), participant);
Organization scopedOrg = getModel().getOrganization("{CaseModel}ScopedOrg1");
Department department1 = sf.getQueryService().findDepartment(null, "Department1", scopedOrg);
ActivityInstance delegatedAi = wfs.delegateToParticipant(ai.getOID(),

Setting and Reading Case Descriptors

A Case has the ability to store descriptors and its values dynamically per process instance. Descriptors for a Case are not designed at model time, instead it is possible to set any primitive value by using setOutDataPath or setOutDataPaths on the WorkflowService. The only exception is the Case name, which is also a descriptor but limited to the type String. Refer to section Setting a Case Name for details on the Case name. Retrieval of the Descriptors is possible via the ActivityInstance getDescriptorDefinitions() method, which returns a list of DataPath objects containing the IDs DataPath.getId() and MappedType DataPath.getMappedType() of the available descriptors. Finally by knowing the mapped type and IDs, the descriptor values can be retrieved by the ActivityInstance getDescriptorValue() method.

Note: It is also possible to retrieve the descriptor values by using getInDataPath or getInDataPaths on the WorkflowService. Using this method however also includes the process attachments which are not a descriptor but only a data path.

Example usage:

wfs.setOutDataPath(casePi.getOID(), "FirmId", Long.valueOf(123));

assertEquals(Long.valueOf(123), (Long) ai.getDescriptorValue("FirmId"));
assertEquals(Long.valueOf(123), (Long) wfs.getInDataPath(casePi.getOID(), "FirmId"));

List<DataPath> descriptorDefinitions = ai.getDescriptorDefinitions();
assertEquals("FirmId", descriptorDefinitions.get(1).getId());
assertEquals(Long.class, descriptorDefinitions.get(1).getMappedType());

Setting a Case Name

The Case name can be changed by the same means as descriptors by just using the reserved id for the Case name descriptor:

Example usage:

wfs.setOutDataPath(casePi.getOID(), PredefinedConstants.CASE_NAME_ELEMENT, "NewName");
assertEquals("NewName", wfs.getInDataPath(casePi.getOID(),

List<DataPath> descriptorDefinitions = ai.getDescriptorDefinitions();
assertEquals(String.class, descriptorDefinitions.get(0).getMappedType());

Factory methods of the ProcessInstanceQuery are provided to allow searching for Case members. It is possible to search all process instances that are Cases, Cases matching a specified name or members of a specific Case.

Example usage:

ProcessInstanceQuery query = ProcessInstanceQuery.findCases();

ProcessInstanceQuery query = ProcessInstanceQuery.findCaseByName("CaseForQuery1");

ProcessInstanceQuery query = ProcessInstanceQuery.findCaseMembers(caseProcessInstance.getOID());

ProcessInstances processInstances = sf.getQueryService().getAllProcessInstances(

Searching for Cases by Descriptor

Note that searching by Case descriptors is not supported, Thus finding a Case process instance based on one or more Case descriptor values is not possible. Case process instances can be found indirectly by searching for Case members and navigating up.

Note that when using the API of a Case functionality, you may get ConcurrencyException. In that case, wait for sometime and retry the API call.