How do we consume XS services (hosted on a different domain) in our SAP UI5 application (hosted on gateway server)? Generally it shouldn’t have been a problem, but as UI5 apps are usually run on chrome all UI5 developers would or will have faced the dreaded CORS ! issue at some time while consuming an XS service.
CORS (Cross-Origin-Resource-Sharing), to explain in brief a web security measure to ensure that services that reside outside our domain can only be used if there is a trust between them (like an SSL connection). This creates a small roadblock as UI5 developers try to consume XS services. Let’s say hosted on http://xs.engine.com while the UI5 app resides on gateway let’s say hosted at http://gateway.com, as the Gateway domain and XS aren’t the same we get the dreadful CORS error. Don’t get me wrong, CORS has probably saved a lot of enterprise sites from being hacked so it quite necessary for web security
Moving on, for this blog I will be describing how to consume only XSJS service in Gateway and not XSODATA services.
There are three possible solutions to solve this
1. Use a proxy over XS engine so that the Gateway can make a secure connection to consume the services.
2. Use JSONP data type to consume XSJS while making an ajax call from SAPUI5
3. Create an ABAP object (RFC preferably) in Gateway that will consume the XSJS service and publish the data using an ICF service (created on the Gateway)
I have performed both solution 2 and 3. I will be describing solution 2 in another blog. Although using JSONP is way more easier than solution 3 there are a few drawbacks which will be explained in the next blog:
How to consume XSJS as JSONP in SAPUI5 application.
For Step 1 and 2 i referred a very useful blog by Amaresh Pani : http://scn.sap.com/community/abap/connectivity/blog/2014/11/09/calling-an-external-restful-service-from-abap–http-method-get
Note the XSJS service here is a GET service. I will be exploring this more in the next few days for POST services as well.
The service I am trying to hit is : http://<XS engine host>:<port>/JohanXSJS/XSJS/Profit_Center.xsjs?comp=XXXX
Step 1: Create an RFC destination with connection type G (i.e. to External Server) to your XS engine
You can mention the DB user credentials in the Logon tab that would ensure that you that you can access the XSJS service without a logon prompt.
Step 2: Create an RFC to use this RFC destination and call any XSJS service dynamically.
*” VALUE(IV_URL) TYPE STRING
*” VALUE(JSON_STRING) TYPE STRING
DATA : lo_http_client TYPE REF TO if_http_client,
lo_rest_client TYPE REF TO cl_rest_http_client,
lo_response TYPE REF TO if_rest_entity,
lv_url TYPE string.
destination = ‘HANAXS’ ” Logical destination (specified in RFC destination above)
client = lo_http_client ” HTTP Client Abstraction
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6
CREATE OBJECT lo_rest_client
io_http_client = lo_http_client.
request = lo_http_client->request ” HTTP Framework (iHTTP) HTTP Request
uri = iv_url ” URI String (in the Form of /path?query-string)
lo_response = lo_rest_client->if_rest_client~get_response_entity( ).
json_string = lo_response->get_string_data( ).
Step 3: Make a handler class that will be consumed by ICF service node
Add an interface as shown below to the class to make a Handler class for ICF service
This provides the below method definition:
This method definition given by this interface will provide the necessary parameters. Write the below code in that method :
DATA : lv_string TYPE string,
lv_url TYPE string.
lv_url = ‘/JohanXSJS/XSJS/Profit_Center.xsjs?comp=XXXX’.
CALL FUNCTION ‘Z_XSJS_GET_DATA’
iv_url = lv_url
json_string = lv_string.
CALL METHOD server->response->set_cdata( data = lv_string ).
Step 4: Make an ICF service that will call the above RFC.
Go to transaction SICF and select the below hierarchy :
Click on the Create Host/Service button at the top left corner to create a new node under this hierarchy.
In the Handler tab enter the name of the class you’ve created in Step 3 :
Right click on the node then Activate this node and then test it in the browser.
Now this service will be as follows : http://<gateway host>:<port>/sap/bc/zxsjs?sap-client=XXX.
You can add query parameters that can be captured in your handler class. I will be updating the blog with how to call two or more services with this one handler class.
In your UI5 code you can access this service with an ajax call to this service. Hope this helps all the UI5 developers out there !!