This blog post, as part of this blog series, refers to the recently introduced Conditional Start feature in SAP NetWeaver BPM available with SAP NetWeaver 7.3 EHP 1 SP 06 and higher.
This blog post uses a simple scenario as an example: One division of a stationery manufacturer produces graphite pencils . Factory workers manually choose ten graphite pencils and separate them into bins on a conveyor belt so that they can be packed by a machine.
In SAP NetWeaver BPM a web service endpoint is represented by a reusable message trigger. A process uses the so-called Conditional Start feature, if the same message trigger is used in the start event and in at least one intermediate message event of the process. Processes that are making use of the Conditional Start feature are referred to as conditional start processes in the following. For a running instance of a conditional start process it is defined that messages with matching correlation criteria will be received by the intermediate message event. In case there is no running process instance with matching correlation criteria, the message will be received by the start event – given the start condition is satisfied – thereby spawning a new process instance. For further information, see also help.sap.com -> Conditional Start.
In the exemplary scenario: In case no bin exists that can consume graphite pencils, a new bin will be provided. The newly provided bin will then be able to take another nine graphite pencils until it is full. The graphite pencils of the filled bin can then be packaged. Again a new bin for the next pencil will be provided and so on. The described behavior is related to the so-called Aggregator Pattern – an Enterprise Integration Pattern – which is described in more detail in .
SAP NetWeaver BPM differentiates between message reception and message consumption. For further information see also help.sap.com -> Correlation for Intermediate Message Events. This means that process instances can receive an arbitrary number of incoming messages that match the defined correlation condition. However, the already received message must not be necessarily consumed before the process completes or terminates.
In non-conditional start processes the consumption of each received message is not guaranteed and not yet consumed messages are discarded upon process completion. The behavior of not yet consumed messages differs for conditional start processes. These messages are not discarded but handled appropriately: Not yet consumed messages are resent to the same web service endpoint again upon process completion/termination. In case that there is no running process instance of the same process definition with matching correlation criteria, the message shall be consumed by the message Start Event (given the start condition is satisfied). Again a new process instance of the current active definition is spawned. For further information see also help.sap.com -> Conditional Start. When a process instance of the same definition is running, the messages are provided to the running process instance (given the correlation condition is satisfied).
Example: An already running conditional start process instance is able to consume three messages. Three messages are sent to its web service endpoint and are consumed by the intermediate message event of the process instance. The process flow of the process instance continues and it takes some time until the process completes. During this time another two messages are sent to the web service endpoint and are received by the Intermediate Message Event but will not be consumed. When the process instance finally completes and terminates, these two messages are resent. The first resent message will spawn a new process instance. The second resent message will be consumed by the intermediate message event of the newly spawned process instance.
The explained scenario can be modeled as a simple conditional start process in BPMN using the process composer. In the process model, the graphite pencils are represented by messages sent to the web service endpoint. The graphic pencils are identified by an id, named graphite pencil ID.
However, the concepts explained in the following example can be easily mapped to other scenarios, e.g., in a purchase order scenario in which a customer can collect ten different graphite pencils – the order items – in a web shop. The different order items are then aggregated in the backend by a process and sent to the supplier.
The conditional start process model implementing the scenario is shown in Figure 1. The model details can be found at the end of this blog post.
Assume that no process instance of this conditional start process model is running on the process server. When a new message containing the pencil ID – representing a new unique graphite pencil – arrives at the process server a new process instance is spawned. The start event then consumes the message and temporarily saves the pencil ID in the CurrentPencilID data object. After that, the mapping activity AggregateCurrentPencilID concatenates the CurrentPencilID with a data object AggregatedPencilIDs containing the already aggregated pencil IDs.
The first message consumed by the Start Event also contains the number of messages (pencils) to aggregate, i.e., the size of the bin. This number is temporarily saved in the data object NumberOfPencilsToAggregate. The next Mapping Activity decreases this number by 1. The subsequent exclusive choice gateway checks the number. If the number is greater than zero, the process can consume further messages, i.e., the bin is not full. In this case the process flow follows the AggregateNextPencil edge of the gateway.
The intermediate message event then consumes the next message and saves the provided pencil ID again in the data object CurrentPencilID. Subsequently, the mapping activity AggregateCurrentPencilID aggregates the CurrentPencilID with the already aggregated pencil IDs in the AggregatedPencilIDs data object. Again the NumberOfPencilsToAggregate is decreased by 1. In case that thenumber has reached zero, i.e., the bin is full, the process flow follows the AllPencilsAggregated edge. An Automated Activity PackagePencils sends the aggregated pencil IDs stored in the AggregatedPencilIDs data object to a web service endpoint, i.e., the pencils are packaged by the supplier.
Table 1 shows the content of an exemplary process execution. The start message is consumed by the start event and the NumberOfPencilsToAggregate provided by the start message is 3. The pencil ID encapsulated in the payload of the start message is pencil_B, subsequent messages consumed by the intermediate message event contain the pencil IDs pencil_A and pencil_C in its payload.
|pencil_C||pencil_B pencil_A pencil_C|
Table 1 – Content of the AggregatedPencilIDs data object after three consumed messages
Note: The aggregation of the CurrentPencilID in the data object AggregatedPencilIDs as a space separated list is only done for simplification reasons. In real scenarios a complex type should be created which can hold an arbitrary number of CurrentPencilIDs.
So far, it is assumed that only graphite pencils are considered by the process model. However, if the process model should distinguish between different colors, i.e., aggregating pencil IDs from pencils of a specific color, the color can be defined as a correlation condition of the intermediate message event. For more information see blog post Conditional Start: Deep Dive (3/7).
The following section describes the details of the exemplary process model, which are important to model the process.
Create a new Conditional Start WSDL file ConditionalStart.wsdl. For your convenience you can copy the following WSDL content and paste it in the newly created file.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.org/ConditionalStart/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ConditionalStart" targetNamespace="http://www.example.org/ConditionalStart/"> <wsdl:types> <xsd:schema targetNamespace="http://www.example.org/ConditionalStart/"> <xsd:element name="ConditionalStartOperation"> <xsd:complexType> <xsd:sequence> <xsd:element name="numberOfPencilsToAggregate" type="xsd:int"></xsd:element> <xsd:element name="pencilID" type="xsd:string"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </wsdl:types> <wsdl:message name="ConditionalStartOperationRequest"> <wsdl:part element="tns:ConditionalStartOperation" name="parameters"/> </wsdl:message> <wsdl:portType name="ConditionalStart"> <wsdl:operation name="ConditionalStartOperation"> <wsdl:input message="tns:ConditionalStartOperationRequest"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="ConditionalStartSOAP" type="tns:ConditionalStart"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="ConditionalStartOperation"> <soap:operation soapAction="http://www.example.org/ConditionalStart/ConditionalStartOperation" /> <wsdl:input> <soap:body use="literal" /> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:service name="ConditionalStart"> <wsdl:port binding="tns:ConditionalStartSOAP" name="ConditionalStartSOAP"> <soap:address location="http://www.example.org/"/> </wsdl:port> </wsdl:service></wsdl:definitions>
The WSDL file contains an operation ConditionalStartOperation with two parameters pencilID and numberOfPencilsToAggregate.
Create a new message trigger ConditionalStartTrigger and select the just created web service as shown in Figure 2.
Model the process ConditionalStartProcess as shown in Figure 1. Refer to the following sections for modeling details of the process model.
Ensure that the data object CurrentPencilID as well as the data object AggregatedPencilIDs is of type string and the data object NumberOfPencilsToAggregate is of type int.
For the start and intermediate message event select the same message trigger ConditionalStartTrigger. This will enable the Conditional Start feature implicitly.
The NumberOfPencilsToAggregate has to be set once during process start via the start message. The first start message already contains a pencilID to be aggregated in its payload. Therefore the input values of the start message have to be mapped in the output mapping of the start event, to the data objects of the process context, as shown in Figure 3.
For further concatenation operations it is important that the AggregatedPencilIDs data object is initialized here by adding a simple function of an empty string to it:
Optionally a space can be added to the CurrentPencilID data object of the process context, such that the pencil IDs are separated by spaces in the AggregatedPencilIDs data object. Therefore, add a function to the CurrentPencilID data object:
concat(ConditionalStartOperation/pencilID, " ")
The aggregation of the CurrentPencilIDs takes place in the mapping activity AggregateCurrentPencilID. The data objects of the process context have to be mapped as shown in Figure 4.
To enable the mapping, a function needs to be added to the AggregatedPencilIDs data object on the right hand side:
Due to the already added space to the CurrentPencilID, the function will lead to a space separated list of pencil IDs.
To decrease the NumberOfPencilsToAggregate once a message is consumed either by the Start or the intermediate message event, the mapping activity DecreaseNumberOfPencilsToAggregate is needed. Define the activity by mapping the NumberOfPencilsToAggregate data object as shown in Figure 5.
In addition, add the following function to the NumberOfPencilsToAggregate data object on the right hand side:
NumberOfPencilsToAggregate - 1
The function will decrease the number of pencils to aggregate by 1.
To decide whether all pencil IDs are aggregated or not, set the conditions for the exclusive choice as shown in Figure 6.
If NumberOfPencilsToAggregate > 0 holds true, the edge AggregateNextPencil will be followed. If no further pencils are expected to be aggregated, the edge AllPencilsAggregated will be followed.
The Correlation Condition of the intermediate message event can be set to
because only messages for graphite pencils are sent to the endpoint.
A message sent to the intermediate message event also contains a pencilID to be aggregated in its payload. Therefore the input values of the message have to be mapped in the output mapping of the intermediate message event to the data objects of the process context, as shown in Figure 7.
As for the start event, a space can be added optionally to the CurrentPencilID data object of the process context, such that the pencil IDs are separated by spaces in the AggregatedPencilIDs data object. Therefore, add a function to the CurrentPencilID data object:
concat(ConditionalStartOperation/pencilID, " ")
The NumberOfPencilsToAggregate has to be set once during process start via the start message. Thus, a mapping is not needed here.
The automated activity PackagePencil can have any web service interface, which could make use of the AggregatedPencilIDs data object for instance. Also, a notification activity can be used here.