SAP CPI – Distribute Messages to Multiple Recipients

Starting Situation

The task of a middleware is to collect messages and send them to the according receivers. Often, the correct receiver is determined during the integration process. Even, multiple receiver for a single message is common, splitting of copying the message content.

Example for Demonstration

Consider a file based integration, where the middleware has to pick up a file on an sFTP server and distribute the file to different sFTP servers, based on the file name. In our demo scenario here, we have

  • file_A.xml going to receiver A,
  • file_B.xml going to receiver B,
  • but also file_AB.xml going to both receiver systems.

Coming from classic SAP PI/PO

In SAP PI/PO, the integration flow (iFlow) can have a recipient list step. In the configuration of the recipient list, conditions for each route can be entered. The evaluation during the processing does not stop, if one condition is fulfilled. So for our demonstration example, we can simply define a condition matching file_A.xml and file_AB.xml for the route leading to system A (similar for system B). A file with name file_AB.xml matches both conditions and is therefore transferred to both receivers.

Explanation of migrated PI/PO Scenario

SAP CPI offers the function to migrate existing PI/PO integrations to CPI, if the backend connections are maintained properly. The aim of this blog entry is not to explain the migration process, but to explain the resulting integration.

Why not simply use a Router step in CPI?

The Router in SAP CPI does deliver the message to multiple routes, if multiple conditions match. In the demonstration example, file_AB.xml which matches the condition for both receivers is delivered only to one system, not both (evaluation stops after first match).

The Steps explained

The result of the migration process is a quite complex setup. The relevant part, which is copying the message according to the file name, is show here:

Part of the Integration setup after migration.

What happens during those steps:

  1. The payload of the message (in the example case, the file content) is stored as an exchange property called InboundPayload. The allows to completely overwrite the payload and restore it later.
  2. The receiver conditions step sets a boolean variable per receiver system. The value of the boolean is dynamically determined based on a condition (here: the file name pattern).
  3. Step receiver determination is a Groovy script, setting a new payload. Basically, the resulting payload contains a list of receivers (all receivers with true from the previous step).
  4. The following router checks, if there is any receiver system in the payload. If not, the processing is ended.
  5. An Iterating Splitter is used to split the payload into multiple messages. For each receiver section in the payload, a separate message is produced. As a result, there is a message per receiver.
  6. Only in the next step, the receiver (currently in the payload) is stored as header property and the original payload is restored (from exchange property created in step 1).

Since there is a message per receiver, another router reading the header property can now send the message to the appropriate receiver.

A new receiver should be added: steps to adjust

In order to add a new receiver to the setup, the following parts of the setup have to be adjusted.

A new conditional exchange property in the Receiver Conditions needs to be added. Important: the name of the property is used to set the receiver as header property. In the example, the receiver is called SystemA, so the property name is SAP-DYNREC-1-SystemA.

The condition is given as source value and has to be an expression which results in a boolean (true/false) value. In case of the file name, something like:

${header.CamelFileName} regex '(file_A|file_AB)\.xml'

Now, the properties are adjusted, so the next steps work without changes. Later in the integration process, the router, which actually distributes the messages, has to be extended to deal with a new receiver. Add a router to the new system and adjust the processing properties of the router to send messages to the new receiver using the ${header.SAP_Receiver} property.

Keep in mind, the content of the header property comes from the name of the exchange property in the Receiver Conditions step.

Alternative Setup for easy distribution

The complex setup generated during the migration process is working fine but seems quite overcomplicated for what was a simple Recipient List in SAP PI/PO. Maintenance and monitoring can be challenging, especially when additional mapping step come into play.

The alternative setup shown here is easy to understand and works without any Groovy scripts.

Since the CPI Router does not duplicate message, the first step uses Parallel Multicast operation. This copies the message for every receiver and processed the routes in parallel. Since not all messages should be transmitted to all receiver, a Router is used to filter the message on each branch (if necessary).

The filter works exactly as the condition in the setup explained before. The default route leads to a Termination Exit, so only message matching the condition are transferred to the target.

To set up new receivers, just add the system and connect it to the Duplicate Messages step. Then add a Router with the condition to filter messages (e.g. based on the file name).