Skip to Content
Technical Articles

SAP CPI handles token in Global Variable

In the SAP PI/PO, the process is stateless. When it has a requirement to consume a service by using a token, normally we will fetch the taken each time before consuming the service rather than hold the token till it is expired. Apparently the disadvantage is that the network traffic has been increased.

On the other hand, SAP CPI has lots of ways holding the status.

In this end to end tutorial, we will

  • Create an ODATA service that provides a SFLIGHT structure query

The service will use a token as authentication method

The token will be expired every 10 minutes

  • Design an iFlow in SAP CPI to consume the service

1         Process Overview

1.1         Detail steps

  1. POSTMAN sends the request to CPI;
  2. CPI calls ODATA from ABAP backend and get the response;
  3. Response has sent back to POSTMAN;

1.2         Technologies involved in the tutorial

  • ODATA query development;
  • CPI write/read variable;
  • CPI Content Modifier;
  • CPI Exception handling;
  • CPI local call;
  • CPI Message Tracing;

1.2.1        Content download

All of the configured iFlow, groovy script, ABAP programs can be downloaded from here

 

2         Development Steps

2.1         OData Development

If you are not interested in the ABAP OData development, you can skip this part.

Here I used an ABAP ODATA Service working as a Service provider which requires a token. In the real case, it can an ODATA or a generic RESTful service etc.

2.1.1        Create a static class to generate token and token validation check

According to my understanding, a token is periodic expired password. In this case, the first 11 digits of timestamp has been used as a token.

For instance, a full timestamp is: 20200116091124987. It means a time at 09:11:24.987 of 16th of Jan, 2020.

The first 11 digits is 20200116091. It will change every 10 minutes.

However the numeric string looks not similar to a token, we will use a base-64 conversion to make it more beautiful.

This is the method to generate a token

 

This is the method to valid an input token is valid or not

Since the logic of these two methods are quite straightforward and the full class source code can be get here, i will not go deep into analysing it.

2.1.2        Create Odata Service

2.1.2.1         Create Gateway Service

We are going to create a gateway service with two endpoints:

  • Query the SFLIGHT information
  • Get a new token

Get into the ABAP backend, TCODE SEGW

Input a name: YGW_SFLIGHT

In this OData Service, we will implement two endpoints:

  • Sflight query
  • Get a new token

A reusable OData pattern has been used here. I will elaborate it in another Blog Post. The key logic will be analysed here and you can download the whole source code from Github below.

2.1.2.1.1         Sflight Query

This is the source getting ‘token’

    lo_facade ?= /iwbep/if_mgw_conv_srv_runtime~get_dp_facade( ).
    lt_client_headers = lo_facade->get_request_header( ).
    DATA ls_client_headers TYPE ihttpnvp.
    READ TABLE lt_client_headers WITH KEY name = 'token'
         INTO  ls_client_headers.

The ‘token’ is in the variable:

ls_client_headers-value

To check the token is valid or not:

IF ycl_token=>validate( token =  ls_client_headers-value ) EQ abap_true.
" Do whatever you want. for this case, it is to ready table SFLIGHT
ENDIF

If the token is not valid use the following code to raise the HTTP exception

      CONSTANTS : lc_unauthorized TYPE /iwbep/mgw_http_status_code VALUE '403'.
      DATA:
        ls_message type SCX_T100KEY.
      ls_message-attr1 = 'Token is expired'.
      RAISE EXCEPTION TYPE /iwbep/cx_mgw_tech_exception
        EXPORTING
          http_status_code = lc_unauthorized
          textid           = ls_message.

This is the code to derive the search condition ‘CARRID’

  lt_filters = io_tech_request_context->get_filter( )->get_filter_select_options( ).

  IF NOT lt_filters[] IS INITIAL.
* Derive search conditions
    READ TABLE lt_filters ASSIGNING <ls_filter> WITH KEY property = 'CARRID'.
    IF sy-subrc EQ 0.
      LOOP AT <ls_filter>-select_options[] ASSIGNING <ls_select_option>.
        APPEND INITIAL LINE TO lt_r_carrid ASSIGNING <ls_r_carrid>.
        MOVE-CORRESPONDING <ls_select_option> TO <ls_r_carrid>.
      ENDLOOP.
    ENDIF.
  ENDIF.

This is the source code getting the SFLIGHT records

  SELECT *
    FROM sflight
    INTO TABLE lt_entityset
   WHERE carrid IN lt_r_carrid.
  IF sy-subrc EQ 0.
    /iwbep/if_mgw_conv_srv_runtime~copy_data_to_ref(
      EXPORTING
        is_data = lt_entityset
      CHANGING
        cr_data = er_entityset
    ).
2.1.2.1.2         Get a new token

The logic of this endpoint is very simple. Just two lines of source code:

  er_entity-operation = 'GET'.
  er_entity-token     = ycl_token=>generate( ).

2.1.2.2         Test the service

Get a token

Use the token to make a query

Use the token after few minutes( to test exception raised )

These services will be consumed later by SAP CPI.

 

2.2         Cloud Connector Configuration

To connect SAP CPI with SAP Backend system, Cloud connector is the recommended application.

SAP CPI configuration can be easily found on google.  Here is one for your reference:

http://www.sapspot.com/how-to-guide-connectivity-setup-with-abap-and-sap-cloud-connector/

2.3        CPI iFlow Configuration

The main process of the iFlow will be as below:

  1. Get the stored token from Global container;
  2. Use the token to make a query;
  3. The HTTP error status will trigger an exception occurring;
  4. The exception catching process will be start;
  5. The iFlow will call backend getting a new token;
  6. The iFlow will update the global container by using the new token;
  7. The iFlow will start again from step 1 and 2.

Here is the detail step

Log into SAP CPI account

2.3.1        Create a Credential

Monitor –> Overview –> Manage Security –> Security Material

Click Add button and choose ‘User Credentials’

 

After deploying, the credential will be listed here. Record the name and it will be used later.

2.3.2        Create iFlow

Switch to Design view

Select your own folder or create a new folder

Goto tab Artifacts

Click the EDIT button on the top left corner

Select the Add dropdown menu –> Integration Flow

Fill in the information in the popup dialog

there you are. this is the empty iFlow you have created.

2.3.3        Configure the iFlow

Create a sender adapter from Sender to iFlow

Drag and drop Connector to Start event on the right side

Select HTTPS

Input a name for the adapter

Specify an endpoint here and switch off the CSRF check to simply the DEMO

2.3.4        Configure the Main Process

As planned in the first step, we will retrieve a token from global container

Drag and drop a content modifier

In order easy to track trace, give a name Main Process: Set Token in Header

Select the content modifier box and Click Add button

Fill in the values as below

Leave tabs Exchange Property and Message Body blank there

Now we will try to fetch the data from backend

Drag and Drop a Request Reply

Call –> external call –> Request Reply

Input a name: Main Process: Get Sflight

Drag and drop an HTTP adapter from the Request Reply component to system ERPCLNT100

Fill in a name to the adapter

Input {{hostname}}:{{port}} so that these two segments will be parameterized.

Change Proxy type to ‘on promise’ , Method to Get, Authentication to Basic

Credential is configured in the previous chapter

2.3.5        Create Exception Process

Since the token will somehow be expired, we will need a process to catch the exception.

Drag and drop an Exception Subprocess into main process box

Name it as: Main Process: Exception Handling

Here we will create two steps here:

  1. Get a new token from backend;
  2. Write the token to the global container;

From call –> local call –> process call, drag and drop two calls into the process flow ‘Main Process: Exception Handling’ as below

 

Input names for each of them:

  • Main Process: Exception Handling: Update a new Token
  • Main Process: Exception Handling: Get Sflight

Create a local process for local call Main Process: Exception Handling: Update a new Token

2.3.6        Create a local process Update a new Token

From process à local Integration Process, drag and drop a process into the iFlow

Input a name: Process: Update a new Token

Let it be called by Main Process: Exception Handling: Update a new Token

Select the call Main Process: Exception Handling: Update a new Token of exception handling process

Select tab Processing

Select the process created

Switch back to local process ‘Process: Update a new Token’.

Drag and drop a ‘Request-Reply’ call into the process

Give a name Sub Process: Update a new Token: Get a new Token

Drag and drop an adapter to ERPCLNT100

Fill the name HTTP_Receiver_GetToken to the adapter

Input the values as below:

next step, we will write the token get to the global variable so that it can be derived by any iFlow instance.

Drag and drop a Write Variables process

Name it: Sub Process: Update a new Token: Update Token

this is the entry maintained to the Processing tab page. make sure the Global Scope flag has been checked.

The variable name has to be the same as the one used in the content modifier.

2.3.7       Create a new sub process Get Sflight

The process is the same as the main process

Switch to Exception Handling process, select the process

 

Drag and drop a Request-Reply to the process

Input url http://{{hostname}}:{{port}}/sap/opu/odata/SAP/YGW_SFLIGHT_SRV/SflightSet

This is the process configured:

2.3.8        IFlow Overview and Deployment

This is the whole iFlow after designing

Deploy the iFlow by clicking the button on the upper right corner.

2.3.9        Configure the iFlow

Input hostname and port for the HTTP adapters used in the iFlow

Deploy the configuration.

Please feel free to Download the iFlow from here

3         Unit Test

Switch the monitor level to trace

Goto monitor, choose the iFlow

Get the endpoint URL

Use POSTMAN to trigger a request call

Check the monitor

you will find that The token is invalid at the first call

This is the New token retrieved

here is the Payload in the last step

 

Soon after the first call, make a second request from POSTMAN

As we can see, from the message overview, we can see that the first call lasted 3.45 seconds whereas the second one lasted 0.26 seconds

This is the running steps of the second call, which as 7 steps, Compared with the first call which does have 17 steps.

4        Conclusion

By using global variable and write variable steps, the status can be held amount instances of a same CPI iFlow template and it will be better for the performance.

 

Be the first to leave a comment
You must be Logged on to comment or reply to a post.