Skip to Content

Introduction

Integration with cloud services, e.g. SuccessFactors and Salesforce, can present some challenges.  The basic challenge is the retrieval of the session-id, and then uses it in our request.  This requires a 2-step process:  login to the cloud service to retrieve the session-id, and then use the session-id to send the request.  Customarily, we will have to create a business process using either BPM or ccBPM to accomplish the 2 steps.
In this blog, we will use another alternative which does not require the use of BPM or ccBPM.  This is to use a user-defined function in Message Mapping.

Limitation

The limitation of this method is that service request to be sent must be accomplished with one call.  If multiple calls are required, then BPM or ccBPM will have to be used.  An example of when multiple requests are needed is when we query an object in SuccessFactors, the query will return only a subset of the resultset.  A queryMore request will have to be used and looped to retrieve the remainder of the resultset.

Concept

When a web service request is sent to the cloud application, the session-id will have to be used.  This session-id is obtained with a “login” request, using userid and password and companyid (if SuccessFactors).
This login request can be done either using a traditional synchronous integration interface, or using a “lookup” in Message Mapping.  Since “lookup” in Message Mapping is only available for JDBC and RFC, we have to develop our own for web service (SOAP).
By using the “lookup” we can avoid creating a separate integration and BPM/ccBPM.
For this blog, we will use SuccessFactors as an example.

User-Defined function

Below is the UDF I used:  (I created a Function Library to contain the UDF, so that it can be used in multiple Message Mappings.)
SFSF_Integration1.png
Please note:

  1. The request string is obtained from the WSDL which can be obtained from the cloud application.  In this example, from SuccessFactors.  The response string, to be parsed, can also be obtained from the WSDL.  To ease the process, I used soapUI to perform the login request, which allows me to examine the contents of both the request and response easily.
  2. Include 2 additional imports in the UDF:
    • Javax.xml.parsers.*
    • Org.w3c.dom.*
  3. A Channel Parameter, SFLogin, is used to make the web service call.  The communication channel will have to be configured in the Integration Directory.  Hard-coding the communication channel in the UDF can also be used, to avoid using the parameter.
The java code is below:
public String GetSessionid(String companyid, String username, String password, Channel SFLogin, Container container) throws StreamTransformationException{
String request = “<?xml version=\”1.0\” encoding=\”UTF-8\”?>”
    +”<ns1:login xmlns:ns1=\”urn:sfobject.sfapi.successfactors.com\”>”
    +”<ns1:credential><ns1:companyId>”+companyid+”</ns1:companyId><ns1:username>” 
    +username+”</ns1:username><ns1:password>”+password+”</ns1:password>”
    +”</ns1:credential></ns1:login>”;
InputStream isRequest = new ByteArrayInputStream(request.getBytes());
SystemAccessor accessor = null;
String sessionid = “”;
Try {
/*
     1. Determine a channel.
                        channel information can be hard-coded here
         Channel SFLogin = LookupService.getChannel(“BusComp”, “CommChan”);
*/
    // 2. Get a system accessor for the channel.
    accessor = LookupService.getSystemAccessor(SFLogin);

    // 3. Create a payload according to the data type which the adapter exspects.
    //       Use service.getBinaryPayload() for binary payload,
    //    and service.getTextPayload() for text payloads.
    Payload payload = LookupService.getXmlPayload(isRequest);

    // 4. Execute lookup.
    Payload result = accessor.call(payload);

    //Parse response
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    InputStream resStream = result.getContent();
    Document document = builder.parse(resStream);
    NodeList respNodes = document.getElementsByTagName(“result”);
    Node node = respNodes.item(0);
    Element element = (Element) node;
    sessionid = element.getElementsByTagName(“sessionId”).item(0).getChildNodes().item(0).getNodeValue();

}
catch (Exception e) {
        return e.getMessage();
} finally {
    try {
        if (accessor != null) accessor.close();
    } 
    catch (Exception e) {
        return e.getMessage();
    }
}

return sessionid;

}

Testing

The “display queue” in Message Mapping is used to perform the test:
SFSF_Integration2.png
As you can see, the session-id is return during mapping, and can be used in mapping to send our request to SuccessFactors.
To report this post you need to login first.

14 Comments

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

  1. Ruben Velasco

    Hi William,

    First of all, thanks for the info.

    Why we should avoid the use of parameters?

    In my point of view you can improve your call creating a Dynamic call to the channel without using hard-coding.

    1) Creating first a parameter in the Operation Mapping called “soapChannel”, the type of the parameter has to be Adapter.

    2) Replacing in your UDF you harcoded call for the code showed below:

    InputParameters parameters = container.getInputParameters();

    Channel channel = (Channel)parameters.getChannel(“soapChannel”);

    SystemAccessor accessor = LookupService.getSystemAccessor(channel);

    3) Configuring the value of the parameter in the Interface Determination.

    Kind Regards,

    Rubén.

    (0) 
    1. William Li Post author

      Hi Rubén,

      Yes, using parameters does provide flexibility.  The example code I provided does use parameter.  As you will notice, that 1st section of the code has been commented out.  By declaring an argument as a “Channel”, it automatically uses parameter without any additional coding.

      This method also allows older releases, which does not have the parameter functionality, to use this code.  I was just trying to show the coding invovled.

      Regrads,

      William

      (0) 
  2. Hans-Jürgen Schwippert

    Thanks for sharing your idea.

    We implemented the “session id problem” with an Adapter Module in the SOAP adapter using standard web service proxies to login/logout (optionally routed via PI for monitoring reasons). The session id is then stored/retrieved with Entity Beans.

    Using this approach, the session information can be reused until the maximum session timeout and the web service calls are minimized. In my opinion the logic is better placed in an adapter (specialized connect to the cloud application) than in the message mapping.

    Regards

    Hans

    (0) 
    1. William Li Post author

      Hi Han,

      Yes, I totally agree with you.  Thanks for suggesting this idea of using the user-module.

      By using the UDF, although not ideal, but it is quick-n-dirty and allows for easy testing.

      Regards,

      William

      (0) 
    2. Pavan kumar

      Hi Han

      We implemented the “session id problem” with an Adapter Module in the SOAP adapter using standard web service proxies to login/logout (optionally routed via PI for monitoring reasons). The session id is then stored/retrieved with Entity Beans.


      As per your comments looks like you made the session id as one time activity instead of hitting SF for each transaction.Did you write any custom adapter module or else do we have any standard module provided by SAP.If so can you please share the details how you implemented this.

      (0) 
      1. Hans-Jürgen Schwippert

        Hi Pavan

        Yes, we wrote a custom adapter module to be called before the standard SOAP Adapter calls SF with the application data call.

        This adapter module calls another session bean (this one is be EJB 3) to handle the SF session.

        If no active session is found in the database (Entity Bean), an SF logon is called via a web service proxy (in NWDS web service proxies can be generated from ESR Service Interfaces). This proxy can be configured via NWA to point the correct SF instance. We handled this configuration via our custom adapter module configuration which is forwarded to the web service Proxy. This allows configuration of the logon procedure via Integration Directory adapter module configuration.

        The received session id is stored including timeout Information and is then reused by following requests.

        Within the adapter module the returned session id (either a new one or one from database) is inserted into the SOAP Header.

        We also wrote a little WDJ app to manage the sessions manually.

        This implementation is stable in productive use.

        If you need further details I can send you our adapter module documentation and/or source code.

        (0) 
        1. Pavan kumar

          Hi Han,

          Thanks for the reply and the approach which you handled for session Id sounds really good.We have similar kind of requirement to handle session id.Can you please share the details your adapter module to pavankumar1017@gmail.com also we are planning to achieve the same using VALUE MAPPING REPLICATION

          (0) 
  3. Vicky G

    William,

    My organization does not integrate with success factors. Is there an any web service out there on cloud that I could use to perform a POC for my client and show them that PI has the capability of integrating with apllications on the cloud.

    Regards,

    Vicky

    (0) 

Leave a Reply