Skip to Content

When I came across this thread  (lookup soap inside udf) on the XI forum, initially I thought that it would not be possible to call a Webservice from an user Defined Function. But then I started digging deep and voila I realized that SOAP Lookup’s are actually possible and I was wrong! Various blogs on SDN have already discussed options like DB LookUp and RFC Lookup, but there was not much on SOAP Lookup’s and maybe one reason why I made that initial mistake of thinking that SOAP Lookup’s were not possible.


Sample Business Case:

We need to get the latest Currency Conversion Rate for converting one Currency to another in your mapping. One solution is to do this by making a call to a Webservice that can provide the conversion rate.   We can perform Currency Conversion using Value Mapping and many other options, but for the current scenario, let us assume that we need to make a call to a web service from XI and get the corresponding conversion value back. Here we are looking at avoiding a BPM and invoking the web service from Message Mapping using the receiver SOAP adapter.

    

Solution:      This is possible using  SOAP Lookup. In my solution, I am using the freely available  Currency Converter Webservice    (http://www.webservicex.net/CurrencyConvertor.asmx). The Webservice takes the From Currency and To Currency as its input. In our case let us consider that we are getting these inputs from our Source and then need to get the Conversion rate from the Webservice.     

UDF:

1.The UDF takes 2 inputs, the From Currency (USD – US Dollar ) and To Currency (INR – Indian Rupee) and returns the Corresponding Conversion rate.

2. Construct the Source / the SOAP request XML inside the UDF by passing the Import parameters as input to the UDF.

3. Use the LookUp API to trigger the SOAP call and get the SOAP response.

4. Parse the SOAP response to get the Conversion Rate.

5. Create a SOAP Communication Channel in the Integration Directory with the correct SOAP URL and SOAP action and proxy settings if any.


Source Code:



import javax.xml.transform.stream.StreamResult;
import com.sap.aii.mapping.lookup.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import javax.xml.transform.*;
AbstractTrace trace = container.getTrace();
String conversionRate = "";
try {
  /*Pass the Business System and Communication Channel as  input to the getChannel().
  BS_SOAPLOOKUP – Business System*CC_Webservice_SOAP_CURRENCY_CONVERTOR – Receiver SOAP Adapter */
  Channel channel = LookupService.getChannel("BS_SOAPLOOKUP","CC_Webservice_SOAP_CURRENCY_CONVERTOR");
  SystemAccessor accessor = LookupService.getSystemAccessor(channel);
  /* Construct the SOAP Request Message using the InputParameters
  FromCurrency , ToCurrency are the Input Parameters.*/     
  String SOAPxml ="";
  InputStream inputStream = new ByteArrayInputStream(SOAPxml.getBytes());
  XmlPayload payload = LookupService.getXmlPayload(inputStream);
  Payload SOAPOutPayload = null;
  /*The SOAP call is made here and the response obtained is in the SOAPOutPayload.*/
  SOAPOutPayload = accessor.call(payload);
  /* Parse the SOAPPayload to get the SOAP Response back.
  The conversion rate is available under the Field Name ConversionRateResult */
  InputStream inp = SOAPOutPayload.getContent();
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  /* Create DOM structure from input XML */
  DocumentBuilder builder = factory.newDocumentBuilder();
  Document document = builder.parse(inp);
  /* ConversionRate is available in the TAG ConversionRateResult in the Response XML */
  NodeList list = document.getElementsByTagName("ConversionRateResult");
  Node node = list.item(0);
  if (node != null) {
  node = node.getFirstChild();
  if (node != null) {
  conversionRate = node.getNodeValue();
  }
  }
}
catch (Exception e){
    trace.addWarning("Error" + e);
}
return conversionRate;

SOAP Adapter Configuration


   image

image   

To report this post you need to login first.

23 Comments

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

      1. Sravya Talanki
        Bhavesh,

        Good one.At the same time anything that can be possible in java should be possible in UDF as well and no doubts on it.Only consideration in writing complex UDF is version control and question of Sustenance and performance.

        It is definetly a new way but also check if the webservice of conversion rates is upto date and valid one if you are refering to a real time scenario.

        Generally in SAP we have a conversion rates routine i.e a standard one that will be called using RFCLookup.

        (0) 
        1. Bhavesh Kantilal Post author
          Sravya,
          Coming from you that has to be a compliment. Thanks.

          The Currency Conversion example in this blog was just a starting point to show how the functionality can be used.In real time, ofcourse it should be ensured that the values returned from the Webservice are always correct.

          Regards,
          Bhavesh

          (0) 
          1. Manoj Kumar
            Hi Bhavesh ,

            I have a scenario in which I need to connect a SAP4.7 system to a .net application version 2003.
            Earlier it was done by BC(Business Connector)but If I want to use XI instead and try to make a web service call can you please let me know which adapter can i use  on both sides and in order to connect SAP4.7 to XI do I need to implement XI addon on SAP4.7 server.

            Thanks in advance

            (0) 
            1. Yash Agarwal
              Hi Bhavesh,

              This is precisely what i want in my scenario. I want to call a web service to do a lookup in my message mapping and based on that my mapping will proceed. I used your technique but when i try to test it, it doesnt give me any error but at the same time it doesnt return me anything.

              I have made sure of the proxy part and the message format the web service expecting. Infact the web service is something which my team has developed. When i do debugging on the code of the web service, i found out that the web service is getting called but the message passed to it is empty.

              Where am i making the mistake?

              Regards,
              Yash

              (0) 
          2. Sudharshan Aravamudan
            Bhavesh,

            Nice blog.

            Did you try SOAP Look up with Payload size in order of MBs. Any Comments on the performance (Timeouts, Threads,etc) of SOAP Look up compared to standard SOAP Scenario especially for reasonable payload sizes.

            Regards,
            Sudharshan N A

            (0) 
            1. Bhavesh Kantilal Post author
              Sudharshan,
              A few MB’s of data should not be a issue.
              We use this Option of SOAP lookup extensively in one of our roll outs and the size of payload was not the concern, rather the processing applications ability to provide split second response was the major concern.

              What we found was that one of our back end applications took more time to process these Lookup calls and changing this application was not feasible and hence we ended with TimeOut Errors.

              Ofcourse we went ahead and changed the timeout parameter of the SOAP adapter , but what we hit was the fact that as this Lookup takes time, the rest of our messages in the same Queue ended up getting Queued up -random Queues used by XI.

              We went ahead and implemented low Priority Interface Specific Queue for this Message and thereafter things looked better as rest of messages went through without getting queued up.

              If your target application can provide the necessary thorough put Lookup’s should not be a major concern.

              Regards
              Bhavesh

              (0) 
  1. Suraj S.R.
    Hey bhavesh really a useful and cool blog…

    Just check the link for [b]XI Mapping Lookup API[/b]… It is reffering APIs…. ๐Ÿ™‚

    Suraj

    (0) 
    1. Bhavesh Kantilal Post author
      1. Check if there is a proxy server between your Xi server and the webserivce. If yes, give the details in the SOAP adapter.

      2. Make sure that the SOAP URl and SOAP action are valid in the SOAP adapter.

      3. Make sure that the request to the Webservice is in the format expected by the Webservice.

      Regards
      Bhavesh

      (0) 
  2. Bhargav Srinadh Gundabolu
    Hi Bhavesh,

         First of all Thanks for your Blogs they are simply amazing. I tried this Blog just as you explained. But when i am testing it in Test Tab in message mapping it is showing an error “com.sap.aii.mapping.lookup.LookupException: Exception during processing the payload.Problem when calling an adapter by using communication channel SOAP_RECV (Party: , Service: AA_BS_RECV, Object ID: 4fb8e1fbeb0e3213a3381de6f63d9542) XI AF API call failed. Module exception: ‘com.sap.aii.af.ra.ms.api.RecoverableException: Connection timed out:could be due to invalid address: java.net.SocketException: Connection timed out:could be due to invalid address’. Cause Exception: ‘Connection timed out:could be due to invalid address’.”

    When i test it end to end teh Look up is not returning any Value

    Can you please let me know what could be the Error.

    The Target URL and the detaisl given in SOAP Receiver are all the same.

    Thanks,
    Bhargav

    (0) 
  3. Bhavesh Kantilal Post author

    Note to users on PI 7.3 and Beyond

    • On PI 7.3 and beyond having a receiver agreement on your receiver SOAP Adapter is a mandatory requirement.
    • In case you use the SOAP Adapter only for Lookups create a Dummy Receiver Agreement.

    Regards,

    Bhavesh

    (0) 
  4. Artem Solohin

    /* code from this post */

    import javax.xml.transform.stream.StreamResult; import com.sap.aii.mapping.lookup.*;

    import javax.xml.transform.dom.DOMSource; import javax.xml.parsers.*; import org.xml.sax.*;

    import org.w3c.dom.*; import javax.xml.transform.*; 

    AbstractTrace trace = container.getTrace();

    String conversionRate = “”;

    try { 

    /*Pass the Business System and Communication Channel as  input to the getChannel().     

    /*BS_SOAPLOOKUP – Business System*CC_Webservice_SOAP_CURRENCY_CONVERTOR – Receiver SOAP Adapter

    */   

    Channel channel =  LookupService.getChannel(“BS_SOAPLOOKUP”,”CC_Webservice_SOAP_CURRENCY_CONVERTOR”);   

    SystemAccessor accessor = LookupService.getSystemAccessor(channel);  

    /* Construct the SOAP Request Message using the InputParameters     

      FromCurrency , ToCurrency are the Input Parameters.*/    

    String SOAPxml =           “”;   

    InputStream inputStream = new ByteArrayInputStream(SOAPxml.getBytes()); 

    XmlPayload payload = LookupService.getXmlPayload(inputStream);   

      Payload SOAPOutPayload = null;   

    /*The SOAP call is made here and the response obtained is in the SOAPOutPayload.*/    

    SOAPOutPayload = accessor.call(payload);    

    /* Parse the SOAPPayload to get the SOAP Response back.    

       The conversion rate is available under the Field Name ConversionRateResult */   

      InputStream inp = SOAPOutPayload.getContent();    

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();    

    /* Create DOM structure from input XML */    

    DocumentBuilder builder = factory.newDocumentBuilder();    

    Document document = builder.parse(inp);   

      /* ConversionRate is available in the TAG ConversionRateResult in the Response XML */ 

        NodeList list = document.getElementsByTagName(“ConversionRateResult”);

         Node node = list.item(0);     

               if (node != null) { 

         node = node.getFirstChild();          

               if (node != null) {    

               conversionRate = node.getNodeValue();          

                           }    

    } } catch (Exception e) {   

      trace.addWarning(“Error” + e);  } return conversionRate;

    (0) 
  5. Vicky G

    All I am using the following code to invoke soap receiver adapter from UDF:

    SystemAccessor accessor = null;

    DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
    DynamicConfigurationKey varFileName = DynamicConfigurationKey.create(“http://sap.com/Custom“,”FileName“);
    DynamicConfigurationKey varShipmentNumber = DynamicConfigurationKey.create(“http://sap.com/Custom“,”ShipmentNumber“);
    DynamicConfigurationKey varCustomerCode = DynamicConfigurationKey.create(“http://sap.com/Custom“,”CustomerCode“);
    DynamicConfigurationKey varItemNumber = DynamicConfigurationKey.create(“http://sap.com/Custom“,”ItemNumber“);
    DynamicConfigurationKey varField03 = DynamicConfigurationKey.create(“http://sap.com/Custom“,”Field03“);

    String FileName = conf.get(varFileName);
    String ShipmentNumber = conf.get(varShipmentNumber);
    String CustomerCode = conf.get(varCustomerCode);
    String ItemNumber = conf.get(varItemNumber);
    String Field03 = conf.get(varField03);

    try

    {
    String sysName = (String) System.getProperty(“SAPSYSTEMNAME”);
    if (“DHX”.equals(sysName))
    {
    Channel channel = LookupService.getChannel(“”,”FUSION_DEVBTSERVER_USA”,”Receive_SOAP_TrackingServiceWS_LogToCentralMonitoring_ISIS”);
    accessor = LookupService.getSystemAccessor(channel);
    }   

    String  SOAPxml =”<?xml version=\”1.0\” encoding=\”utf-8\” ?><ns2:LogToCentralMonitoring xmlns:ns2=\”http://EI.CentralMonitoring\”><ns2:loggingData><MON_EISLDCTLID>WM211.03</MON_EISLDCTLID><MON_ProgramID>WM211.03</MON_ProgramID><MON_ProcessID>IP_FEXX_IsisToFusion_Value</MON_ProcessID><MON_MsgStartTimeStamp>”+timeSent+”</MON_MsgStartTimeStamp><MON_MsgEndTimeStamp>”+timeSent+”</MON_MsgEndTimeStamp><MON_MsgStatus>”+msgStatus+”</MON_MsgStatus><MON_MsgStatusDescription>”+constantError+”: “+msgDesc+”</MON_MsgStatusDescription><MessageAttribute><Name>MON_FileName</Name><Value>”+FileName+”</Value></MessageAttribute><MessageAttribute><Name>MON_FunctionalID</Name><Value>”+ItemNumber+”</Value></MessageAttribute><MessageAttribute><Name>MON_ShipNum</Name><Value>”+ShipmentNumber+”</Value></MessageAttribute><MessageAttribute><Name>MON_SearchField1</Name><Value>”+Field03+”</Value></MessageAttribute><MessageAttribute><Name>MON_SearchField2</Name><Value>”+CustomerCode+”</Value></MessageAttribute></ns2:loggingData></ns2:LogToCentralMonitoring>”;

    InputStream is = new ByteArrayInputStream(SOAPxml.getBytes());     

    XmlPayload payload = LookupService.getXmlPayload(is);            

    Payload result = accessor.call(payload);

    }
    finally
    {                                              
    if(accessor!=null)accessor.close();               
    }

    return (msgDesc);

    But intermittently I am getting the following error:  SOAP: call failed: java.net.SocketException: Connection reset

    But surprisingly other interface using the same channel normally without udf never throws error. The error seems to be happening only for the messages being sent to this CC using UDF.

    Any advice.

    (0) 
  6. Ankit Mishra

    Hi Bhavesh,

    May i know what changes might be required when we have multiple operations in a web service? How the mapping will take place? I’m using a synchronous web service.

    (0) 
  7. Adriana Barbera

    Hi,

    What could be the problem?

    Error:

    • error: com.sap.aii.mapping.lookup.LookupException: Exception during processing the payload. Error when calling an adapter by using the communication channel CC_SOAP_C3_LOGIN_RECEIVER (Party: , Service: BS_C3, Object ID: 02c7feabad1939639e835f0919b649a6) XI AF API call failed. Module exception: ‘com.sap.engine.interfaces.messaging.api.exception.MessagingException: java.io.IOException: Failed to get the input stream from socket: iaik.security.ssl.SSLCertificateException: Peer certificate rejected by ChainVerifier’. Cause Exception: ‘java.io.IOException: Failed to get the input stream from socket: iaik.security.ssl.SSLCertificateException: Peer certificate rejected by ChainVerifier’.
      com.sap.aii.mapping.lookup.LookupException: Error when calling an adapter by using the communication channel CC_SOAP_C3_LOGIN_RECEIVER (Party: , Service: BS_C3, Object ID: 02c7feabad1939639e835f0919b649a6) XI AF API call failed. Module exception: ‘com.sap.engine.interfaces.messaging.api.exception.MessagingException: java.io.IOException: Failed to get the input stream from socket: iaik.security.ssl.SSLCertificateException: Peer certificate rejected by ChainVerifier’. Cause Exception: ‘java.io.IOException: Failed to get the input stream from socket: iaik.security.ssl.SSLCertificateException: Peer certificate rejected by ChainVerifier’.
      at com.sap.aii.ibrun.server.lookup.AdapterProxyLocal.process(AdapterProxyLocal.java:92)
    (0) 
  8. Aamir Khan

    Hi All,

    The requirement in my project is that some value has been sent from ECC side to PI in a particular field now PI would read that value and the same is sent to some third party URL ย with the help of UDF (It means UDF read the data of that field and sent to the required URL), Please help me to solve this issue, It is very urgent and i am not to able to solve the same.

    Thanks

    Aamir

    (0) 

Leave a Reply