Monday, September 19, 2022

HTTP Retry - Groovy + Looping Process Call

This blog post will cover the HTTP Retry process using a Groovy script and Looping process call combination. Sometimes, we get a temporary time out error on the HTTP endpoint. To tackle this, we can use this mechanism to do a http retry for a specific interval / specific number of times. 


Overall iFlow Design:


Set Properties in Content modifier:

For the Groovy script to work, we need to declare the below properties.



Looping Process Call:




HTTP Retry Groovy Script:


If the HTTP Response code is greater than or equal to 400, the script will retry depending on the retry_interval and retry_limit properties.

-------------------------------------------------------------------------------------------------------------


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

import java.util.HashMap;

def Message processData(Message message) {


        def map = message.getHeaders();

        def  httpStatusCode = map.get("CamelHttpResponseCode") as Integer;

        def _loopIndex=message.getProperty("CamelLoopIndex") as Integer;

        def _propRetryLimit = message.getProperty("propRetryLimit") as Integer;

        def _propRetryInterval=message.getProperty("propRetryInterval") as Integer;

        def _retryFlag=false;

        

        switch(httpStatusCode>=400)

        {

            case true:

            switch(_loopIndex+1<=_propRetryLimit) {

                case true:

                    _retryFlag=true;

                    sleep(_propRetryInterval);

                    break;

                case false:

                    _retryFlag=false;

                    //def ex = properties.get("CamelExceptionCaught");

                    throw new Exception("HTTP request failed after exausting configured retry limit with status code:"+map.get("CamelHttpResponseCode")+" response body:"+ message.getBody(java.lang.String));

                    break;

            }

            break;

            case false:

            _retryFlag=false;

            break;

        }

        

        message.setProperty("propIsRetry",_retryFlag)

       

       return message;

}


-------------------------------------------------------------------------------------------------------------

Note:

Disable the throw exception checkbox in HTTP Adapter, else the flow won't move to the next shape (Groovy script) and will get halted.






With Throw Exception Enabled, error message will be as below: (here I am purposefully making the http call fail)




Flow with Throw Exception Enabled: It won't go to the next shape avail - Groovy script




-------------------------------------------------------------------------------------------------------------

With Throw Exception Disabled, error message will be as below: (here I am purposefully making the http call fail)





CamelLoopIndex starts with zero.




------------------------------------------------AMOR FATI---------------------------------------------------



XSLT Mapping - Extract Integer value

 I had a requirement where in we wanted to extract the km value from a node value.


Input XML Example:

-------------------------------------------------------------------------------

<root>

<test>Nasik 180km Bombay</test>

</root>




-------------------------------------------------------------------------------


XSLT Mapping used:

-------------------------------------------------------------------------------

<xsl:stylesheet version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:strip-space elements="*"/>


 <xsl:template match="/*">

     <xsl:value-of select=

      "translate(.,translate(., '0123456789', ''), '')"/>

 </xsl:template>

</xsl:stylesheet>


-------------------------------------------------------------------------------





Output:





-------------------------------------Love Your Fate ----------------------------------------------------------

Monday, March 7, 2022

Content Modifier - Concatenate Array Inputs ( Dynamic Parent Node)

 

 Requirement is to extract the repeated XML node with Dynamic Parent Nodes.






Here, we are passing the below payload directly in Content Modifier - Message Body

--------------------------------------------------------------------------------------------------------------------

<message>

    <header>

      <messageId>1</messageId>

      <masterMsgId>33300453700</masterMsgId>

      <equipment>

        <serialNumber>API TestSNVin</serialNumber>

        <make>CAT</make>

        <model>D100</model>

        <nickname>API Test Asset</nickname>

      </equipment>

      <moduleCode>API TestDeviceSN</moduleCode>

      <moduleTime>2022-02-16 10:45:14</moduleTime>

      <receivedTime>2022-02-16 10:45:14</receivedTime>

      <owner>Equipment Owner</owner>

    </header>

    <serviceMeter>

      <value>79</value>

      <uom>Hours</uom>

    </serviceMeter>

    <mileage>

      <value>13</value>

      <uom>Miles</uom>

    </mileage>

    <location>

      <latitude>7</latitude>

      <longitude>77</longitude>

      <validity>V</validity>

    </location>

  </message>

--------------------------------------------------------------------------------------------------------------------


Groovy Script:

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


import java.util.HashMap;

import java.util.*;

def Message processData(Message message)

{

    def body = message.getBody(java.lang.String) as String;

    def root = new XmlParser().parseText(body);

    def i=0;

    def errors="";

    def allmessage=[];

        root.'**'.findAll { it.name() == 'value'}.each { a ->allmessage << a.text()};

    int len = allmessage.size();

    while(i<allmessage.size())

    {

        errors=errors+","+allmessage[i];

        i++;

    }

        errors=errors.substring(1);

     def messageLog = messageLogFactory.getMessageLog(message);

       if(messageLog != null){

        messageLog.setStringProperty("Logging1", "Printing Payload As Attachment");

        messageLog.addAttachmentAsString("only_message:", len + "message – "+errors, "text/plain");

     }

     message.setBody(errors);

    return message;

}




--------------------------------------------------------------------------------------------------------------------

Output:  We need the data from Value nodes

<value></value>  ,  with two Parent nodes (Dynamic) -  serviceMeter and mileage





Content Modifier - Concatenate Array Inputs

 Requirement is to extract the repeated XML node with Static parent node.




Step 1 -

Here, I am passing input in the Content modifier itself.


Sample Input:

<Root>

<Employee>

<Name>Akshay</Name>

<ID>1</ID>

</Employee>

<Employee>

<Name>Sudeep</Name>

<ID>2</ID>

</Employee>

<Employee>

<Name>Advik</Name>

<ID>3</ID>

</Employee>

<Employee>

<Name>Hirva</Name>

<ID>4</ID>

</Employee>

</Root>

-----------------------------------------------------------------------------------------------------------------------------

Step 2 :

Declare Property variables to hold the output.



Name_Concat

 string-join(/Root/Employee/Name, ",")


ID_Concat

 string-join(/Root/Employee/ID, ",")


Below is the config. of the message body tab of the content modifier:



-----------------------------------------------------------------------------------------------------------------------------

Step 3:

Using a Groovy script to log the payload

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
def messageLog = messageLogFactory.getMessageLog(message);
messageLog.addAttachmentAsString("Payload", body, "text/plain");
return message;
}

-----------------------------------------------------------------------------------------------------------------------------


Final Output :






Tuesday, March 1, 2022

Global Data Store & Variable

 The first iFlow shows how to write a variable (Global) and Write the incoming data to a Data Store.

Whereas, in the second iFlow we will fetch data from the data store which was declared in the first iFlow. 


First iFlow (Producer)



Address :

https://refapp-espm-ui-cf.cfapps.eu10.hana.ondemand.com/espm-cloud-web/espm.svc

 


Write Variable:

Write Variables are used to share data across different integration flows (deployed on the same tenant).

To consume the variable (either in another step of the same integration flow or in another integration flow), can use a Content Modifier.

A variable gets expired after the retention period which is 400 days.



Data Store Write Operation:

This step performs a Write operation on the transient data store.

Entry ID

Specify an entry ID that is stored together with the message content. The entry ID must not exceed 255 characters.

Details for the entry ID are read from the incoming message. You can enter the following kinds of expressions:

  • ${header.headername}, to dynamically generate the entry ID from the message header.
  • ${property.propertyname}, to dynamically generate the entry ID from the exchange property of the message.
  • ${xpath.<xpath>}, to dynamically generate the entry ID from an element in the message indicated by an xPath expression.

 





Below is Log for WRITE VARIABLE Step:


 



Below is Log after Splitter step:

You will observe 18 different Segments for General Splitter in the Trace mode.

Each Splitter consisting of one CustomerReview node.

 


 


 

 

Second iFlow (Consumer)

 



This step selects entries from a transient data store and creates a bulk message containing the data store entries.


 Content Modifier 1


Content Modifier 2


 Postman :



 

 


Saturday, February 26, 2022

XML to CSV Conversion

 Input to Content Modifier:

--------------------------------------------------------------------------------------------------------


<Records>


                <Header>


                                <FieldA>H_ABC</FieldA>


                                <FieldB>H_123</FieldB>


                                <FieldC>H_XXX</FieldC>


                                <FieldD>H_567890</FieldD>


                </Header>


                <Line>


                                <Field1>ABC</Field1>


                                <Field2>123</Field2>


                                <Field3>XXX</Field3>


                                <Field4>567890</Field4>


                </Line>


                <Line>


                                <Field1>XYZ</Field1>


                                <Field2>456</Field2>


                                <Field3>YYYY</Field3>


                                <Field4>98765</Field4>


                </Line>


</Records>

--------------------------------------------------------------------------------------------------------------------





------------------------------------------------------------------------------------------------------

When configuration of XML to CSV:



Output:




------------------------------------------------------------------------------------------------------

Config : 



Output:





------------------------------------------------------------------------------------------------------


Config:



Output:




------------------------------------------------------------------------------------------------------


Config:

 


Output:



-----------------------------------------------------------------------------------------------------------------------------


Thursday, February 24, 2022

General Splitter




 Demo Scenario :

Content Modifier: Body 

---------------------------------------------------------

<root xmlns="demo.sap.com">

<shop>

<customerReview>

<id>001</id>

<rating>4</rating>

</customerReview>

<customerReview>

<id>002</id>

<rating>1</rating>

</customerReview>

<customerReview>

<id>003</id>

<rating>1</rating>

</customerReview>

<customerReview>

<id>004</id>

<rating>1</rating>

</customerReview>

<customerReview>

<id>005</id>

<rating>1</rating>

</customerReview>

</shop>

</root>

---------------------------------------------------------















Please also refer to the below blog for elaborative analysis :

https://blogs.sap.com/2020/09/21/sap-cloud-platform-integration-general-splitter/