Skip to Content
Technical Articles

EIPinCPI – Routing Slip

Previous – Scatter-Gather | Index | Next – Process Manager

This week, we’ll study a routing pattern known asĀ Routing Slip.

When do I use this pattern?

A routing slip contains information about the steps that need to be performed on a given message. For examples, IDocs received from an ECC system may require different steps based on the message type. These steps can be configured in a Content-Based Router for each message type.

Routing Slip in CPI

In CPI, there does not exist a component for Routing Slip. I will implement a custom Routing Slip in this blog.

We need two components to implement the Routing Slip pattern:

  1. A Content-based Router flow to attach the routing slip based on the message type
  2. A Routing Slip processor component that routes the message to the next step in the Routing Slip

Integration Flow – Routing Slip Attacher

Routing Slip Attacher

In this integration flow, the steps for each message type are configured.

Firstly, ‘Message Type?’ router routes the message based on the message type. The configuration is as follows:

Order Route Name Condition Expression Default Route
1 ORDERS05 ${header.SapIDocType} = ‘ORDERS05’ No
2 INVOIC02 ${header.SapIDocType} = ‘INVOIC02’ No
3 Other Yes

Secondly, on each route, a Content Modifier is used to set Header ‘RoutingSlip’. These are the values for each message type:

Message Type Value of ‘RoutingSlip’ Header
ORDERS05 /ECC/${header.SapIDocType}/Target/Map,/EnrichWithCustomerInformation,/ECC/Target/Send
INVOIC02 /ECC/${header.SapIDocType}/Target/Map,/ECC/Target/Send

Orders are mapped to target schema, customer information is added in the order information and, finally sent to the target system. Whereas, Invoices are mapped and sent to the target system.

The advantage of using Routing Slip is that the individual steps of enriching with customer information and sending IDocs to the target system can be reusable. The routing slip determines steps that a message needs to take.

Integration Flow – Routing Slip Processor

Routing Slip Processor

In this integration flow, if the previous step was the last step, then processing is ended, else the next step in the routing slip is determined using a Groovy Script.

This is the code for determining the next step:

import com.sap.gateway.ip.core.customdev.util.Message

def Message processData(Message message) {

    def routingSlip = message.getHeader('RoutingSlip', String)
    def steps = routingSlip.split(',')

    def nextStepIndex = steps.indexOf(message.getHeader('PreviousStep', String)) + 1
    message.setHeader('NextStep', steps[nextStepIndex])

    return message
}

Integration Flow – Individual Steps

The individual step must set header ‘PreviousStep’ with the path that it exposes and forward the message to Routing Slip Processor.

Mapping Flows

Mapping%20Flows

Mapping Flows

Enrich with Customer Information

Enrich%20with%20Customer%20Information

Enrich with Customer Information

Send to Target

Send%20to%20Target

Send to Target

Execution

Orders

These are the steps taken in processing orders:

  1. When the IDoc is dispatched from ECC, it is first received by Routing Slip Attacher. Routing Slip Attacher attaches the Routing Slip by setting the header ‘RoutingSlip’ and forwards the message to Routing Slip Processor.
  2. Routing Slip Processor recognises that the next step is to map the payload and forwards the message to Mapping flow.
  3. Mapping flow sets the ‘PreviousStep’ header, maps the payload, and forwards it to Routing Slip Processor.
  4. Routing Slip Processor recognises that enriching is the next step and forwards it to ‘Enrich with Customer Information’ flow.
  5. ‘Enrich with Customer Information’ sets the ‘PreviousStep’ header, enriches the payload with Customer Information, and forwards it to Routing Slip Processor.
  6. Routing Slip Processor recognises that sending to target is the next step and forwards it to ‘Send to Target’ flow.
  7. ‘Send to Target’ flow sets the ‘PreviousStep’ header, sends the payload to target and forwards the response to Routing Slip Processor.
  8. Routing Slip Processor recognises that the previous step was the last one and ends the processing.

In essence, the payload takes this trip as configured in the Routing Slip Attacher:

Routing Slip Attacher => Routing Slip Processor => Mapping => Routing Slip Processor => Enricher => Routing Slip Processor => Send to Target => Routing Slip Processor.

Invoices

For invoices, steps 1, 2, 3, 6, 7, and 8 are performed.

The Invoice payload takes this trip as configured in the Routing Slip Attacher:

Routing Slip Attacher => Routing Slip Processor => Mapping => Routing Slip Processor => Send to Target => Routing Slip Processor.

Limitations of this implementation

  • The same step cannot be used twice. At the moment, if the same step is mentioned twice in Routing Slip, then either the processing will get stuck in an infinite loop or the processing will end in an unexpected error.
    • While using the same step twice in a Routing Slip seems rare, this limitation can be overcome by appending to ‘PreviousStep’ header instead of setting it. We will have to rename the header to ‘PreviousSteps’ of course ;).
  • ProcessDirect in CPI does not support asynchronous processing. This means that the Routing Slip Attacher flow will keep waiting for response until all the steps in the Routing Slip are completed.
    • This limitation can be overcome by using JMS in place of ProcessDirect.

Conclusion

Routing Slip enables the developer to code reusable steps and to use them in a configurable manner based on a condition. A custom implementation is required to use Routing Slip pattern in CPI.

References/Further Readings

Hope this helps,
Bala

P.S.: What do you think of my implementation of Routing Slip pattern? Did you spot any improvements? Do you think it can be implemented in a different way? Please let me know your thoughts in comments.

Previous – Scatter-Gather | Index | Next – Process Manager

Be the first to leave a comment
You must be Logged on to comment or reply to a post.