OAuth 2.0 is widely used these days in most of the REST Services. To access any REST service which is using OAuth 2.0, you need ACCESS TOKEN from the REST providers.
david.halsband4 has already provided a blog for the same using UDF
https://blogs.sap.com/2017/01/23/oauth-2.0-authentication-within-a-udf-mapping-to-be-included-in-res...
Actual Scenario: You need to send data to a REST service but before you sent it you must have a valid access token which is provided by the same REST provider
Using the REST Lookup in a UDF you can definitely achieve this. But in my case the issue was that the number of transaction were too many to be handled by the Lookup.
So, to achieve this we used another scenario,
REST Pooling Sender Channel & two standard web services
ValueMappingServiceVi &
ChangeListServiceVi to change & activate value mapping respectively. This might not be the best way to achieve it, so If you have some better options do share the same so that the mass can know it. There might be an easy way too, mine may be complex for few of you.
My TEST Value Mapping:
First I'll show the functionality of the two web services:
Path to test standard web services -
http://<HOST>:<PORT>/wsnavigator
- ValueMappingServiceVi
After searching the web service, click Next, you'll be able to see different operations that web service contains & use the one you need. In my case I'll be using the first one i.e.
change operation to change the value of an existing Value Mapping.
Click Next, & populate the data as shown in below screenshot:
MasterLanguage &
languageCode =
EN (for English)
ValueMappingID =
Group ID (In my case it is
57d22255-b80a-11e7-bfd4-00059a3c7a00 & it remains the same in all environment after transport)
GroupName =
Value Mapping Group (in my case it is
TEST)
schemeID =
Scheme
schemeAgencyID =
Agency
value =
Value (whatever value you want to update in value mapping, in my case to test I just used "new token value")
Click Next, on right hand side you should see the result, with a
ChangeListID (in my case it's value is
e2b8c6d1-18c1-11e8-a21c-00000036eb2e)
Now check your Value Mapping it should be updated with the new value & also there must be a change list created under your id for the same.
Now your Value Mapping is updated with the new value. But it should be activated before we can use it. So, to achieve it we'll use another Web Service
ChangeListServiceVi
2.
ChangeListServiceVi
Use the same process as above:
Next
Next
Provide the same
ChangeListID we got in response from first web service (i.e.
e2b8c6d1-18c1-11e8-a21c-00000036eb2e)
Refresh your change list in ID & you'll see that your value mapping is activated.
Now all the above things we did, have to come under a PI scenario. It will be a REST Pooling -> SOAP -> SOAP scenario using Async-Sync Bridge.
To achieve this download the WSDLs for both the web services discussed above.
Path to download WSDL file for web services -
NWA -> SOA -> Application and Scenario Communication -> Single Service Administration -> Service Definitions Tab -> Find
After downloading Zip file, extract it & you'll find 4 wsdl files. You need to use file2 as it is the main file which will give you the External Definition & Service Interface.
Choose the option of "
Import Service Interface" in ESR & import both the wsdl files. After importing you'll see them under Service Interfaces. With Service Interface you'll also see two External Definitions as well. Not discussing here how to import.
Here I renamed the "
file2" before importing, to
ED_ChangeListServiceVi &
ED_ValueMappingServiceVi
Data Type: Only 1 to be created
DT_Token_Request
The above structure you can check with your REST provider, or you can also have it from the REST Pooling sender channel.
Message Type: Only 1 to be created
MT_Token_Request
Service Interfaces: 4 required, out of which two are created by itself when we import wsdl files.
- SI_GetToken_Out - Outbound Asynchronous Stateless XI30 Compatible
- ValueMappingServiceVi - Created by importing, Inbound Synchronous Stateless with Operation changeOut_doc
- SI_ApgieeActivateToken_Out - Outbound Asynchronous Stateless. Uses the External Definition of above web service in Messages i.e. changeOut_doc
- ChangeListServiceVi - Created by importing, Inbound Asynchronous (by default it is Synchronous, changed it to Asynchronous as we don't need any response from it), Stateless with XI30 Compatible. Uses operation activateIn_doc as External Definition to activate the objects.
Message Mappings: 2 Required
- MM_TokenRequest - we only need access_token from REST service in our value mapping, so only that is mapped to value field in the web service structure. Other values will be same as shown while testing ValueMappingServiceVi in WSNavigator & can be passed as Constants.
- MM_ActivateValueMapiing - we need only ChangeListID to be mapped to ChangeListActivateRequest
Operation Mappings - Again 2 required
- OM_GetToken - Sender is Async & Receiver is Sync. You'll get a warning but it will get activated.
- OM_ActivateToken - Make sure to select the operation changeOut_doc as outbound service interface.
ID Objects
Channels:
- REST_GetToken_SND - If your REST Provider supports XML then configure Data Type as "XML" in third tab i.e. Data Format
- SOAP_ChangeTokenValueMapping_RCV - You can use your SAP PI business system for the SOAP channels: Target URL is the endpoint of the web service ValueMappingServiceVi. Target URL - http://<HOST>:<PORT>/ValueMappingService/HTTPBasicAuth?wsdl&mode=ws_policy&style=document. Verify the same from SOA under NWA. Also, under Modules added RequestResponseBean & ResponseOnewayBean so as to pass the response from 1st web service to 2nd web service. For more details on these beans refer: https://blogs.sap.com/2014/01/28/generic-pi-async-sync-bridge-configuration-for-any-adapters/. There are many blogs for the same on sap.com.
- SOAP_ActivateTokenValueMapping_SND - Just required to send the response from 1st web service to the 2nd
- SOAP_ActivateTokenValueMapping_RCV - Channel for the second web service i.e. ChangeListServiceVi. Target URL: - http://<HOST>:<PORT>/ChangeListService/HTTPBasicAuth?wsdl&mode=ws_policy&style=document. Verify endpoint from SOA under NWA.
Integrated Configurations: 2 needed
- | Your REST Provider | SI_GetToken_Out | |
- | INTEGRATION_ENGINE_JAVA | ValueMappingServiceVi.changeOut_doc | | Your REST Provider - Make sure to create this ICO with virtual receiver as your REST Provider business system.
Running the scenario by just starting the REST Pooling Channel, we get below request
Received the
access_token value as
KK4WMDwoyvlhkqZFT1BuSaf5h5YT in JSON. Now the same should reflect in my Value Mapping & it does so.
Now use this value mapping in a java UDF to update the access token in the mapping where you want to connect to the REST Provider to send some data. Refer below code for Dynamic Configuration which will be used in REST Receiver Channel of the actual scenario.
DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey tokenKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","XHeaderName1");
conf.put(tokenKey, token);
Don't use the above code as it is, for proper java coding use try-catch blocks & handle exceptions.
Under the REST Receiver Channel of Actual Scenario,
REST URL Tab configure
Pattern Variable Replacement
Under
HTTP Headers tab enter the
Header Name &
Value Pattern as required by your REST Provider. In my case it was as shown below. The
Authorization - Beared {Token} contains the value from the Value Mapping.
Quite a lengthy way to achieve OAuth 2.0 token, but a fruitful one. Kindly share a better way if you have one, as I still think there might be a better way to achieve it.
Thanks
Ankit Mishra