Creating an custom object definition and maintain some data

Employee Central offers a powerful feature to create custom generic objects also called Metadata Framework (MDF) Objects. This feature is available via “Admin Tools–>Configure Object Definitions” if the logged in user has the corresponding permissions. The following screenshots shows such a custom generic object called cust_LMS_Trial. Each record of this object has a autogenerated code (externalCode), an associations to a user in employee central (externalName) and four fields of type string (cust_Field1,…cust_Field4). All other fields are system generated fields:

Capture.JPG

This object definition can be created using a simple UI without any coding required. And after saving the object definition above also a UI to enter data is available via “Admin Tools–>Manage data”:

SCNBlogManageData.JPG

Hint: In some cases it might be required to refresh the OData API metadata after creating the object before a first successful API call. This refresh can be found in “Admin Tools–>OData API Metadata Refresh and Export” (after enabling this feature in permissions in group “Manage Integration Tools”).

Retrieve data from the created generic object using OData

After saving this object definition OData API for reading and writing the data are available instantly. Note that this is only the case if

  • you select “API Visibility” accordingly while creating the custom generic object and
  • if the user used to call the API has proper permissions set  (“Permissions–>Manage Integration Tools–>Admin access to OData API” and “Metadata Framework–>Read/Write Permission on Metadata Framework”. See also OData API Programmers Guide at http://help.sap.com/hr_api )

After creating an object definition as described above a rest client such as “Advanced Rest Client” in google chrome can be used to call APIs for the created object cust_LMS_Trial in employee central.

The easiest API call would be the retrieval of all records of the created object cust_LMS_Trial. A request for this would look like this in our salesdemo environment (note that the URL might differ in your environment, please refer to the OData API Programmers Guide for the right URL in your case):

Request-URL and Operation:

GET https://salesdemo4.successfactors.com/odata/v2/cust_LMS_Trial?$format=JSON

Request-Header:

Authorization: Basic dXNlckBjb21wYW55OnBhc3N3b3Jk

Remark: The cryptic authorization string above is the base64 encoding of the username, the instance or company you use to login and the corresponding password of the user in this company. To get the string above any base64 encoding tool can be used to encode the string user@company:password (for example notepad++ and the mime-tools available in this editor). The same request including parts of the repsonse in the advanced rest client:

SCNBlogAdvancedRestClient.JPG

The parameter $format is used to influence the output format and returns the data in JSON format (default value is ATOM/XML).

Create new data for the generic object using OData (POST)

In order to create new data via OData APIs, a POST operation is used (see also http://www.odata.org/documentation/odata-version-2-0/operations). To create data for our object cust_LMS_Trial we have to switch our operation to POST and add a content type parameter into the OData request header. This content type defines the format of the payload, in our case JSON, and the used character set (here utf-8):

Request URL and operation:

POST https://salesdemo4.successfactors.com/odata/v2/cust_LMS_Trial?$format=JSON

Request Header:

Authorization: Basic dXNlckBjb21wYW55OnBhc3N3b3Jk

Content-Type: application/json;charset=utf-8

Payload:

{

“cust_Field1”: “15”,

“cust_Field4”: “40”,

“cust_Field3”: “30”,

“cust_Field2”: “20”,

“externalName”: “greinhard”

}

Response:

Status “201 Create” and  created data in response

The same create request in google chrome:

SCNBlogAdvancedRestClientCreate.JPG

Update existing data for the generic object using OData (PUT)

In order to update existing data the PUT operation has to be used and the corresponding record has to be identified in the URL. A OData request to update a record for cust_LMS_Trial with key 162 would look like this. Pleas not that only the operation and the url changes compared to creating data:

Request URL and operation:

PUT https://salesdemo4.successfactors.com/odata/v2/cust_LMS_Trial(162L)?$format=JSON

Request Header:

Authorization: Basic dXNlckBjb21wYW55OnBhc3N3b3Jk

Content-Type: application/json;charset=utf-8

Payload:

{

“cust_Field1”: “151”,

“cust_Field4”: “401”,

“cust_Field3”: “301”,

“cust_Field2”: “201”,

“externalName”: “greinhard”

}


Response:

Status “200 OK” and no data in response

Same request in google chrome:

SCNBlogAdvancedRestClientUpdate.JPG

Important remarks about updating links with OData

Using field “externalName” in the example above as a simple field is just a shortcut to allow easy creation of data. Usually associations have to be created using a dedicated navigation property. This shortcut version of creating data does not work anymore if the field is marked as required and the corresponding permission checks are enabled for those fields in the object definitions:

SCNSecuritySettings.JPG

From that point of view it is a not a good idea to use the shortcut if you plan to switch later to permission enabled mode and make this field “externalName” required.

In such a case it is better to use a payload as follows:

{

“cust_Field1”: “11”,

“cust_Field4”: “41”,

“cust_Field3”: “31”,

“cust_Field2”: “21”,

“externalNameNav”: {

   “__metadata”: {

      “uri”: “https://salesdemo4.successfactors.com:443/odata/v2/User(‘greinhard‘)”,

      “type”: “SFOData.User”

      }

   }

}

To report this post you need to login first.

22 Comments

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

  1. Sahiba Gandhi

    Beautiful Blog !

    Had a question- when we try to retrieve data from custom generic/metadata object using Odata API it provides details of all the records of that generic objects.

    Is it possible to just get the username of logged in user/or the one you pass during base64 encoding through Odata API calls.

    Thanks,
    Sahiba Gandhi

    (0) 
    1. Gerald Reinhard Post author

      Hi,

      I’m not 100% sure if I got your question right because if you are able to build the base64 string from username@company:password why would you want the API to return the username to you again? I would be really interested in your use case. May I ask you to explain what you want to achieve.

      A view possible answers to your question:

      Of cause an API call like this

      https://salesdemo4.successfactors.com/odata/v2/User?$filter=username+eq+'admin'&$select=username&$format=JSON

      would return the username only but you would have to know the username when building the query (or any other ID of the user)

      To figure out the username used for an API call, an easy trick would be to create or change some data as mentioned above and read it it afterwards and using the createdBy or lastModifiedBy fields to get the userID (not the username). To get from the userID the username the following OData call can be used:

      https://salesdemo4.successfactors.com/odata/v2/User?$filter=userId+eq+'admin'&$select=username&$format=JSON

      Please note that userId and username can be the same (in this case admin) but must not be the same. Fields like createdBy and lastModifiedBy contain the userId and not the username.

      Best regards

        Gerald

      (0) 
  2. Sahiba Gandhi

    Hi Gerald,

    Thanks for your response.

    What I want to achieve is – I would like to read the logged in user through an Odata API call in a custom portlet/tile.

    Thanks,
    Sahiba

    (0) 
    1. Gerald Reinhard Post author

      Hi Sahiba,

      if you are embedding an UI into employee central the EC system can be configures to send a SAML assertion to your application. Hence the application server will get the user ID via this SAML assertion. The user ID in this SAML assertion can be used to get further data from EC via OData APIs (see 2nd example above) and will also be used by your application to authenticate without having to login again. If you application is running on Hana Cloud Platform (HCP) you will get also further benefits like theming etc..

      Best regards

         Gerald

      (0) 
  3. Faisal Nawaz

    Nice blog Gerald,

    Is it possible to link the custom object to external API for CRUD operations? actual data for the custom object will not reside in Success factor. Custom object will call the API that will push/pull the information in some other system.

    Thanks,

    Faisal

    (0) 
    1. Gerald Reinhard Post author

      Hi Faisal,

      not sure what exactly is your use case but technically you can use a middleware to retrieve data from a third party system and put it into the custom object.

      There is no way to call a 3rd party API directly from Success Factors in order to store data into the custom object you will require a part inbetween, for example HCI or HCP.

      Best regards

         Gerald

      (0) 
    1. Gerald Reinhard Post author

      Hi Satish,

      thanks! And yes you can read data from multiple users, you would just use a corresponding filter, e.g. odata/v2/<customObject>?$filter=externalCode+eq+’user1’+and+’externalCode+eq+’user2′ (assuming that the user is stored in the externalCode of the customObject)

      If a single filter is not possible you could also batch several calls in a $BATCH call, see help.sap.com/hr_api for more details about OData.

      Best regards

         Gerald

      (0) 
  4. Mathias Maerker

    I have a question here. After some testing it does seem, the creating MDF Objects via OData API does not trigger any onSave Rules(e.g. starting a conditional Workflow) can anybody elaborate on that?

    Regards

    Mathias

    (0) 
      1. Mathias Maerker

        Well I had a lot of Rules which where not triggered, e.g. you change a field value via rule before save. Are there any plans to support workflows? especially for extensions it is often crucial (after all we are in HR 😉 )

        (0) 
  5. Mathias Maerker

    I have a question here. When trying to update the entitie JobRequisition via PUT it says, templateId required, but templateId is not updatetable, neither does an upsert work.

    Payload is only

    {

        “internalStatus”: “0”

    }

    Can somebody elaborate on that “feature” and tell me how to update Jobrequisitions? I check the documentation and in their examples they don’t pass templateId.

    Second question: How can I use MERGE? i tried it with X-HTTP-Method and X-HTTP-Method-Overwrite but same result as above..

    Regards

    Mathias

    (0) 
      1. Mathias Maerker

        No I figuered that the requisition was delted and as soon as the field delted is set you can’t change the entity anymore. But many thanks for your time and effort!

        (0) 
  6. tarika manchanda

    Hi, I have been facing this error:

    org.apache.olingo.odata2.api.uri.UriNotMatchingException: Could not find property with name: ‘cust_payperstartdate’.

    This is while upserting compensation data to one of the OData. The payload to this OData looks like this:

    <?xml version=”1.0″ encoding=”utf-8″?>
    <Root>
    <Record>
    <RecordNo>1</RecordNo>
    <EEID>17</EEID>
    <COVERAGE_CATEGORY>N</COVERAGE_CATEGORY>
    <CoverageCategory>2</CoverageCategory>
    <Paygroup>UM</Paygroup>
    <nextPayrollStartDate>2016-12-02T00:00:00.000</nextPayrollStartDate>
    <Emp_Status>A</Emp_Status>
    <Pay_component>7699</Pay_component>
    <PayCompValue>600.0</PayCompValue>
    </Record>
    </Root>

    And the <nextPayrollStartDate> is fetched from custom MDF Object filtered on other dates. So my query looks like this.

    Operation: Query(GET)
    ResourcePath : cust_payroll_calender?$select=cust_payperstartdate,cust_payperenddate,cust_paygroup,cust_nextpayperstartdate&$filter= cust_payperstartdate le datetime’${property.SFCurrentdate}’ and cust_payperenddate ge datetime’${property.SFCurrentdate}’
    Path to edmx : edmx/api4_successfactors_com_odata_v2.edmx
    Can u please help check and advise.

    (2) 
  7. Shruthi Anantha

    When I am trying to access the EC Odata Api from SAP ByD I am getting a Unauthorized error.I am passing the Username in the format “Basic username@companyId:password(base 64 format)”,But I am facing a 401 Unauthorized error.

    Kindly let me know what value should be passed for the  Username and Password to access the api’s?

    (0) 
  8. Nurhan Ozcan

    Hello,

    How can i send custom generic objects to SAP ERP? We have success factors add-on in SAP ERP. Is there any standart configuration in SAP ( SOAP, or idoc) to get data for custom MDF Objetcs?

     

    Regards,

    Nurhan

    (0) 

Leave a Reply