Thursday, 7 January 2021

Success Factors API Integration with SAP on Premise

I’ve decided to create this blog post for two main reasons. First is, like many other posts out there, I’ve struggled a lot to find a solution to a problem I was facing, and I could not find anything out there that helped me in any way, so I want to make sure that if anyone else has the same problem, there is something online that hopefully will help them. Second reason is, I am really not sure of what I am doing, and I am hoping that someone will read this post and will stop me from doing a crazy thing

I have an UI5 portal connected to an SAP Box (on Premise) and a Success Factors system. Users can navigate from UI5 portal to Success Factors using SSO, but they only get to the landing page. If an user has a TODO item in Success Factors, the only way for them to know is to log in to the UI5 portal, and then navigate to Success Factors (I’m going to say SFSF from now on). In the UI5 portal the users have an Inbox, where they can see if they have pending TODOs, but this inbox is only being fed from SAP right now.

What I am trying to achieve is a way to feed this inbox from SFSF as well, so that they can see their TODOs in there and navigate to the TODO upon clicking on it.

SFSF has its API which I would like to use, and I could pretty much instantiate an OData model from my UI5 app and query that API, but there are a couple of issues around that:

◉ Both systems are connected through SSO, so I don’t have an userId and password to pass on that call. Even if I had it, I really don’t want to have that info in my controller.

◉ Both systems have different domains, so I would have to disable CORS on that call and I don’t want to do that either.

I think these two statements above will present great security risks and that is the reason why I am looking for alternatives.

So I figured, if SFSF has an OData API, why cant I just somehow declare that as a service in my SAP Gateway and redirect the call to SFSF using an HTTP destination? This brought me to something called Gateway-OData Consumption and Integration ( package /IWBEP/OCI  ). This thing here allows me to generate an OData service in my own gateway using an external service’s metadata ( it could be SFSF, or it could be literally ANYTHING else, OData of course ).

Here is what I did:

◉ Created a new HTTP destination pointing to my SFSF instance:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification
/odata/v2 is important here, although you could go as far as pointing to a single entity, if that’s all you need.

◉ On the gateway, created a new System Alias, using the newly created RFC Destination:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

◉ Next step is to create an empty service, and to register this service in your gateway against the newly created System alias:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

At this point your OData service is “connected” to SFSF and now we have to build the service structure using SFSF OData metadata.

◉ Click on Redefine -> OData Service (SAP GW)

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

This is going to ask you for some information:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

What I did here is do a full overwrite, specify the technical service name and version, and ask the tool to get the metadata using the RFC destination I created earlier.

◉ Click next.

The tool will try to perform the action, and unfortunately you will get a lot of errors… I don’t have a screenshot to share with you about that, but I guess you will find out for yourself. I will briefly say that, although I don’t know the exact reason as to why these errors come up, it has to do with the fact that SFSF API is huge, and it has a ton of things that don’t translate well when you do the import (function imports and entities with unknown data types etc.), but nothing that cannot be solved with a bit of debugging and getting rid of what you don’t need. I will explain that at the bottom, for now I will continue assuming there are no errors.

In my case, I am interested on the entity TodoEntryV2 and User, as that’s all I really need to cover my scenario, so I did the necessary modifications on OCI (will show later) to only retrieve what I want, and this is what it looks like:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

As you can see I only have the two entities I want and the associations between them:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

◉ Now you generate your service and you are done. Lets make a test:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

Your newly created OData service is ready to query SFSF and is fully capable, as long as you’ve imported the entities, associations and navigation properties you need.

For my scenario this is a big help, as I can simply use this service that is hosted in the same domain as all my other services and my portal, and I don’t have to worry about CORS, or authorizations, all that works behind the scenes.

My main concern is that due to all errors and al modifications I had to do in standard classes to make this work (don’t worry, more on that below), it makes me feel that I am bending a tool that wasn’t really thought to do this, and I might be getting into somewhere I shouldn’t be getting into.

Ok, lastly I will walk you through the changes I had to make in OCI classes to make this work. Basically my changes consist in preventing these classes from reading and loading entities, entity sets, function imports, complex types, associations and domains that I don’t need/want, to keep the model as simple as possible and eliminate the errors.

◉ Class /IWBEP/CL_OCI_MP

The first problem is that, when you read the metadata, you get two Schemas. SFODataSet and SFOData. The code tries to read the entities from first schema, and entity sets from second schema, but I found out that it should be the other way around, so everywhere where I saw this

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

in the methods below, I changed the index to 2.

Second change was to filter out all I did not want. That was done on DEFINE. I created a range of the entities I was interested on and used that to delete everything that did not reference these entities. Also commented create_oci_funcimports() as I was not interested in it at all:

SAP ABAP Tutorial and Material, SAP ABAP Career, SAP ABAP Exam Prep, SAP ABAP Certification

Overview of changes: Overwrite exists on the following methods:

◉ DEFINE
◉ CREATE_OCI_FUNCIMPORTS
◉ PREPARE_ENTITIES
◉ PREPARE_ENTITY_PROPERTIES
◉ PREPARE_COMPLEX_PROPERTIES
◉ PREPARE_ASSOCIATIONS
◉ PREPARE_FUNCTIONIMPORTS
◉ PREPARE_COMPLEX_TYPE_PROPS

No comments:

Post a Comment