Yes Rest LookUp is possible in PI
Recently we had a requirement where we need to perform a look up for a rest service to obtain the token and then include the same in the future requests.
I did not find any document for REST look up in PI , so thought to create a new one so that it can help others.
For this document, I have used the below rest api
http://maps.googleapis.com/maps/api/geocode/json?address=10001
This service takes zip code as json input and returns status and result in json format.
So like other look up first thing we need to do is to create a new communication channel with type REST in ID
REST URL Tab:
Notice we have used a variable parameter {req_zipcode} in the URL.The value of this parameter will be fetched from the input xml message which we will be passing during the look up.
In the xpath expression we have used the value as //zipcode. So in the input xml there has to be a field with the name zipcode. Below is our input xml
Rest Operation tab:
Data Format tab:
Our input is xml but the service expects json so we have to choose the option ‘Convert XML Payload To JSON’.
Similarly the service will return the output as JSON. So we have to choose the option ‘Convert to XML’. Also we need to select the ‘Add Wrapper Element’.
The final output in xml format will look like below
Communication channel is ready now. Next we need to create source and target structure in ESR
source:
target:
Java Mapping Code:
package com.test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;
import com.sap.aii.mapping.lookup.Channel;
import com.sap.aii.mapping.lookup.LookupService;
import com.sap.aii.mapping.lookup.Payload;
import com.sap.aii.mapping.lookup.SystemAccessor;
public class RestLookInPI extends AbstractTransformation {
public void transform(TransformationInput arg0, TransformationOutput arg1)
throws StreamTransformationException {
this.execute(arg0.getInputPayload().getInputStream(), arg1
.getOutputPayload().getOutputStream());
}// end of transform
public void execute(InputStream in, OutputStream out)
throws StreamTransformationException {
try {
String status = "";
// generate the input xml for rest look up
String loginxml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<zipcode>10001</zipcode>";
//perform the rest look up
Channel channel = LookupService.getChannel("BC_468470_Receiver","CC_Rest_Rcv");
SystemAccessor accessor = null;
accessor = LookupService.getSystemAccessor(channel);
InputStream inputStream = new ByteArrayInputStream(loginxml.getBytes());
Payload payload = LookupService.getXmlPayload(inputStream);
Payload SOAPOutPayload = null;
SOAPOutPayload = accessor.call(payload);
InputStream inp = SOAPOutPayload.getContent();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inp);
NodeList stats = document.getElementsByTagName("status");
Node node = stats.item(0);
if (node != null)
{
node = node.getFirstChild();
if (node != null)
{
status = node.getNodeValue();
}
}
Document targetDoc = builder.newDocument();
Element targetRoot = (Element) targetDoc.createElement("ns0:MT_Output");
targetRoot.setAttribute("xmlns:ns0","http://xxxxxxx/pi/468470/RestLookUp");
Element stat = (Element) targetDoc.createElement("status");
stat.setTextContent(status);
targetRoot.appendChild(stat);
targetDoc.appendChild(targetRoot);
DOMSource domSource = new DOMSource(targetDoc);
StreamResult result = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
} catch (Exception e) {
e.printStackTrace();
}
} // end of execute
}
Test Result:
Hi Indrajit,
Thank you for sharing. I think we can also use the SystemAccessor for other lookups e.g CSV or SOAP 🙂
Regards,
Mark
Thank You Mark..
Hi Indrajit, Can I do rest lookup inside UDF similar to soap lookup? For some reason the lookup in Java mapping is not working for me.
Thanks,
Hi Amol!
Sure, you can do it the same way. Take a look at this blog:
https://blogs.sap.com/2013/08/07/how-to-soap-lookup/
Regards, Evgeniy.
Thanks Evgeniy - Yes, It worked.
Thanks,
Amol
Hi Kolmakov,
I use ASMA instead of xpath substitution,I set ASMA in UDF before call lookup channel,but when using it in channel,the channel didn't get the ASMA values,but it did showup in the payload of dynamic configuration,how come?
Thanks
Hi Yunze!
I'm not sure that SystemAccessor class used in such type of lookup pays any attention to attributes placed in the main message's DC header.
Regards, Evgeniy.
Great Indrajit!!
Thank you for sharing!, Rest communications are every day more usual, and this was one of the last lookup frontiers!.
Regards.
Thank you Iñaki..
Hi Indro,
Thanks for sharing knowledge and this is really worthy blog.
Regards,
Sami.
Thanks Sami..
Thank you Indrajit, for sharing this information. It was helpful.
Good one. Thanks for sharing this info..
Br,
Praveen Gujjeti
is it possible to read the header information in the rest lookup response?
i need to get the "etag" value while performing rest lookup.
This etag value is not coming the body. it is coming under response header.
Muni,
Were you able to read the tag from the header? Is this possible via dynamic config?
Br,
Manoj
Hi Manoj,
I was not able to read the header paraters in the rest look up.
So I created two interfaces, one is for lookup and another one is for main interface, instead of handling in one interface.
i called first interface(proxy to rest sync) and read the header details in response mapping using dynamic configuration and send it to ECC.
After lookup service is successful, main interface will be triggered with first interface header values.
I went with this approach as in house consultant who is going to support is not good at java coding.
another approach will be calling rest service from java code without using any adapter. this you can put it in udf, java map or adapter module.
https://archive.sap.com/discussions/thread/3872833
Regards,
Muni
My approach was to have lookup to get the X-csrf-token and use it in subsequent calls. but unfortunately, the session used in lookup and the subsequent calls are different hence that token becomes invalid.
Hi Former Member, they have a more complete scenario ?, I am trying to replicate with a restlookup but I can not get a correct result, my doubt is in the mapping of a synchronous scenario, thanks.
Martin,
Did you made it ?
I also copy the same here and it´s not working.
Former Member ?
Hi,
My lookup code is not triggering the REST communication channel at all . Any clues please !
I have used an UDF to do the REST look up and also configured REST Receiver channel with a dummy ICO.
Does anyone provide information on how to get CSRF token set it in HTTP header for Odata API?
so, i can copy and paste your code into de udf option in graphical mapping and modifying the CC or BS, and then it works?. or i have to do it eclipse and import as a jar file? please let me know how to do it