In this blog, I would like to share some experiences about an integration scenario between SAP HANA Cloud Platform Integration Services and SuccessFactors to give you an idea what kind of issues you can bump into developing a scenario like this, but also possibilities how to solve that.

Business case:

Our customer has the policy that all HR processes need to be migrated to the cloud with SuccessFactors as main platform. Based on this requirement the current system will be phased out and replaced by SuccessFactors Recruitment, using the standard API OData functions from SuccessFactors.

The process that needs to be created contains 3 steps for candidates to apply on the jobposting website (third-party system):

The third-party system will send candidacy data collected on the application form to the SuccessFactors system where the candidate will become part of the recruitment process. When this data is sent by the third-party system, SAP HCP-IS will check in SuccessFactors if the candidate exists or not. Based on the reply from SuccessFactors, SAP HCP-IS either creates a candidate profile (if the candidate does not exist) or/and creates a JobApplication. Furthermore, there is a validation between the application form candidacy data and already existing candidacy data in the SuccessFactors system. This check can’t be performed by the third-party system and therefore SAP HCP-IS is used.

Main integration flow:

As described, we need to check if the candidate already exists, this has to be done based on the email address of the applicant (step 1):

Step 1: Check Primary emailAddress:

In this process, an OData call is used to check if the email address the applicant uses exists or not. The request-reply function sends a reply with or without a candidateId. If this step/call will fail (due to invalid user credentials for example) we catch the error in the Exception SubProcess and write this to the Datastore to store the message and use the message for reprocessing.

The Exception SubProcess will catch a potential error during the first step. The Content Modifier will make sure the message that has failed, is put back in the body of the message using the property set by the first Content Modifier operation in the main process. The Write operation (Data Store Operations in “Write” mode) will persist the body of the message to the HCI Data Store and the file name (as it is dynamic we don’t want to lose it) as Entry ID. A very useful blog on how to create this and use the Datastore is from Martin Jaspers and Frank Bakermans:

OData channel:

In the OData channel, we query on emailAddress (GET operation).

Based on the reply we get from SuccessFactors, we either create a candidate profile (if the candidate does not exist) or we create the JobApplication directly and add the candidate in the Recruitment step.

Step 2: Create candidate profile

If a candidate does not exist, a candidate profile will be created via OData (POST) in SuccessFactors.

During the steps for JobApplication and CandidateProfile, we use the Exception SubProcess function to catch the possible errors with 2 different Process Calls. A good blog that you can use (that I also used for this part) is from Paul Todd how to handle errors:

According to Paul Todd’s blog; the first process is created to determine what kind of status we get from the message. In the first step, I have used the following script:


import java.util.HashMap;

def Message processData(Message message) {

     def map = message.getProperties();

   def ex = map.get(“CamelExceptionCaught”);

         if (ex!=null) {

def body = message.getBody();



message.setHeader(“STATUS_CODE”, ex.getStatusCode());

message.setHeader(“STATUS_TEXT”, ex.getStatusText());

      return message;

This script extracts the “CamelExceptionCaught” element from the message and then extracts the status code and status text from the exception message (although ‘status text’ will not give you more text then for example: ‘Internal Server Error’).

In the Content Modifier, I have used the following expression: ${header.STATUS_CODE} ,to form a new message body showing only the STATUS_CODE from the exception message.

In the second Process Call (Send Error Messages below) the message is routed depending on the STATUS_CODE. This is needed because some status codes indicate that a functional error has occurred and in that case the message should not be reprocessed. If the STATUS_CODE is 500 (because of characters that are not allowed, target structure do not match with target’s system response message etc) a reprocess of the message will also go wrong when it will be picked up from the Datastore. The Datastore will get contaminated, so the messages with STATUS_CODE 500 will be written to an error directory on a specific server. The other possible errors (like 401: Unauthorized) will be written to the Datastore to store the message and use the message for later processing.

Step 3: Create JobApplication:

I’ve experienced that during this step I needed to use the HTTP adapter. When I’ve used OData modelling here I could not select all (mandatory) fields needed for the JobApplication, even if I use sub-level 1 during the model operation.

When I tried the OData adapter as recommended (by SAP), the monitor in HCI says that the message is successfully sent to SuccessFactors but also gives below error: Request Payload: Either the OData metadata content available in the server is outdated or the request payload seems to be incorrect = with error => only whitespace content allowed before start tag and not { (position: START_DOCUMENT seen {… @1:1)

When I checked the output of the JSON-string after the XML to JSON Converter, I saw that the string indeed started with an { (example: {“zip”:”3***MT” etc), but I could not filter this because otherwise the JSON-string was not valid for SuccessFactors, so I needed another option.

The SuccessFactors adapter was also an option and it did not give any errors in the monitoring, but it also did not create anything in SuccessFactors so the only option left was to use the HTTP adapter for this part of the process.

Summarized; the check and two create calls should all three work with the OData adapter. However, the call to create a JobApplication did not work. If you did manage to work with the SuccessFactors adapter (or OData), please feel free to share your experiences with me J.

If you have any further questions, don’t hesitate to contact me.  [private information removed by Moderator]

Jelle de Bruijn

To report this post you need to login first.


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

  1. Moya Watson

    Thanks for taking the time to share this really great post, Jelle! I love how you took us step-by-step with the process, yet also contextualized the whole purpose of the integration.  I look forward to more posts from you!

    As for this —
    >If you did manage to work with the SuccessFactors adapter (or OData), please feel free to share your experiences with me J

    Did you try a search on Might also be worth a post to see if the community has some insights.

    thanks again!

    1. Jelle De Bruijn Post author

      Hi Moya,

      Thank you! I have searched on, but could not find anything suitable yet. In the Web UI is a standard content package that looks similar where the SuccessFactors adapter is used, but I have to try if that works for me :). Thanks again for your reply!




Leave a Reply