Skip to Content

Hi,

Recently, I had a requirement where I was supposed to send a request to the web-service in “x-www-form-urlencoded” format using POST Method via REST Adapter. I had come across various scn links on how to handle such scenarios such as  (https://archive.sap.com/discussions/thread/3823412  and https://answers.sap.com/questions/335020/rest-receiver-adapter-how-to-do-post-using-x-www-f.html ) but I couldn’t find the blog with complete configuration of REST Adapter. I hope this blog will help PI consultants, if they have similar kind of requirement.

Detailed Requirement:

Request Method: POST

URL : http://<host>:<port>/abc/abc.aspx?transid=174178189819&Action=GetDenominationCategory&BrowsePlanCategory=1&OperatorAlias=AIRC&RegionAlias=WB

Content-type  : application/x-www-form-urlencoded

Request  Body:

transid=174178189819

BrowsePlanCategory=1 will change as per requirement.

OperatorAlias=AIRC will change as per requirement.

RegionAlias=WB will change as per requirement.

Note:  URL Parameter values are dynamic. These values are coming from source payload.

Response Structure:

Content-type= application/json

{“BrowsePlanCategory”:null,”Operator”:null,”Region”:null,”DenominationCategory”:”[{“CategoryId”:1,”CategoryName”:”A Plan”},{“CategoryId”:2,”CategoryName”:”B Plan”}]”,”Plans”:null}

This is how I have implemented it in PI:

ESR Objects:

Data Types:

 Define a data type that includes the required parameters for your REST call.

Define another data type that includes all the required parameters from the REST.

Request Mapping with UDF:

All the parameters are mapped one to one but in our requirement, URL is dynamic. so we need to write a UDF to pass these values dynamically and we can access using ASMA. We also need to write a Java mapping/XSLT mapping to send the request in a single string as our Request type is “x-www-form-urlencoded” which basically means raw data.

Note: If the URL is static then we don’t need message mapping we can directly send the request in String format using java mapping only.

UDF to dynamically set REST URL parameters:

public String DynamicHeader(String var1, String var2, String var3, String var4, String var5, Container container) throws StreamTransformationException{
DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION); 
DynamicConfigurationKey key1 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName1");
conf.put(key1, var1); 
DynamicConfigurationKey key2 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName2");
conf.put(key2, var2); 
DynamicConfigurationKey key3 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName3");
conf.put(key3, var3); 
DynamicConfigurationKey key4 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName4");
conf.put(key4, var4); 
DynamicConfigurationKey key5 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName5");
conf.put(key5, var5); 
return "";
}

Java Mapping code to send the request in String Format:

package com.pi.browseplan;
import org.json.*; // import jar file attached in the blog 
import com.sap.aii.mapping.api.*;
import java.io.*;
import java.util.Map;
public class ParseXMLStructure extends AbstractTransformation {
	public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException {
 
		  try {
		            InputStream inputstream = in.getInputPayload().getInputStream();		  		String sourcexml = ""; String targetxml =""; String line="";
		            BufferedReader br = new BufferedReader( new InputStreamReader(inputstream));

		            while ((line = br.readLine()) != null) 
sourcexml +=line+"\n"; 
br.close();
// convert the xml Structure to JSON
		            JSONObject xmlJSONObj = XML.toJSONObject(sourcexml);
		            String jsonstring = xmlJSONObj.toString(0);
//formatting to convert string in required structure
//Required structure:transid=d&Action=d&BrowsePlanCategory=d&OperatorAlias=dd&RegionAlias=d	
	            
		            jsonstring =jsonstring.replaceAll("\\{", "").replaceAll("\\}","");
		            jsonstring=jsonstring.replace("\"", "");
		            jsonstring=jsonstring.replace(":", "=");
		            jsonstring=jsonstring.replace(",","&");
//If you are getting the response in correct format .you may need to do some changes here as per your //structure. 
			for(int i=0;i<jsonstring.length();i++)
		          	{
		          		char value=jsonstring.charAt(i);
		          		if(value == '&')
		          		{
		  			jsonstring = jsonstring.substring(i+1,jsonstring.length());
		          			break;
		          		}
		          	}

		            targetxml=jsonstring.trim();
		            out.getOutputPayload().getOutputStream().write(targetxml.getBytes());
		        } 
catch (Exception exception) {
		            getTrace().addDebugMessage(exception.getMessage());
		            throw new StreamTransformationException(exception.toString());
		        }
 }
	
}

Response Mapping

One -to- one mapping for response.

Operation Mapping:

Output after applying message mapping and Java Mapping in Operation Mapping:

Generally, we don’t need UDF to pass parameters dynamically in case of REST Adapter. As REST Adapter already have this feature to set parameters through XPATH Expression.

But in our case the response from Operation Mapping is not xml so in this case XPATH Expression will not work. That’s why we need to use UDF to set parameters dynamically in REST Adapter and access those parameters using ASMA.

ID Objects:

REST Receiver configuration:

Create a REST receiver channel with your target URL and request parameters as required by your call. Channel sets the Values of request parameters from UDF.

Note: In case of static URL, you don’t need to set Pattern variable Replacement. You just need to enter URL Pattern.

Likewise set the values of all request parameters.

Set the Operation mode to POST.

Set Request Format as JSON as of now, we will set it via Adapter Module. Set the Response Format as per your requirement.

Use Message Transformation Bean to convert the Request format to “x-www-url-encoded”.

Snapshots:

Dynamic  configuration :

Please find attached updated jar file for json to xml conversion. As the standard json jar file doesn’t create xml structure in sequence. Import this jar while writing Java Mapping.

https://drive.google.com/open?id=1qCVAuBYAlLNMFQUsCagqEGaUMcbtrReC

I hope this blog is helpful for you.

 

To report this post you need to login first.

13 Comments

You must be Logged on to comment or reply to a post.

  1. Jose Nunes

    Hello Sonam,

    Great blog, thanks for sharing.

    One question: why use ASMA & UDF to set URL Variables instead of using JSON Expressions?

    Regards,
    JN

    (0) 
    1. Sonam Ramsinghani Post author

      HI Jose,

      Here the Request Format is in raw string(x-www-form-urlencoded) not in JSON /XML Structure, so the JSON EXPRESSION/XPATH EXPRESSION will not work in this case. So we will have to use ASMA.

      (1) 
  2. Rashmi Joshi

    Awesome Blog, I wish this blog was available when I was struggling with  x-www-form-urlencoded…. Almost same requirement… M sure this will be good guide for others….

     

    BR,

    Rashmi

    (0) 
  3. Akshay Ruia

    Hi Sonam,

    Its an excellent.

    I manage to post request using your blog but not able to capture response which is also in a URL encoded format.

    can you please help me with this.

    Regards,

    Akshay Ruia

     

     

    (0) 
    1. Sonam Ramsinghani Post author

      Hi Akash,

      I think for response you will need java mapping to convert the Response string into a XML Structure. you can refer the same java mapping but with some modifications, like you will have to first convert your Response string to JSON Structure and then you can convert JSON Structure to XML.

      Thanks,

      Sonam Ramsinghani

      (0) 
    1. Sonam Ramsinghani Post author

      Hi Raffael, I tried using HTTP Tab initially but it didn’t work for me. Later i did many changes and used MTB then i didn’t try HTTP Tab. you can try it and let us know the result.:)

      (0) 
  4. Karan Chowdhury

    Hi Experts,

    We are also facing the same dilemma.

    We have to send messages from postman to rest sender channel in x-www-form-urlencoded format.

    Is there is specific setting we have to mention in the sender channel to receive the data correctly in PI.Right now we are facing the below issue.

     

    Error while sending message to module processor: Sender Channel ‘TMS_MG_WebIMPORT_REST_In’ (ID: 7f4796ac575d37df98148b7ea46bb12d): Catching exception calling messaging system: Mapping failed in runtimeRuntime Exception when executing application mapping program com/sap/xi/tf/_Webimport_request_MM_; Details: com.sap.aii.utilxi.misc.api.BaseRuntimeException; Content is not allowed in prolog.: Runtime Exception when executing application mapping program com/sap/xi/tf/_Webimport_request_MM_; Details: com.sap.aii.utilxi.misc.api.BaseRuntimeException; Content is not allowed in prolog.: Content is not allowed in prolog.: Content is not allowed in prolog.: Content is not allowed in prolog.

     

    BR

    Karan

    (0) 

Leave a Reply