PI REST Adapter . Exposing a function module as RESTful service
This blog is part of a collection of blog entries that shows architectural concepts and configuration of the SAP PI REST Adapter. We also added some sample scenarios to make it easier for you to understand how your scenario can be implemented using the PI REST Adapter.
If you haven’t done so far, best is to start with the very first blog PI Rest Adapter – Don’t be afraid within the blog series covering the concepts of the REST adapter. A complete list of all blog entries can be accessed from here PI REST Adapter – Blog Overview.
The current blog describes how to call a function module via PI’s RFC adapter, and expose the same as a RESTful service.
Scenario
We would like to read customer data from an ERP backend system calling a remote function module, and expose this interface as RESTful service. The customer ID is passed to the service as part of the URL of the RESTful service call. In order to map the customer ID to the corresponding input field of the function module, we need to retrieve the ID from the URL, and store the same as adapter specific attribute.
In the SAP Process Integration Designer perspective of the NetWeaver Developer Studio (NWDS), I have defined an Integration Flow with a REST sender channel and an RFC receiver adapter. In the operation mapping, the value of the adapter specific attribute is read, and mapped to the function module structure.
Configuring the REST sender channel
On the Integration Flow, double click on the sender channel, and switch to tab General below the Adapter-Specific settings. In our specific case, the settings for the input message format, i.e., the format of the request message are superfluous since we do not provide any payload anyway. As mentioned above, the required customer ID is part of the URL. Choose Quality of Service Best Effort. The format of the output message, i.e., the response, should be JSON. Within PI, the format of the response from the remote function call is XML, so we need to select the Convert XML Payload to JSON check box.
We would like to define a custom end point. On the Channel Selection tab we specify the static part of the end point URL whereas on the REST Resources tab we define the dynamic part that will hold the customer ID. Switch to tab Channel Selection, and select the Specify Endpoint check box. As endpoint, we enter /demo/query/customer. Furthermore, we can limit the endpoint to specific http operations. We would like to allow the service being called via the GET http operation only, so we select the Limit to HTTP Operation check box, and the GET http operation from the drop down box.
Switch to tab REST Resources, and define the URL pattern as /{id_part}. The pattern element id_part is a placeholder for the customer ID. As mentioned above, we need to store the customer ID within a dynamic attribute. In the XI Dynamic Attribute section, we map the pattern element id_part to the dynamic attribute id.
Mapping the customer ID
In the ESR, I have created a user defined function getASMA to read the value of the dynamic attribute:
@LibraryMethod(title=“getASMA”, description=“get adapter specific message attribute”, category=“UDFPool”, type=ExecutionType.SINGLE_VALUE)
public String getASMA (
@Argument(title=“”) String namespace,
@Argument(title=“”) String attribute,
Container container) throws StreamTransformationException{
Map<String, Object> all = container.getInputHeader().getAll();
DynamicConfiguration dynConf = (DynamicConfiguration)all.get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key = DynamicConfigurationKey.create( namespace, attribute);
String value = dynConf.get(key);
return value;
}
As input parameter of the function I pass the key of the attribute, in our case name id with namespace http://sap.com/xi/XI/System/REST. The value of the attribute is mapped to the input field CUSTOMERNO of the function module.
Running the scenario
For testing the scenario you can use the Advanced REST Client Application in the Google Chrome browser. The endpoint URL of your RESTful service starts with http://<host>:<port>/RESTAdapter with host and port of the SAP PI system, followed by what you have defined in the sender channel, here /demo/query/customer/<id>.
Example: Assuming we would like to gather information of customer with ID 26, so the URL would be as follows:
http://<host>:<port>/RESTAdapter/demo/query/customer/26
As a response we would get the customer details in JSON format as can be seen in figure below.
I hope this blog was helpful to understand how to expose a function module as RESTful service using the SAP PI REST adapter. If you like to learn more, check out the other blogs in the series, accessible from the main blog PI REST Adapter – Blog Overview.
Hi Ivo
Many thanks for the blog - very useful and informative. I was wondering if you could clarify something for me. I am slightly confused about exactly what values should be used in the table on the "Operation Determination" tab for a Sender Channel, specifically the "variable" column. So far as I understand, it is by using this table that I need to map my REST operation (e.g. GET) to my PI Operation via Operation and namespace. But this table does not have any input help in the UI and I am confused as to which values should go in there? The help doc says:
So does this mean for example that I have to map "GET" to "MyOperation in urn:MyNamespace"? but if so I am not clear on what the possible values for the "Variable" column should be to achieve this?
And do we always need a value in this table? I am using a single operation type and single PI Operation but I still get the message: "No matching rule to map interface found".
Many thanks!
Chris
08 Jan 2015, Edit to Add:
Hi Ivo - apologies, I just found your other blog which answers my above question here - thanks
Hi Chris,
thanks for your feedback. I will take your question as a hint that the standard documentation is a bit "weak" on the topic "Operation Determination" and will add some more examples.
Have a great New Year 2015!
ivo
Hi Chris,
Regarding "No matching rule to map interface found" error, please check you ESR objects are correctly set up, I had to update a Message Type on Operation Mapping.
Regards,
Adal.
Hi Ivo,
When we test the scenario to processing messages the adapter reports the error message:
Error while sending message to module processor: senderChannel '589b39c9b91c3ae99040d9addc6a818b': Catching exception calling messaging system: Unable to parse XML message payload to extract operation for receiver determinationorg.xml.sax.SAXParseException: Premature end of file.
Anyone an idea or solution direction?
Thanks in advance.
Cheers, Luc
Hi Luc,
your problem seems similar to the one mentioned above by Christopher.
Either you use a Dummy Interface in the IFlow for the adapter or you have to specify on the Operation Determination Tab which XI Operation / Interface should be used. The table on the tab allows to specify different interface name depending on the internal variables. In the variable columns add for example the REST operation, by entering "operation", in the expression column "GET" or "POST" or "*" and in the operation/namespace columns the XI operation / interface you want to reference.
I know this is a tricky part in the configuration of the adapter and the should UI support it in a more easy way...
Hope this helped,
ivo
There was a type in my answer: The variable "operation" has to be in curly brackets, so that it gets evaluated.
Ivo... Wonderful blog and very informative.
I am getting the same error after followed all your steps. Even adding operations too.
I am using simple Material Details search. REST to ABAP Proxy. My scenario is working fine with SOAP.
Error while sending message to module processor: senderChannel Catching exception calling messaging system: Unable to parse XML message payload to extract operation for receiver determinationorg.xml.sax.SAXParseException: Premature end of file.
Please help!
Please suggest any documents on REST adapter in PO environment.
Thanks
YRv...
Ooops. In my answer to Luc was a typo...
The variable "operation" has to be in curly brackets, so that it gets evaluated. So the entry should look like "{operation}" ( or like "{service}" if you want to map the XI operation by REST service name)
Hi Ivo,
What is the value of the constant, I marked with a green & yellow star in the picture below? Could you share customer_query data type structure in your sample? No tailstring function in our system. What should I use instead of tailstring function?
Thanks
Hi Esra,
we haven't mentioned those details here since they are not relevant for understanding the REST specific features, the rest of the mapping is rather scenario specific.
Anyway, I need to ensure that the customer no is a 10 digit number with leading zeros, so I add 10 times 0 to the value, and with tailString I keep only the last 10 digits, so the green constant is "0000000000", the red constant is "10". There might be better ways to achieve this but that'S all taht came to my mind. The tailString function actually comes with the deployment of the b2b add-on, I just nicked it.
Here we go:
@LibraryMethod(title="tailString", description="remove leading characters", category="UDFPool", type=ExecutionType.SINGLE_VALUE)
public String tailString (
@Argument(title="") String value,
@Argument(title="") String tailLength,
throws StreamTransformationException{
null;
if (value != null && tailLength != null
int tailLengthInt;
try {
catch (NumberFormatException numberFormatExp) {
throw new RuntimeException(
"UDF tailString: could not convert tailLength"
" to integer");
"";
int valueLength = value.length();
for (int i = valueLength; i > 0; i--) {
if (value.charAt(i - 1) != ' ') {
break;
int length = trimmedValue.length();
if (length > tailLengthInt) {
else {
else {
return output;
}
The customer_query data type just has a field id of type string
that's it
Alex
Hi Alex,
I am getting an error as you see below. Do you have any suggestion?
Error while sending message to module processor: senderChannel 'bb592eb66d7f309daf583d93f6e4a370': Catching exception calling messaging system: XIServer:CX_RD_PLSRV::Problem while determining receivers using interface mapping: Error while determining root tag of XML: BOM / charset detection failed::::Error when determining the receiver: Problem while determining receivers using interface mapping: Error while determining root tag of XML: BOM / charset detection failed Problem while determining receivers using interface mapping: Error while determining root tag of XML: BOM / charset detection failed Error while determining root tag of XML: BOM / charset detection failed Error while parsing an XML stream: 'BOM / charset detection failed'.
Thanks
Hello Ivo / Alexander,
We had a requirement for Exposing the Function module as RESTful service. In that I am using Synchronous Sender Rest Adapter where I want to give 2 Runtime parameters(TOKEN, INPUTREQUEST) in the URL and the RFC should give the response back.
The sample Request URL will be like:
http://Host:Port/RESTAdapter/Demo/PO?TOKEN=12345&INPUTREQUEST=<?xml version="1.0" encoding="UTF-8" ?>
<Z_Request>
<REGION>ASIA</REGION>
<SOURCE_SYSTEM>PRO</SOURCE_SYSTEM>
<item>
<KOKRS>1000</KOKRS>
<BUKRS>100</BUKRS>
</item>
</Z_Request>
The communication channel configuration:
When we place the URL in Rest Client tool, SAP PI takes the 2 parameters through GET variable but the value of INPUTREQUEST is getting truncated as "<?xml version". We cant able to send the complete xml as input to "INPUTREQUEST".
Kindly suggest some ideas/solutions for this issue.
However the call is successful without ‘=’ symbol in the XML Header, please find the URL for the reference.
URL:
http://Host:Port/RESTAdapter/Demo/PO?TOKEN=12345&XMLREQUEST=<?xml version="1.0" encoding="UTF-8" ?>
<Z_Request>
<REGION>ASIA</REGION>
<SOURCE_SYSTEM>PRO</SOURCE_SYSTEM>
</Z_Request>
Please suggest the potential solution to achive the above business case since we also tried the adapter module to manage the call but somehow the Rest sender adapter is not supporting the same.
Many Thanks
Ezhil.
Hi,
How can I achieve this functionality without using NWDS. I mean mapping sender with dynamic attributes.
please advise.
Regards,
Venu
Hi Gurus,
maybe I'm too naive to the REST Topic. 😛
I do not always know how to define the Sender and Receiver Intefaces.
Who can explain me and give me more Details, such as a step-by-step guide?
thanks a lot!
Regards
Sara
Hi Ivo,
I have a scenario which Integrates
SAP ECC and SAP UI5 via SAP PI 7.4 server in a bidirectional data flow by means of RFC BAPI-XML conversion synchronously using RFC and REST adapter within internet.
Open PO's are send from SAP ECC to UI5 and gets the acknowledgment back i.e response from UI5 to SAP ECC via SAP PO server.
Please help on this. Many thanks
https://answers.sap.com/questions/51166/how-to-integrate-sap-po-server-with-ui5.html?childToView=52401#comment-52401