This blog covers some ideas and approaches on routing of messages based on a particular XPath condition in SAP CPI.

Requirement :

  • Flow : SAP S4 HANA –> CPI –> 3rd party SFTP
  • Source : IDOC, Target : External Definition
  • IDOCs having no /ZCUSTOM_ZINVOIC02_INV/IDOC/E1EDP01/ZCUSTOM_E1EDP01_SUBITEM/ZFLAG=”A” need to be terminated in CPI and not sent to target system.
  • IDOCs having mixed values i.e combination of “A” and other values can be sent but mapping needs to be considered only for ZFLAG=”A”
  • Source is IDOC and target is a custom XML External definition
  • Multiple IDOCs can be sent in a batch

3 approaches were explored as below :

Approach 1 :

  • Use a message mapping and apply logic for checking ZFLAG value at root IDOC level. Suppress IDOCs having no Lines in IDOC having ZFLAG=A.
  • Use a router in next step and check if count of IDOCs is zero.
    • If count is not zero, pass it to main mapping in default route where IDOC-External Definition mapping is done (Default Route)
    • If count is zero then end that batch here ( Router Condition : count(//IDOC) = 0 )

Approach 2 :

  • Use a Groovy Script which keeps a count of all items having ZFLAG=”A” and sets the count as a Exchange Property
  • Use a router at next step to check if Exchange Property count is greater than zero
    • If count is not zero, pass it to default route where IDOC-External Definition mapping is done and sent ahead
    • If count is zero, then end that IDOC in CPI

Approach 3 :

  • Use a content modifier to capture all actual values of Flag in an Exchange Property and use another Exchange Property to capture the applicable value (Here it is “A”)
  • Use a router in next step and check if Applicable Value Exchange Property value exists in Actual value exchange property.
    • If applicable value exists in actual value list, pass it to main mapping in default route where IDOC-External Definition mapping is done
    • If applicable value does not exist in actual value list, end that IDOC in CPI

All 3 approaches are covered in detail below :

Approach 1 : Filter Mapping + Router + Main Mapping Combination

Approach%201%20%3A%20Filter%20Mapping%20+%20Router%20+%20Main%20Mapping

Figure 1- Approach 1 : Filter Mapping + Router + Main Mapping

Step 1 : Message Mapping which suppresses the IDOCs which do not have even one line item with ZFLAG=A

  • Use a message mapping and apply filter of checking ZFLAG value at root IDOC level and at E1EDP01 segment (Rest segments can be mapped one-one)
  • Suppress IDOCs having no Line item in IDOC having ZFLAG=A in mapping.

Mapping%20Logic%20for%20filtering%20IDOCs%20that%20do%20not%20have%20any%20line%20items%20with%20ZFLAG%3DA

Figure 2 – Mapping Logic for filtering IDOCs that do not have any line items with ZFLAG=A (Logic applicable for Root IDOC segment and E1EDP01 segment)

NOTE : After ifWithoutElse, a UDF is used which returns a single true, if atleast a single line item with ZFLAG=A exists in an IDOC, else, it will return false which will suppress that IDOC itself (UDF is not discussed here)

Step 2 : Conditional Routing

  • Step 2.1 : If count is not zero pass it to main mapping in default route where IDOC-External Definition mapping is done (Default Route)
  • Step 2.2 : If count is zero then end that batch here ( Router Condition : count(//IDOC) = 0 )

Router%20Condition%20for%20terminating%20IDOCs

Figure 3 – Router Condition for terminating IDOCs

Step 3 : Split and Map IDOC to XML as applicable

 

Simulation Results for Positive test Case : When IDOCs in a batch contains atleast one line item with ZFLAG=A. 4 IDOCs triggered in a batch, 2 have no line items with ZFLAG=A and 2 IDOCs have mixed values

Simulation%20result%20of%20Mapping%20Logic

Simulation%20result%20of%20Mapping%20Logic

Figure 4 – Simulation result of Mapping Logic for positive test case i.e when batch of IDOCs have atleast one line having ZFLAG=A. Out of 4 IDOCs in a batch, 2 are having mixed values of ZFLAG and 2 are having no line items with ZFLAG=A which are suppressed as shown above.

Simulation%20Result%20of%20iflow%20for%20positive%20test%20case%20i.e%20when%20batch%20of%20IDOCs%20have%20atleast%20one%20line%20having%20ZFLAG%3DA

Figure 5 – Simulation Result of iflow for positive test case i.e when batch of IDOCs have atleast one line having ZFLAG=A. Out of 4 IDOCs in a batch, 2 are having mixed values of ZFLAG and 2 are having no line items with ZFLAG=A which are suppressed in Mapping and the relevant filtered IDOCs are sent ahead.

 

Simulation Results for Negative test Case : When none of the IDOCs in a batch have line items with ZFLAG=A

Simulation%20result%20of%20mapping%20logic%20for%20negative%20test%20case

Figure 6 – Simulation result of mapping logic for negative test case i.e when batch of IDOCs have no lines having ZFLAG=A. Out of 2 IDOCs in a batch, none of them are having line items with ZFLAG=A which are suppressed as shown above.

Simulation%20Result%20when%20batch%20of%20IDOCs%20have%20no%20lines%20having%20ZFLAG%3DA

Figure 7 – Simulation Result of iflow for negative test case i.e when batch of IDOCs have no lines having ZFLAG=A. Out of 2 IDOCs in a batch, none of them are having line items with ZFLAG=A which are suppressed in Mapping out and hence count of IDOC is zero here, hence this batch is terminated in CPI.

 

Approach 2 : Groovy + Router + Main Mapping Combination

Approach%202%20%3A%20Groovy%20+%20Router%20+%20Main%20Mapping%20Combination

Figure 8 – Approach 2 : Groovy + Router + Main Mapping

  • Step 1 : Split the IDOCs
  • Step 2 : Groovy Script which keeps a count of all items having ZFLAG=”A” and sets the count as a Exchange Property-ZFLAG_Count
    // Purpose of using this groovy - per requirement, if an IDOC has no Line item (E1EDP01) containing ZCUSTOM_E1EDP01_ITEM/ZFLAG=A, then no output XML for that IDOC should be created from CPI.
    // Below script will return the count of ZFLAG=A in Exchange property, If count > 1 then send idoc to mapping, else end such message in CPI
    
    import com.sap.gateway.ip.core.customdev.util.Message;
    import java.util.HashMap;
    import groovy.util.XmlSlurper ;
    import groovy.xml.XmlUtil;
    import org.w3c.dom.*;
    import javax.xml.parsers.*;
    import java.io.*;
    import java.io.StringReader;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import org.w3c.dom.Document;
    import org.xml.sax.InputSource;
    def Message processData(Message message) 
    {
    def mapProperties = message.getProperties();
    
    //read message as string
    def body = message.getBody(java.lang.String) as String;
    
    //initialize variables
    def count=0;
    
    //Create a DocumentBuilder
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(new InputSource(new StringReader(body)));
    doc.getDocumentElement().normalize();
    
    //Extract the root element
    Element root = doc.getDocumentElement();
    System.out.println("Root element " + doc.getDocumentElement().getNodeName());
    NodeList nList = doc.getElementsByTagName("E1EDP01");
    
    for (int temp = 0; temp < nList.getLength(); temp++) 
    {
        Node nNode = nList.item(temp);
        Element eElement = (Element) nNode;
                  
        if (eElement.getElementsByTagName("ZFLAG").item(0).textContent.equals("A"))
        count++;
    }
        message.setProperty("ZFLAG_Count", count);
        return message;
        
    }
    

     

  • Step 3 : Use a router at next step to check if Exchange Property ZFLAG_Count
    • Step 3.1 : if count is greater than zero, pass it to default route where IDOC-External Definition mapping is done and sent ahead (Default Route)
    • Step 3.2 : If No, then end that IDOC in CPI (Condition : ${property.ZFLAG_Count} = ‘0’)Figure%209%20-%20Router%20Condition
      Figure 9 – Router Configuration
  • Step 4 : Mapping IDOC-XML as applicable


Simulation Results for Positive test Case : When IDOC in a batch contains atleast one line item with ZFLAG=A. 4 IDOCs triggered in a batch, 2 have no line items with ZFLAG=A and 2 IDOCs have mixed values

Figure%20-%20IDOCs%20having%20no%20ZFLAG%3DA%20ended%20in%20CPI

Figure 10 – IDOCs having atleast one ZFLAG=A sent to default route.

Figure%20-%20IDOCs%20having%20atleast%20one%20ZFLAG%3DA%20sent%20to%20default%20route

Figure 11 – IDOCs having no ZFLAG=A ended in CPI

Simulation Results for Negative test Case : When none of the IDOCs in a batch have line items with ZFLAG=A

Figure%20-%20No%20IDOCs%20in%20a%20batch%20contain%20line%20items%20with%20ZFLAG%3DA%20ended%20in%20CPI

Figure 12 – No IDOCs in a batch contain line items with ZFLAG=A ended in CPI

Approach 3 : Content Modifier + Router + Main Mapping Combination

Figure%2010%20-%20Approach%203%20%3A%20Content%20Modifier%20+%20Router%20+%20Main%20Mapping%20Combination

Figure 13 – Approach 3 : Content Modifier + Router + Main Mapping

  • Step 1 : Split the IDOCs
  • Step 2 : Use a content modifier
    • capture all actual values of ZFLAG in an Exchange Property (ZFLAG_ACTUAL_VALUES-string-join((//E1EDP01/ZCUSTOM_E1EDP01_SUBITEM/ZFLAG/text()),’,’)
    • capture all applicable values of ZFLAG in an Exchange Property (ZFLAG_APPLICABLE_VALUES). Here this value is hardcoded to “A” as per requirement. (This can also be externalized)

NOTE : Here another exchange property – ZFLAG_COUNT is used with XPath value : count(//E1EDP01[ZCUSTOM_E1EDP01_SUBITEM/ZFLAG=”A”])(We can leverage this as an alternative to Groovy script in Approach 2 as well!)

Content%20Modifier%20Exchange%20Properties%20%28ZFLAG_COUNT%20value%20can%20be%20levraged%20instead%20of%20Approach%202%20Groovy%20script%20as%20well%21%29
Figure 14 – Content Modifier Exchange Properties (ZFLAG_COUNT value can be levraged instead of Approach 2 Groovy script as well!)

 

  • Step 3 : Use a router in next step and check if Exchange Property-ZFLAG_APPLICABLE_VALUES value exists in exchange property-ZFLAG_ACTUAL_VALUES.
    • Step 3.1 : If Yes, pass it to main mapping in default route where IDOC-External Definition mapping is done (Default Route)
    • Step 3.2 : If No, end that IDOC in CPI (Condition : ${property.ZFLAG_ACTUAL_VALUES} not contains ${property.ZFLAG_APPLICABLE_VALUES}Router%20Configurations

      Figure 15 – Router Configuration

  • Step 4 : Mapping as applicable


Simulation Results for Positive test Case : When IDOC in a batch contains atleast one line item with ZFLAG=A. 4 IDOCs triggered in a batch, 2 have no line items with ZFLAG=A and 2 IDOCs have mixed values

IDOCs%20having%20atleast%20one%20ZFLAG%3DA

Figure 16 – IDOCs having atleast one ZFLAG=A sent to default route

Positive%20test%20Case%20%3A%204%20IDOCs%20triggered%20in%20a%20batch%2C%202%20have%20no%20line%20items%20with%20ZFLAG%3DA%20and%202%20IDOCs%20have%20mixed%20values

Figure – IDOCs having no ZFLAG=A ended in CPI

Simulation Results for Negative test Case : When none of the IDOCs in a batch have line items with ZFLAG=A

No%20IDOCs%20in%20a%20batch%20contain%20line%20items%20with%20ZFLAG%3DA%20ended%20in%20CPI

Figure 17 – No IDOCs in a batch contain line items with ZFLAG=A ended in CPI

 

Summary

Multi-dimensional approaches/ideas were shared for a requirement to bifurcate data based on repetitive XPath as explained above.

Hope this blog was informative with respect to the ideas on approaching a requirement with different ways and will be relevant to the CPI/PI/PO Developers/Consultants.

Constructive comments or feedback/suggestions if any on the above are welcome.

References

Filtering the IDoc Segment in SAP CPI | SAP Community

[SAP Cloud Platform-Integration] Content Filter in Detail | SAP Blogs

XPath Count | Mendix Documentation

Using XPath Functions (oracle.com)

Content Modifier Xpath Data Type | SAP Community

Get to know Camel’s Simple expression language in SAP Cloud Integration | SAP Blogs

Please explain Conditional router in detail in CPI | SAP Community

Concat same node field in XPath of CPI | SAP Community

Define Router | SAP Help Portal

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x