cancel
Showing results for 
Search instead for 
Did you mean: 

SF API Select Using Navigation Property

huseyindereli
Active Contributor
0 Kudos
18,214

Hi,

I'm using Cloud SDK for Javascript to fetch some data from SF OData API. It's working smoothly. ( Foundation platform, User Management API )

const getUserData = async function (userId) {
  const userApi = new UserApi();
  const resp = await userApi
    .requestBuilder()
    .getAll()
    .select(
      userApi.schema.USER_ID,
      userApi.schema.JOB_CODE,
      userApi.schema.DIVISION,
      userApi.schema.CUSTOM_01,
      userApi.schema.CUSTOM_02,
      userApi.schema.CUSTOM_03,
      userApi.schema.CUSTOM_04,
      userApi.schema.TOTAL_TEAM_SIZE,
      userApi.schema.DEFAULT_FULL_NAME,
      userApi.schema.LOCATION,
      userApi.schema.TITLE
    )
    .filter(userApi.schema.USER_ID.equals(userId))
    .execute({ destinationName: _dest });
  return resp;
};

But when I add a navigation property to select at the bottom of the TITLE like;

userApi.schema.HR

it's throwing an error (Cannot read properties of undefined (reading '_fieldName'))

When I add it like this;

userApi.schema.HR.select(userApi.schema.USER_ID)

It also throws an error ( Cannot read properties of undefined (reading 'select') )

I also couldn't find a specific schema for that Navigation Property (HR).

Any ideas how to get navigation properties ?

View Entire Topic

The service object contains all APIs, it is a sort of umbrella object. This object has all the apis. I generated the code and added a navigation property (HR). I have no SFSF to test a actual call so I just generated the URL:

const service = require('./plt-user-management-service/service')

const userApi = service.pltUserManagementService().userApi

userApi.requestBuilder().getAll().select(userApi.schema.NICKNAME, userApi.schema.HR)
.url({url: 'http://foo.com'})
.then(url => console.log(url))

which gives me in the console:

http://foo.com/successfactors/odata/v2/User?$select=hr/*,nickname&$expand=hr

which looks ok. Can you give it a try using the service and access the userApi not via the constructor directly. You can also remove the core package, since it is version 1 which is not needed when you have the more granular version 2 packages.BestFrank
huseyindereli
Active Contributor
0 Kudos

Thanks so much Frank! It worked. Though I didn't get why it wasn't working with the first approach. Or the difference between these two calls.

One thing to note, when I try getting specific fields of the navigation prop, it's woorking.

  const resp = await userApi
    .requestBuilder()
    .getAll()
    .select(
      userApi.schema.USER_ID,
      userApi.schema.TITLE,
      userApi.schema.HR.select(userApi.schema.USER_ID)
    )
But when I try to select all as you proposed above, it throws an error related with the * at the beginning of constructed url.
  const resp = await userApi
    .requestBuilder()
    .getAll()
    .select(
      userApi.schema.USER_ID,
      userApi.schema.TITLE,
      userApi.schema.HR
    )

Unable to understand API request with character sequence: hr/*,userId,jobCode,division,custom01,custom02,custom03,custom04,totalTeamSize,defaultFullName,location,title

Cheers.

The difference is that when you access it via the service (intenden way) some getters are invoked which initialize some fields. The problem is that JS does not have any proper protection so even if we mark the constructor as private you could still use it.

Why the `*` is not working is not clear to me. I think it is proper OData notation, however sometimes the backend systems do not implement all OData features correctly. I hope the selection of the explicit fields is acceptable for your usecase?

huseyindereli
Active Contributor
0 Kudos

I've just seen your comment. Yes that is enough in my case. I had already found a workaround but I was curious about the cloud SDK call and your answer showed me the way of accessing the service via the service 🙂 . I did replace this with my workaround.

Thanks again for your help and your comment on the difference.