Skip to Content

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

RFC destination for XSJS.PNG

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.

FUNCTION z_xsjs_get_data.

*”———————————————————————-

*”*”Local Interface:

*”  IMPORTING

*”     VALUE(IV_URL) TYPE  STRING

*”  EXPORTING

*”     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.

   cl_http_client=>create_by_destination(

    EXPORTING

      destination              = ‘HANAXS’    ” Logical destination (specified in RFC destination above)

    IMPORTING

      client                   = lo_http_client    ” HTTP Client Abstraction

    EXCEPTIONS

      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

     EXPORTING

       io_http_client = lo_http_client.

   cl_http_utility=>set_request_uri(

    EXPORTING

      request = lo_http_client->request    ” HTTP Framework (iHTTP) HTTP Request

      uri     = iv_url                     ” URI String (in the Form of /path?query-string)

  ).

   lo_rest_client->if_rest_client~get( ).

   lo_response = lo_rest_client->if_rest_client~get_response_entity( ).

   json_string = lo_response->get_string_data( ).

ENDFUNCTION.

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

Class Interface.PNG

This provides the below method definition:

Class method.PNG

This method definition given by this interface will provide the necessary parameters. Write the below code in that method :

METHOD if_http_extension~handle_request.

     DATA : lv_string TYPE string,

            lv_url    TYPE string.

     lv_url = ‘/JohanXSJS/XSJS/Profit_Center.xsjs?comp=XXXX’.

     CALL FUNCTION ‘Z_XSJS_GET_DATA’

       EXPORTING

         iv_url      = lv_url

       IMPORTING

         json_string = lv_string.

     CALL METHOD server->response->set_cdata( data = lv_string ).

   ENDMETHOD.

Step 4: Make an ICF service that will call the above RFC.


Go to  transaction SICF and select the below hierarchy :

SICF node.PNG

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 :

SICF Handler.PNG

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 !!

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Florian Pfeffer

    Hello Johan,

    in my opinion the “solution” provided here to overcome the CORS issue should not be recommended or used (also not for test scenarios). Reason for that is, that you create a workaround for things for which no workarounds necessary, cause such things are handled by a classic Reverse Proxy (like SAP Web Dispatcher). Creating such additional coding adds more complexity to your landscape and issues higher maintenance efforts.

    Best Regards,

    Florian

    (0) 
    1. Johan Fernandes Post author

      Hi Florian,

      I understand and accept your opinion. It would definitely reduce the amount of code needed to consume XSJS code. Even we are going to use a Web dispatcher , but as a solution I thought I should get the word out there. Thanks for your opinion

      (0) 

Leave a Reply