Analyzing EC OData API Performance

Objective

After completing this lesson, you will be able to identify what kind of API tools are available in SAP SuccessFactors Employee Central.

Introduction

The following contents covers an overview of the EC OData API Basics.

Recorded Webinar: EC OData API Features

Test Client

We will introduce 3 test clients for EC OData API. The first one is Soap UI, it can be used for both SOAP and REST, and it allows complex test script creation including load tests. The second is the JMeter, it also can be used for both SOAP and REST/OData. The last one is Firefox Rest client and can be used for any Rest based API including OData.

SOAP UI

  • Get it here:API Testing Tool | SoapUI
  • Can be used for both SOAP and Rest/OData
  • Allows complex test script creation including load tests

JMeter

Firefox addon Rest Client

Basic Authentification

As we known, there will be the identity authentication when we call OData API, we can call it Basic Authentication. Generally speaking, we send authentication with the https header by parameter Authorization. Base 64 encode string username@companyId:passwordcombine with word Basic and a space in front of it. (In fact all of the test clients will provide us the parameter of Authorization, we just need to set theusername@companyId and the password, then the Base 64 encode string will be created automatically according to your input in the Authorization.)

  1. Send authentification with the http header by parameter Authorization
  2. base64 encode string user@company:password(e.g. admin@ACE123:secret).
  3. Combined with word Basic and a space in front of it
  4. Base64 encoder available in notepad++
SAP query example for PerPersonal resource filtering by external person ID, showing GET request with Basic Authorization header.

OAuth with SAML assertions

See OData Documentation

Operations and Resources

HTTP GET,PUT, POST, DELETE

OData API supports on some http operations like GET, POST, PUT, PATCH and DELETE, we use the basic operations to get or edit the entities like User, PerPerson, picklist and so on in EC

HTTP Operations

  • GET: Query
  • POST: Create
  • PUT: Update
  • PATCH: Partial Update
  • DELETE: Delete

HTTP Resources or Services

  • User, PerPerson, Picklist, Position

HTTP Parameter

  • Separated by "?" (first one after Resource) and "&" characters
  • OData standard parameters are starting with an "$" character, like $filter or $select

XML Definition of API metadata

  • Can be retrieved via OData API $metadata call an result can be imported after download into Excel:

In order to get extra information, such as language labels, picklists, beyond what the standard OData metadata provides, SAP Successfactors OData exposes metadata as an entity. The SAP SuccessFactors OData API exposes an entity named 'Entity'. Its properties are exposed as complex type value embedded in the response body of 'Entity'. Different forms of metadata can thus be exposed without changing the standard OData metadata format. You can access the new metadata just like you would access a regular entity. In addition, it supports a simple filter to output metadata of a specific entity.

The metadata can be achieved via OData API by $metadata in the https call. You can request for the metadata via Firefox Rest Client. Because the data is a little large for the metadata, the request may takes more time.

SAP oData request for metadata with GET method displaying Basic Authorization header in the request headers section.

API Metadata – Upload in Excel

OData API Features

OData API Features - $format

Select the play button to learn about the $format parameter.

OData API Features - $filter and $select

Filter options and parameters

The below example shows an OData API query example using filter and select. For the filter we can give a specified value to a field to query on the corresponding entity. For the select we can also define the fields to return the response.

  • $filter=personIdExternal%20eq%20’greinhard’
    • %20 is special escape character for space; like %28 and %29 is for brackets like "(" and ")"

    • Available operators are EQ,NE,GT,GE,LT,GT and those can be combined with NOT, AND and OR

  • $select=firstName defines fields to be returned separated by spaces

SAP oData GET request querying PerPersonal resource.

OData API Features - $expand

The below example shows how to use the parameter of expand. Expand always used to navigate to other entity.

SAP oData GET request querying PerPersonal resource for first name and date of birth, filtered by external person ID.

Expanding the data – navigating the data model

  • $expand=personNav
  • $select=firstName,personNav
    • expands firstName in root resource and all fields in navigated resource person

  • $select=firstName,personNav/dateOfBirth

    • expands firstName in root resource and all fields in navigated resource person

JSON response showing PerPersonal resource details: first name Gerald and date of birth as a JSON date object.

OData API Features - $expand and $filter

SAP oData GET request querying PerPersonal resource.

The above example shows us how to use the parameter of $expand and $filter

The response identifies a set of User Entities whose personNav/emailNav property is emailAddress which is equal to gerald.reinhard@sap.com, After the entities are retrieved, the response removes unselected columns. Then the $expand option expands the selected columns that is a navigation property

Deep Filtering using $filter and $expand

  • $expand performed after filter independent from each other (see result next slide)
  • $select not required for filtered attributes
SAP oData GET request querying PerPersonal resource.

Filter+Expand

  • Filter applied to root resource
  • Expand applied to filtered root resource
  • Result: Expanded Email not matching the filter
JSON response showing PerPersonal resource.

OData API Features – Handling dates

SAP oData GET request querying EmpJob resource.

The below content describes how to query effective-dated entities, to use fromDate and toDate will return all historic data of root entity in the response. But if the root entity is not effective date, the fromDate and toDate will be applied to the next effective dated entity in the navigation hierarchy, and all of the effective dated records falling into the time interval between fromDate and toDate will be returned.

Also If historic data of an effective dated record is returned and a navigation/expand from those records to another effective dated record is done the start date of the first effective dated entity will be used to filter the 2nd one.

toDate and fromDate

  • For effective dated entities to tell the API to return all historic data of the root entity in the response.
  • If the root entity is not effective dated toDate and fromDate will be applied to the next effectived dated entity in the navigation hierarchy:
    • https://salesdemo4.successfactors.com:443/odata/v2/PerPerson? $filter=employmentNav/jobInfoNav/userId%20eq%20'greinhard‘ &fromDate=1900-01-01 &$select=employmentNav/jobInfoNav/startDate,employmentNav/jobInfoNav/departmentNav/externalCode &$expand=employmentNav/jobInfoNav/departmentNav
  • All effective dated records falling into time interval between fromDate and toDate will be returned.

Combination of toDate and fromDate and navigation

  • If historic data of a effecitve dated record is returned and a navigation/expand from those records to another effective dated record is done the start date of the first effective dated entity will be used to filter the 2nd one.
    • https://salesdemo4.successfactors.com:443/odata/v2/EmpJob? $filter=userId%20eq%20'greinhard'&fromDate=1900-01-01 &$select=startDate,departmentNav/externalCode &$expand=departmentNav

This describes how to query effective-dated entities, to use fromDate and toDate will return all historic data of root entity in the response. But if the root entity is not effective date, the fromDate and toDate will be applied to the next effective dated entity in the navigation hierarchy, and all of the effective dated records falling into the time interval between fromDate and toDate will be returned.

Also If historic data of an effective dated record is returned and a navigation/expand from those records to another effective dated record is done the start date of the first effective dated entity will be used to filter the 2nd one

Use last modified queries to retrieve changed records for delta loads

  • Partial Deletions not supported for non effective dated entities such as by PerEmail, PerPhone
  • Full deletion not supported by any API yet
  • lastModifiedOn (server timezone) lastModifiedDateTime (UTC)
SAP oData query filtering FODepartment.

OData API Features – Pagination

  • The OData API provides several pagination options for query results.
  • A single OData HTTP GET request can return at most 1,000 records. This is reasonable because most HTTP clients have a timeout limit of 2 - 5 minutes.
  • A request running longer than the limit gets an HTTP timeout error. Therefore, it is often required to tune complex queries and lower the data size for them to complete within the timeout restriction.

The customer can choose between two types of Pagination:

  • Client Pagination
  • Server Pagination
  • Client Pagination is the most fundamental pagination mechanism. It uses query options on the client side to create an "offset" that restricts the amount of data returned from the server. A client uses the following URI parameter.
  • A client uses the following URI parameter:
    • The $top parameter indicates the number of records to return in the batch. The default and the maximum number is 1,000 records.
    • The $skip parameter indicates the number of records in the full data set to skip before fetching data.
  • For example, a query with $skip=2000&$top=500 returns the 5th page of data where the page size is 500.
SAP oData GET request for EmpEmployment resource.
  • Unlike client pagination, where the pagination is controlled by client specified parameters, server pagination is controlled on the server side.
  • There are two types of server pagination: cursor-based pagination and snapshot-based pagination. Both types of pagination return a "__next" parameter at the end of each query response that contains a $skiptoken value indicating the next page of data.
  • Cursor-based pagination maintains a database "cursor" on the server throughout pagination HTTP requests. The cursor represents a pointer to the start of the next page in the full data set. This is enabled using the &paging=cursor URI parameter.
  • Snapshot pagination works by persisting a list of all business keys of the data set on the server. This is enabled using the &paging=snapshot URI parameter.

When to use the different types of pagination:

  • For UI consumption, use client offset pagination. This is the only supported method on UI.
  • Cursor-based pagination and snapshot-based pagination are recommended for integration use cases.
  • We recommend that you tune your queries when you use snapshot-based pagination. If you have problems with first page performance for extremely large data sets, switch to cursor-based pagination if applicable.

And last but not least, we have optimized the OData entities FOLocation and FOPayGrade for snapshot-based pagination to improve performance.

Further features

Some additional basic features

  • $top and $skip for consumer based paging
  • IN operator in filters
  • "Entity"-Entity and $metadata on Entity
  • Workflow function imports
  • Metadata refresh as API

A filter can be applied so that in EC OData API queries you can exclude external (non-EC) user data.

To make this possible, the following Boolean fields can be selected and used with $filter;

  • isECRecord for EmpEmployment and includeAllRecords for EmpEmployment, PerPersonal, PerAddressDEFLT, PerPerson, PerEmail, PerPhone.
  • Previously, the default behavior was to exclude non-EC user data from EmpEmployment and PerPersonal but now you can override this behavior using these new fields in your query.

We’ve introduced the concept of a person UUID (unique universal identifier) for the entire SAP SuccessFactors HXM Suite; when a new hire or user is created, the system generates this identifier – called "perPersonUuid". perPersonUuid lets you expose the person UUID for integration and import scenarios for all employees (EC and non-EC employees).

The field is visible and upsertable in PerPerson but cannot be queried via this entity. To make perPersonUuid available in OData, we’ve created a new entity PersonKey. This entity cannot be directly queried but you can use $expand with personKeyNav in the User entity to expose the perPersonUuid. personKeyNav is exposed regardless of data model configuration, RBP or provisioning settings.

API Tuning and Best Practices

Best PracticeAdditional Notes
Use snapshot server pagination for integration use casesIf server pagination is not used, you can experience data loss or duplicates in your result set if simultaneous edits are occurring in the company instance. Snapshot often results in dramatic performance improvements as well.
Use "server pagination" to ensure a stable result setQuerying only records modified since your last execution instead of querying all records for integration use cases.
Don't try to simulate real-time by running jobs too oftenQuerying for periods much less than one hour will use too much API resources and may be throttled in the future. Running short 1/minute queries can result in a denial of service server situation, especially for complex queries that require a lot of back-end processing.
Reuse a login session instead of creating a session for each http transaction or each page of paginated data. 
Using an API for integration that is only designed for single userExample: Iterating across all users and creating a session for each user.

One example of this is the SFOData.Todo API which only allows querying data for a single user.

The correct solution is to use the new TodoEntryV2 "Todo Export" permission.

Always add error checking for edit operations

Check for each item in the response. Log full error responses to your client log.

Note: Do not rely on the API Center audit logs to check for errors.

Avoid too small a page size for paginated data

You should tune your batch sizes to be as large as possible.

Note: There is a maximum of page size of 1000. For more complex transactions, you may need to decrease this value to avoid http timeouts.

Avoid large OData $expand statements

One example of this is an attempt to query all JobRequistions and then expand all JobApplications and all attachments for each application.

Note: Such expands my be throttled in the future where a "Too Complex" or "Too large" error may be returned.

Avoid poor performance by keeping transactions simple.Poor performance is often a sign of misuse of an API.
Avoid excessive multi threading

This can cause server issues and unreliable behavior. Often threading will not improve performance as it may cause data table contention.

Note: Such threading may be limited by throttling in the future to protect servers.

Avoid deprecated APIsSFAPI (excluding CompoundEmployee) and SFAPI Adhoc have been deprecated. Please use OData with snapshot pagination.
Do not query properties and expanded entities you do not need or use

It is easy to build a query that does more $select and more $expand than you need.

Note: Integration Center avoids this, instead of a developer building a query manually based on the mapping of fields, IC generates the query based on the mapping.

Tune your client wait time to match the system wait time

Your client should be set to wait a reasonable amount of time before timing out. Long operations can run for as long as 7 minutes and our network and servers will continue to process a transaction for that long.

It is best to wait for the transaction to complete (rather than just wasting the transaction without waiting for it to complete.)

Note: You can also simplify your transaction to avoid timeouts in the first place.

Make use of API Tools like Data Model Navigator to tune queriesThe Data Model Navigator can easily reveal available relationships to other entities, potentially simplifying your use case, while Preview Mode of the Integration Center can confirm that your results include the proper data within your responses.
Choose the optimal OData base entityOData offers much flexibility from which to base a query but it is important to choose the best for your use case. For example, PerPerson is a better starting entity than PerPersonal. Using the latter increases lengths of all expand paths to email etc and results in poor performance.

Don't pull many records 1 at a time with predicate key or singleton $filter queries instead of by batch or using $filter IN clause

This often happens querying from a list of keys, which is a common "in memory join" technique.

filter with a key clause that checks for only a single entity instance. ie. &$filter=<key> eq <keyvalue>

2. Predicate key queries such as /odata/v2/User(userId='cgrant1')

Recommendation: use OData join techniques or use the IN filter operator: $filter=key in ('cgrant1',mhoff1',....)

Execute a Simple OData API Query Using Advanced REST Client

Process Overview

This simulation demonstrates the basic configuration steps required to manually set up the configuration for SAP SuccessFactors Employee Central. You will get the basic knowledge of OData API call & Tools. How to monitor the APIs for different partners.

Prerequisites

The following configuration and customization must have been completed before implementing Basic Settings in SAP SuccessFactors.

  • Access to OData SFAPI
  • Access to Audio Log
  • Access to API Tools

Result

As part of this demonstration, we will cover configuration section in EC, which is: EC OData API Basics - REST Client.