As a Software Engineer I needed to create an interface between an SAP System and a third party API using XML as request and response but calling the API through REST adapter. After reading some blogs about creating a Lookup service within a UDF and how to use the REST adapter I have developed this implementation.
Requirement
I need to call an API which a dynamic token given by the same service must be included in the header parameters.
Request and Response must be XML format.
Using the API itself
Getting the Token
Request:
Method: POST
Endpoint: https://<hostname>
Resource: /api/v1.3/auth/token
Parameters: ?user_name=<user_name>&password=<password>&auth_type=password
Body: None
Response:
{
"authToken": "<authToken>",
"issuedAt": <issuedAt>,
"endPoint": "<endPoint>"
}
Using the Token in a second request
In these example I’m retreiving my account information
Method: GET
Endpoint: https://<hostname>
Resource: /api/v1.3/user/info
Parameters: None
Body: None
Headers:
Authorization: <authToken> //retrieved in previous request
Response:
{
"accountName": "<accountName>",
"userName": "<userName>",
"userEmail": "<userEmail>"
}
Implementation in SAP PI
ESR Objects
I used the UDF within the request Message Mapping. Since there is no body, I just needed the Token as an input:
The response Message Mapping is all one to one element
Code for the UDF
The inputs are the communication component and communication channel names. I’m using global variables in the UDF since I’m using it in many interfaces but you can set these values by parameters from the configuration side.
//Imports:
javax.xml.parsers.*;
org.w3c.dom.*;
public String getToken(String commComp, String commChann, Container container) throws StreamTransformationException{
Channel channel= LookupService.getChannel(commComp,commChann);
SystemAccessor accessor = LookupService. getSystemAccessor(channel);
StringBuffer sb = new StringBuffer();
String token = "";
try{
InputStream inputStream;
String reqString ="."; //This is to avoid XMLPayload is empty Exception
inputStream = (InputStream) new ByteArrayInputStream(reqString.getBytes());
Payload payload = LookupService.getXmlPayload(inputStream);
Payload RESTOutPayload = accessor.call(payload);
InputStream inpStr = RESTOutPayload.getContent();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inpStr);
NodeList list = document.getElementsByTagName("authToken");
Node node = list.item(0);
if(node !=null) {
node = node.getFirstChild();
if (node !=null) {
token = node.getNodeValue();
}
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
if (accessor!=null) accessor.close();
}
return token;
}
ID Objects
Receiver Channel used in the UDF
You can also send the user and password from de Message Mapping but I rather to set this data in the configuration side:
Request and Response format must be JSON since it’s the format used by the API. I’m converting the response to XML so I can get the value by tag name in the UDF:
For this scenario I’m using XML as request and response but you can use JSON either on request or response.
Sender Channel
Since this is a synchronous scenario I just need to set the QoS to Best Effort
Receiver Channel
I get the dynamic token value from the target of the request Message Mapping
Request and Response must be JSON format since it’s the format used by the API. I’m converting from and to XML in both request and response since that’s my scenario. You can use same JSON either on request or response depending on your scenario.
I need to wrap the response to the MT used in the response Message Mapping.
The Token value is included in Headers tab
That’s it, now the dynamic token is included in the header of the request and I’m able to retrieve the information in a single request from PI:
I hope this blog is helpful for you.
Feel free to share any feedback or thoughts.
Reference Blog posts:
REST Look Up using UDF in SAP PO | SAP Blogs
OAuth 2.0 authentication within a UDF mapping to be included in REST receiver channel | SAP Blogs