Monday 20 December 2021

Google Chrome SAP MDPGroup SuperEasy Extension for SAP CPI /SCPI

SAP MDPGroup SuperEasy Extension:

In Google Chrome, Go to the three dots on the right top -> More Toole -> Extension.

Search for extension "CPI Helper" -> Add to chrome




MDPGroup SuperEasy Extension adds UX improvements and features to SAP Cloud Platform Integration Web UI

Features:

-System Logs Viewer that shows last lines with a quick refresh 
-Simulation mode automatically persists input headers and body. You can also extract or fill JSON data. 
-Partner Directory User Interface 
-ProcessDirect and JMS Dependency Graph for Flows 
-Groovy Syntax Checker 
-MPL CustomHeaderProperty Search 
-Settings for enabling/disabling extension features on regular CPI UI





Google Chrome extension for SAP CPI Helper /SCPI

SAP CPI Helper: 

In Google Chrome, Go to the three dots on the right top -> More Toole -> Extension.

Search for extension "CPI Helper" -> Add to chrome




Features of it:

Extends the SAP Cloud Platform Integration with some useful features to improve usability.
CPI Helper Chrome-Extension

This Chrome Plugin extends the SAP Cloud Platform Integration with some useful features. It includes a button to activate traces and a message sidebar directly in the Integration-Flow-Designer.
As SAP is not well known for it's usability it was time to integrate some features ourselves.

Features
Integration Flow Designer Improvements:
- Sidebar with processed messages
- Activate InlineTrace to see message route in integration flow designer
- Directly see trace messages in integration flow designer
- Pretty print for trace messages in integration flow designer
- Button to switch on trace
- Directly go to traces of specific message
- Directly go to logs and attachments of specific message
- Pop-up with error-message when hovering message in sidebar
- Pop-up with deployment info
- View and delete variables in info pop-up



Useful features in iflow on SAP CPI/ SCPI

While developing the objects in the SAP CPI iflow, we might not aware of or notice some features as a beginner. I can show some features which you can utilize it.

1. View the deployment status in the iflow development screen:

      Earlier we used to view in the manage integration content on Dashboard. Now we can view directly in the iflow development screen.

Can view deployment status such as Run time status,Deployed By, Deployed On, Deployed version



2. Copy the configuration from one palatte to others

     1. To copy the palatte object with its configuration


      2. To copy the adapter configuration:

3. Simulation mode for testing the mapping



        Test the mapping by importing the input data in xml format.




4. Run the complete iflow internally.

        Note:  It won't work on the timer flow.

        1. Start the simulation from where it needs to be tested


        2. End the simulation to where it needs to be tested.


      3. Start the simulation run using the below button:


5. Import the mapping from the local machine or from other iflows.

      1. Click outside of the integration flow, then go to resource tab below.

      2. Select the mapping/scripts which you want to import from other flow/local machine




6. From the monitoring screen, we can direct to iflow and can view / edit the artifact(iflow)








Monday 11 October 2021

Groovy script for picking the field from xml in array and select the particular value

 

Groovy script

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.*;
import groovy.util.logging.*;
import org.codehaus.*;


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


def XmlDataObject = new XmlSlurper().parseText(body)


def xmldata = []
def s="";
XmlDataObject.'**'.findAll { it.name()== 'UserServiceTransactionProcessingTypeCode'}.each { a ->
xmldata << a.text() }

message.setProperty("StatusCode",xmldata);
def newxmldata = xmldata as String[]
newxmldata = newxmldata.contains("ZCW1")

message.setProperty("StatusCode1",newxmldata);

return message;


}




Friday 1 October 2021

Pick the xml field from the huge payload and remove square brackets

 Pick the xml field from the huge payload and remove square brackets.

Groovy Script:


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

import java.util.HashMap;

import groovy.json.*;

import groovy.util.logging.*;

import org.codehaus.*;


def Message processData(Message message) {

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


map = message.getProperties();

requestid = map.get("ReqId");

taskid = map.get("TaskId");


requestid= requestid.toString().replaceAll("\\[", "");

requestid= requestid.toString().replaceAll('\\]', "");


def XmlDataObject = new XmlSlurper().parseText(body)


def xmldata = []

def s="";

XmlDataObject.'**'.findAll { it.name()== 'request_id'}.each { a ->

xmldata << a.text() }



def last = xmldata.last()

def xmldata2 = []

XmlDataObject.'**'.findAll { it.name()== 'task_id'}.each { a ->

xmldata2 << a.text() }

def last2 = xmldata2.last()

message.setProperty("requestid1",last);

taskid= taskid.toString().replaceAll("\\[", "");

taskid= taskid.toString().replaceAll('\\]', "");

message.setProperty("taskid1",last2);

message.setProperty("taskid2",taskid);

return message;

}



Wednesday 29 September 2021

SAP CPI Helper -Chrome Plugin for SAP CPI/HCI

We have a better feature in SAP CPI to enable the trace using the chrome plugin instead of changing the log level in the manage integration content.


To enable the chrome plugin "SAP CPI Helper":

1.Chrome browser -> Settings -> Extension -> Left top corner click three lines near to Extensions.

2. Below can see Open Chrome webstore -> Serach for "SAP CPI Helper"

3. Install it and can reopen the browser

4. Logout and login to the CPI tenant -> Go to Iflow developer page.

5. Can see the new option at right top corner as "Trace, Message, Info"

6. Here you can enable trace and when you change and deploy, the trace will be automatically activated.


This is a useful feature for the developer. Hope this helps, please do comment.




Friday 3 September 2021

Remove/replace xml tags and xml nodes from the error response to make valid json format in SAP CPI


Remove the xml tags and send only the error text to the target system from the exception process/negative response.

Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.lang.*
def Message processData(Message message) {
def body = message.getBody(java.lang.String) as String;
body = body.replaceAll("\\<\\?xml(.+?)\\?\\>", "").trim(); //Replace xml node
body = body.replaceAll("<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">","").trim();
body = body.replaceAll("<code>ERROR</code>", "").trim();
body = body.replaceAll("</message>", "").trim();
body = body.replaceAll("<message xml:lang=\"sv\">", "").trim();
body = body.replaceAll("<error>", "").trim();
body = body.replaceAll("</error>", "").trim();
body = body.replaceAll("\\\t|\\\n|\\\r","");
message.setBody(body);
return message;
}

Input:

{
"Response":
    {
    "status": "Error",
    "statusCode": "500",
    "C4CObjectID": "",
    "error": "<?xml version="1.0" encoding="utf-8"?><error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><code>ERROR</code><message xml:lang="sv">Invalid syntax in email address</message></error>"
}
}

Output:

{​​​​​​​​
"Response":
{​​​​​​​​
"status": "Error",
"statusCode": "500",
"C4CObjectID": "",
"error": " Invalid syntax in email address" }​​​​​​​​}​​​​​​​​



Thursday 12 August 2021

SAP CPI message mapping groovy script for different scenarios with context handlings



Add all values of the context


import com.sap.it.api.mapping.*;


def void addContext(String[] values, Output output, MappingContext context) {


output.addValue(values.sum{it.toBigDecimal()})

}



Return last value of the context


import com.sap.it.api.mapping.*;

def void returnlast(String[] values, Output output, MappingContext context) {

output.addValue(values.last())

}


Replace Null


import com.sap.it.api.mapping.*;

def String replaceNull(String arg1){

def len = arg1.length()

def output

if (len > 1)

output = arg1

else

output = arg1.replaceAll("","NA")

return output

}



Filter null and Suppress Null:


import com.sap.it.api.mapping.*

def void filterNullAndSuppress(String[] values, Output output, MappingContext context) {
def filtered = values.findAll { v -> v != null && !output.isSuppress(v) }
filtered.each { v -> output.addValue(v) }
}



Remove Suppress:


def void removeSuppress(String[] values, Output output, MappingContext context) {

values.each { v ->

if (!output.isSuppress(v)) {

output.addValue(v)

}
}
}


Find elements incontext that starts with

import com.sap.it.api.mapping.*

def void filterStatus(String[] values, Output output, MappingContext context) {

def filtered = values.findAll { v -> v.startsWith('2') }

filtered.each { v -> output.addValue(v) }

}


Find elements incontext that starts with


import com.sap.it.api.mapping.*

def void filterStatus(String[] values, Output output, MappingContext context) {

def filtered = values.findAll { v -> v.startsWith('1')|| v.startsWith('Z6')}

filtered.each { v -> output.addValue(v.split(/@/)[1]) }

}


Read Value map and store in property


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

import java.util.HashMap;

import com.sap.it.api.ITApiFactory

import com.sap.it.api.mapping.ValueMappingApi


def Message processData(Message message) {

//Body

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

def map = message.getProperties();

value=map.get("langcode")



def valueMapApi = ITApiFactory.getApi(ValueMappingApi.class, null)

def lang = valueMapApi.getMappedValue('c4c', 'language', value, 'ymkt', 'lang')

message.setProperty("lang", lang);

return message;

}


Split string with a delimiter


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

import java.util.HashMap;

import com.sap.it.api.mapping.*;

def String split(String arg1){

def output = arg1.split("@");

return output[1]

}



To check the input is numeric or not ->returns true or false.


import com.sap.it.api.mapping.*;

def String customFunc(String arg1){

def output = arg1.isNumber()

return output

}

Output payload:

<?xml version="1.0" encoding="UTF-8"?>

 <test>
       <id>true</id>
</test>



Rearrange one input according to other input field value in mapping groovy script in SAP CPI

Rearrange one input value according to other input field value inside message mapping. 


Groovy Script:

import com.sap.it.api.mapping.*;

def void customFunc(String[] Prod1, String[] Prod, String[] Cat, Output result,MappingContext context){

for(int i=0; i<Prod1.length; i++){

for(int j=0; j<Prod.length; j++){

if(Prod[j]==Prod1[i])

{
result.addValue(Cat[j])
}
}
result.addContextChange()
}
}




Remove duplicates in the mapping groovy script

Remove duplicates from the input field and place in a array and return the fields values.



Groovy Script:

import com.sap.it.api.mapping.*;


def void customFunc(String[] a, Output result){

def Prod = []

Prod[0]=a[0]

result.addValue(a[0])

for(int i=1; i<a.length; i++){

if(Prod.contains(a[i]))

continue;

else{

Prod.add(a[i]);

result.addValue(a[i]);

}
}
}




Thursday 10 June 2021

Groovy Script for removing the first two line from the csv/flat file in SCI/CPI/HCI

 Groovy script to remove first two lines from the string or csv file or flat file:


Remove first 2 lines:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import com.sap.it.api.mapping.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;

def Message processData(Message message) {

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

def lines=body.split("\n").drop(2).join("\n")

message.setBody(lines)
return message;
}

Input:

1Bricks measurement 24/60cm
2Ravikumar
3RAmu
4Dinesh
5Vishnu
6Pradab

Output:

3RAmu
4Dinesh
5Vishnu
6Pradab


Take first two lines:













Thursday 3 June 2021

Split the value by special character @ from the string using groovy script in SAP CPI/SCPI

Split the value by special character @ from the string using groovy script in mapping level in SAP CPI/SCPI.

Written a script to handle the logic on the splitting of two string using a special character

Groovy script:

import com.sap.it.api.mapping.*

def void filterStatus(String[] values, Output output, MappingContext context) {
def filtered = values.findAll { v -> v.startsWith('1')|| v.startsWith('Z6')}
filtered.each { v -> output.addValue(v.split(/@/)[1]) }

}


Input: 1@2020-05-23 22:00:00

Output: 2020-05-23 22:00:00




SAP CPI Testing tool -Figaf introduced

 Testing Tool for CPI message testing. Figaf Tool.


You can test without writing code or enabling the trace in the iflow.
  • Mock Testing
  • Secured Testing
  • Testing with multiply endpoints

Figaf Testing Tool




Thursday 15 April 2021

Groovy script to minus 10 minutes from current time and different stored format time.

It is the groovy script written for using the script in SAP Cloud platform integration interface flow.


Have written a Groovy script to minus 10 minutes from current time and different stored format time. This it required in building the query.


Input:   LastSuccessfulRun_Query = "04/14/2021 16:20:00"

Groovy Script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.util.TimeZone;
import groovy.time.TimeCategory;
def Message processData(Message message) {
//Body
def body = message.getBody();
//Properties

def curDateTime1 = "";
def before10mins = "";
def bef10mins = "";
def lastrun = "";
def value1 = "";
def tz = TimeZone.getTimeZone("UTC")
def ts = new Date()
map = message.getProperties();
value = map.get("LastSuccessfulRun_Query");
use( TimeCategory ) {

before10mins = ts - 10.minutes
lastrun = new Date(value) - 10.minutes

}

curDateTime1 = (ts.format("MM/dd/yyyy HH:mm:ss", timezone=tz))
bef10mins = (before10mins.format("MM/dd/yyyy HH:mm:ss", timezone=tz))
value1 = (lastrun.format("MM/dd/yyyy HH:mm:ss", timezone=tz))

def datequery = "(CREG_PROD_LAST_CHANGE_DATE_TIME ge"+"'"+lastrun+" UTC"+"'"+" and CREG_PROD_LAST_CHANGE_DATE_TIME le"+"'"+bef10mins+" UTC"+"'"+")";

// def datequery = "(CREG_PROD_LAST_CHANGE_DATE_TIME ge'01/15/2021 00:00:00 CET' and CREG_PROD_LAST_CHANGE_DATE_TIME le'01/20/2021 00:00:00 CET')";

message.setHeader("datequery",datequery);
message.setProperty("CurrentDate",curDateTime1);
message.setProperty("before10mins",before10mins);
message.setProperty("bef10mins",bef10mins);
message.setProperty("value",value);
message.setProperty("value1",value1);
message.setProperty("lastrun",lastrun);

return message;
}

Output:  value1 = "04/14/2021 16:10:00"



Wednesday 7 April 2021

Add double quotes to the fields Groovy Script in SAP CPI/SCI

Add double quotes to the fields Groovy Script in SAP CPI/SCI



Groovy Script:


import com.sap.it.api.mapping.*;


def String addQuotes(String value){

String quote = "\"";

String result = quote + value + quote;

return result;

}



Friday 12 March 2021

Script to pick the week day






import com.sap.it.api.mapping.*;

import java.util.Date;

import java.util.Calendar

import java.text.SimpleDateFormat


def String customFunc(String arg1){


//Calendar cal = Calendar.getInstance();

//int dayOfMonth = cal.get(Calendar.DAY_OF_WEEK);
//arg1 = String.valueOf(dayOfMonth);

Calendar cal = Calendar.getInstance();

int day = cal.get(Calendar.DAY_OF_WEEK);

if (day >= Calendar.MONDAY && day <= Calendar.THURSDAY){

arg1 = true;

}else{

arg1 = false;

}






return arg1

}


Random UUID generator in SAP CPI

 Groovy script:


import com.sap.it.api.mapping.*;

def String customFunc(String arg1){

def randomID = UUID.randomUUID().toString().replace("-", "").toUpperCase();

return randomID

}


Monday 8 March 2021

Basics: SOAP vs HTTP vs REST

SOAP :Simple Object Access Protocol vs REST:


SOAP - XML-based messaging protocol for exchanging information among computers.

SOAP needs more bandwidth for its usage whereas REST doesn't need much bandwidth

SOAP only works with XML formats whereas REST work with plain text, XML, HTML and JSON.

SOAP is a protocol whereas REST is an architectural pattern.

SOAP cannot make use of REST whereas REST can make use of SOAP.

Ease of coding – Coding REST Services and subsequent implementation is far easier than SOAP.

Protocol means - set of rules that determine how data is transmitted between different devices.


SOAP vs HTTP:
S.No.    SOAP    HTTP
1.SOAP stands for Simple Object Access Protocol.HTTP stands for Hypertext Transfer Protocol.
2.It is XML based used for sending and receiving messages.It is used to transfer information over the internet.
3.It supports web socket or WS-Addressing, WS-Security, SwA.It do not supports web socket or WS-Addressing, WS-Security, SwA.
4.HTTP is over TCP and IP.SOAP is over HTTP.
5.It support runtime checking against WSDL.It do not support runtime checking against WSDL.
6.It support Automatic processing of Message Transmission Optimization Mechanism (MTOM).It also support MTOM, but it must use the MIME message domain and design flow should be done to handle the attachments explicitly.
7.This protocol’s design is Data centric.This protocol’s design is Document centric.
8.It is a light weight data interchange protocol.It is not light weight data transfer protocol as SOAP.





Sunday 7 March 2021

CPI search using ID's

 

We would need to implement this feature in CPI to search on any specific Key ID’s like CustomerID, TicketID. So we will utilize this below.

 

Challenges:

As of now finding the specific data in CPI using any ID search is not implemented, as we search using timing and it is very difficult for us to find it if there are several message on every secs.

 

Solution:

 

Interface implementation:

 





Friday 5 February 2021

Header , Item, Trailer flatfile/fixed length file conversion in groovy script in SAP CPI

 There is no option in the CVS to XML convertor in CPI for converting the flat file. We can customize using the groovy script to achieve this.

Input:

NHEDSAPPS220C
16 20190523045
16 20190523046
16 20190523047
16 20190523048
TRAR000712

Groovy Script:


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

def Message processData(Message message) {

//Body

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

def lines = body.split("\n");


// variable initialization

def lineArr;

def itemtypPre;

def irlflag="E";

def irflag="E";

def hflag="E";

def Fieldentry = "";

def itemtyp;

def i=0;


//XML and root element formation

Fieldentry += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

Fieldentry += "<Root>";

for(i=0;i<lines.length;i++)

{

if(i>0)

{

//Item Type holder split from File i.e NH, 16, TR

itemtypPre = lines[i-1].substring(0,1);

}

//Item Type holder split from File i.e NH, 16, TR

itemtyp= lines[i].substring(0,2);


if(itemtyp.equals("NH"))

{

    Fieldentry += "<Header>";
    Fieldentry += "<ItemType>"+lines[i].substring(0,3)+"</ItemType>";
    Fieldentry += "<ISPID>"+lines[i].substring(4,5)+"</ISPID>";
    Fieldentry += "<Rate>"+lines[i].substring(6,7)+"</Rate>"
    Fieldentry += "</Header>";
}


if(itemtyp.equals("16")){


        if(irlflag.equals("O")) 

      {

        Fieldentry += "</Items>";

        irlflag="E";

      }
    Fieldentry += "<Items>";

    irlflag="O";

    // Fieldentry += "<ItemType>";
    Fieldentry += "<Type>"+lines[i].substring(0,2)+"</Type>"
    Fieldentry += "<FullClaimNumber>"+lines[i].substring(3,5)+"</FullClaimNumber>"
    Fieldentry += "<ClaimNumber>"+lines[i].substring(4,12)+"</ClaimNumber>"
    Fieldentry += "<AuthorizationCode>"+lines[i].substring(13,15)+"</AuthorizationCode>"
    // Fieldentry += "</ItemType>";
}


if(itemtyp.equals("TR")){

Fieldentry += "</Items><Trailer>";
Fieldentry += "<Type>"+lines[i].substring(0,4)+"</Type>"
Fieldentry += "<NumExtendedWarranty>"+lines[i].substring(5,8)+"</NumExtendedWarranty>"
Fieldentry += "<ElectroluxCustomerId>"+lines[i].substring(9,10)+"</ElectroluxCustomerId>"
Fieldentry += "</Trailer>";

} }

Fieldentry += "</Root>";

message.setBody(Fieldentry);

return message;

}


Output:

<?xml version="1.0" encoding="UTF-8"?>

<Root>

    <Header>

        <ItemType>NHE</ItemType>

        <ISPID>S</ISPID>

        <Rate>P</Rate>

    </Header>

    <Items>

        <Type>16</Type>

        <FullClaimNumber> 2</FullClaimNumber>

        <ClaimNumber>20190523</ClaimNumber>

        <AuthorizationCode>45</AuthorizationCode>

    </Items>

    <Items>

        <Type>16</Type>

        <FullClaimNumber> 2</FullClaimNumber>

        <ClaimNumber>20190523</ClaimNumber>

        <AuthorizationCode>46</AuthorizationCode>

    </Items>

    <Items>

        <Type>16</Type>

        <FullClaimNumber> 2</FullClaimNumber>

        <ClaimNumber>20190523</ClaimNumber>

        <AuthorizationCode>47</AuthorizationCode>

    </Items>

    <Items>

        <Type>16</Type>

        <FullClaimNumber> 2</FullClaimNumber>

        <ClaimNumber>20190523</ClaimNumber>

        <AuthorizationCode>48</AuthorizationCode>

    </Items>

    <Trailer>

        <Type>TRAR</Type>

        <NumExtendedWarranty>007</NumExtendedWarranty>

        <ElectroluxCustomerId>2</ElectroluxCustomerId>

    </Trailer>

</Root>





Monday 25 January 2021

Split Hour, Month separately from the date

Split Hour, Month separately from the date 

Groovy Script:

Date date = new Date();
println(date)// given date
Calendar calendar = Calendar.getInstance(); // creates a new calendar instance
def date1=calendar.setTime(date); // assigns calendar to given date
def time=calendar.get(Calendar.HOUR_OF_DAY); // gets hour in 24h format
println("time="+time)
def Time=calendar.get(Calendar.HOUR); // gets hour in 12h format
println("Time="+Time)
def month=calendar.get(Calendar.MONTH);
println("month="+month)
String a=time;
println("a="+a)
if(a=="6")
{
println("yes")
}
else
{
println("No")
}

Output:

12 ms

Mon Jan 25 15:43:58 UTC 2021

time=15

Time=3

month=0

a=15

No


Hours splitting from the current date

Groovy script to pick only the Hour from the current date.


Groovy script:

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import com.sap.it.api.mapping.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;

def Message processData(Message message) {

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

//String timeStamp = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
Calendar cal=Calendar.getInstance();//it return same time as new Date()
def hour = cal.get(Calendar.HOUR_OF_DAY)   

message.setProperty("Hour",hour);

return message;
}

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

Note:

def hour = cal.get(Calendar.HOUR_OF_DAY)   #24 hour format

def hour = cal.get(Calendar.HOUR) # 12 hours format  



Wednesday 6 January 2021

Split the value at @ and lowercase in groovyscript in sap cpi

 

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.*;
import groovy.util.logging.*;
import org.codehaus.*;
import groovy.xml.*;

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

map = message.getProperties();
def email = "blake1566@BLAKEGUER.COM"
def (value1, value2) = email.tokenize( '@' )
def chemail =value2.toLowerCase();
def fullemail = value1 + "@" + chemail;
message.setProperty("Header",fullemail);
return message;
}