Skip to Content
Technical Articles

ABAP SDK for IBM Watson: Step-by-Step Tutorial

IBM Watson provides a set of industry leading AI services for conversation, natural language processing, visual recognition and other purposes. Just recently, we released the ABAP SDK for IBM Watson, which is an open source community project for integrating IBM Watson services in SAP applications using pure ABAP language. For more details, see announcement at https://developer.ibm.com/blogs/open-source-project-developers-ibm-watson-developer-services-within-sap.

This blog post is a step-by-step tutorial for implementing an ABAP program for language and sentimental tone detection. IBM Watson Tone Analyzer service is used to perform the sentiment analysis.

Though this tutorial focuses on sentiment analysis, other IBM Watson services can be utilized similarly. Thus, the description here can be used as a blueprint for integrating any IBM Watson service into an ABAP application.

Instantiate the IBM Watson Service

The IBM Cloud is a Software-as-a-Service platform that offers over 190 services, including IBM Watson AI services. It is located at

cloud.ibm.com

If you do not yet have an IBM Cloud account, create one. A free account is enough to complete this tutorial.

Login to the IBM Cloud. On the dashboard, click button Create Resource, select category AI on navigation pane and click the Tone Analyzer tile.

The IBM Watson services offer multiple plans including a free plan that can be used for testing. Select the Lite plan here. You may also want to adjust the Service name. Afterwards click button Create.

The service is instantiated immediately.

To use the Tone Analyzer within an ABAP application, you must know the service credentials. They consist of an API Key and a URL and can be displayed on the Manage view.  You will need them later in your ABAP program to access the service instance.

Installing the ABAP SDK for IBM Watson

The ABAP SDK for IBM Watson is available as public Github repository

https://github.com/watson-developer-cloud/abap-sdk-nwas

Therefore, abapGit must be installed on your system. Follow instructions on  https://docs.abapgit.org to do so. Do not forget to setup the abapGit Repo and to pull the latest abapGit code.

Start the abapGit application (transaction zabapgit). Click +Online to add a new online project. Enter

Git clone URL https://github.com/watson-developer-cloud/abap-sdk-nwas.git
Package ZIBMC

Afterwards click ok.

On the Git repository view click Pull and select a transport request to clone the ABAP sources to your system.

If you are experiencing an SSL issue, check that all profile parameters are set correctly and required SSL certificates are installed. See https://docs.abapgit.org/guide-ssl-setup.html and file README.md of the Git repository for more details.

After cloning, package ZIBMC contains all objects of the ABAP SDK for IBM Watson.

Using the ABAP SDK for IBM Watson with a custom ABAP program

Now you are ready to exploit the ABAP SDK with your own ABAP programs.

Create new ABAP Program ZDEMO_TONE_ANALYZER. When completely implemented, this program reads plain text as input, analyzes the tone of the input text and prints the result.

First, add a line for input parameter i_text. This parameter will contain the text that is be analyzed for sentiments by your program.

parameters: i_text type string.

Instantiate ABAP class for IBM Watson Service

You must instantiate an ABAP class that provides an interface to your individual IBM Watson service instance. Since you are using the Tone Analyzer service, the corresponding ABAP class is zcl_ibmc_tone_analyzer_v3. You find the ABAP class name for each IBM Watson service and detailed descriptions in the online reference at

https://watson-developer-cloud.github.io/abap-sdk-nwas

Add an appropriate data declaration to your program.

data: lo_tone_analyzer type ref to zcl_ibmc_tone_analyzer_v3.

Call factory method zcl_ibmc_service_ext=>get_instance to instantiate the ABAP class. This method requires as parameter the IBM Watson service credentials (host and API key) for your individual IBM Watson service that you have instantiate in IBM Cloud before. Also, you must specify IBM Watson service API version as parameter.

The factory method returns a reference to the instantiated ABAP class. Be aware that the class type is determined by the type of the importing parameter which has been specified by the explicit data declaration before. Therefore, you must not use implicit data declaration here.

zcl_ibmc_service_ext=>get_instance(
  exporting
    i_host      = 'https://gateway.watsonplatform.net'  " adjust
    i_apikey    = 'HYrMpH-WcE1iIWN...'                  " adjust
    i_version   = '2017-09-21'
  importing
    eo_instance = lo_tone_analyzer ).

Invoke IBM Watson service API endpoint

You want to call IBM Watson service API endpoint tone to perform the sentiment analysis of the input. The IBM Watson service requires the input text in JSON format. For details, see the IBM Watson service reference https://cloud.ibm.com/apidocs/tone-analyzer#analyze-general-tone-get.

{ "text": "This is the input text!" }

The ABAP SDK for IBM Watson provides the ABAP class method tone that represents an ABAP interface to the IBM Watson service API endpoint and transparently converts JSON data to ABAP structures and vice versa. Suitable ABAP types for data exchange are provided as well. Here ABAP structure type zcl_ibmc_tone_analyzer_v3=>t_tone_input represents the data structure that is required by IBM Watson service API endpoint tone and is therefore the type of the input parameter of ABAP class method tone. Thus, declare a variable of that type and assign the input text to the corresponding ABAP structure component.

data: ls_tone_input type zcl_ibmc_tone_analyzer_v3=>t_tone_input.
ls_tone_input-text = i_text.

Now you are ready to perform IBM Watson tone analysis by invoking the corresponding ABAP method tone. You should implement a try-catch block to catch exception zcx_ibmc_service_exception in case of an error. This exception implements interface IF_T100_MESSAGE and can therefore be used with the MESSAGE command.

try.
    lo_tone_analyzer->tone(
      exporting
        i_tone_input = ls_tone_input
      importing
        e_response   = data(ls_tone_analysis) ).
  catch zcx_ibmc_service_exception into data(lo_service_exception).
    message lo_service_exception type 'E'.
endtry.       

The response of IBM Watson service API endpoint tone in JSON format is hidden by the ABAP SDK for IBM Watson.

{ "document_tone":
   { "tones": [
      { "score": 0.570687,
        "tone_id": "sadness",
        "tone_name": "Sadness" },
      { "score": 0.820755,
        "tone_id": "analytical",
        "tone_name": "Analytical" } ]
   },
  ...
}

ABAP class method tone converts the IBM Watson service response in JSON format to an ABAP structure. Objects in JSON are mapped to ABAP structures and arrays in JSON are mapped to internal tables. The filled ABAP structure is returned by the ABAP class method.

Assign the importing parameter to ABAP variable ls_tone_analysis using implicit data declaration as indicated in the ABAP code snippet above. The variable is used to access the response of the IBM Waston Tone Analyzer service by regular ABAP means.

For example, loop at internal table ls_tone_analysis-document_tone-tones to write all rated tones to a SAPGUI list. Since there is also a data type defined for the records of that internal table, direct access to the components of a record is supported. Subsequently assign each record to variable ls_tone using implicit data declaration.

loop at ls_tone_analysis-document_tone-tones into data(ls_tone).
  write: / ls_tone-tone_name,
           at 20 ls_tone-score exponent 0 decimals 2 left-justified.
endloop.  

That’s it!

You can now run your program. As an example, enter the following text for parameter i_text.

“Team, I know that times are tough! Product sales have been disappointing for the past three quarters. We have a competitive product, but we need to do a better job of selling it!”

Your program should return the result of the text analysis as score for various tones like shown on the screenshot below.

Storing IBM Watson service credentials in a table.

You must provide IBM Watson service credentials to ABAP method zcl_ibmc_service_ext=>get_instance in order to instantiate an ABAP class. By reason of better security and easier maintenance it is recommended to not hard code the credentials in your ABAP program. Instead, you can store the credentials in table ZIBMC_CONFIG.

Add the following two records to table ZIBMC_CONFIG.

SERVICE TONE_ANALYZER_V3 (ABAP class name without prefix ZCL_IBMC_)
INSTANCE_UID TONE_ANALYZER_DEMO (an individual ID)
PARAM APIKEY
VALUE HYrMpH-WcE1iIWN… (Adjust IBM Watson service instance API Key)
SERVICE TONE_ANALYZER_V3
INSTANCE_UID TONE_ANALYZER_DEMO
PARAM HOST
VALUE https://gateway.watsonplatform.net (Adjust IBM Watson service instance host)

Now you can provide service credentials to ABAP method zcl_ibmc_service_ext=>get_instance by specifying parameter i_instance_id. The parameter value is INSTANCE_UID as it appears in table ZIBMC_CONFIG.

zcl_ibmc_service_ext=>get_instance(
  exporting
    i_instance_id = 'TONE_ANALYZER_DEMO'
    i_version     = '2017-09-21'
  importing
    eo_instance = lo_tone_analyzer ).

Complete ABAP Program

Finally, here is the complete source code of your ABAP program.

report ZDEMO_TONE_ANALYZER.

" input parameter
parameters: i_text type string.

" Data declaration using type provided by ABAP SDK for IBM Watson
data: lo_tone_analyzer type ref to zcl_ibmc_tone_analyzer_v3.

" Get ABAP class instance for IBM Watson service
zcl_ibmc_service_ext=>get_instance(
  exporting
    i_instance_id = 'TONE_ANALYZER_DEMO'
    i_version     = '2017-09-21'
  importing
    eo_instance = lo_tone_analyzer ).

" Prepare input parameter for IBM Watson service API endpoint
data: ls_tone_input type zcl_ibmc_tone_analyzer_v3=>t_tone_input.
ls_tone_input-text = i_text.

" Call IBM Watson service API endpoint
try.
    lo_tone_analyzer->tone(
      exporting
        i_tone_input = ls_tone_input
     importing
       e_response    = data(ls_tone_analysis) ).
  catch zcx_ibmc_service_exception into data(lo_service_exception).
    message lo_service_exception type 'E'.
endtry.

" Print response payload
loop at ls_tone_analysis-document_tone-tones into data(ls_tone).
  write: / ls_tone-tone_name,  
        at 20 ls_tone-score exponent 0 decimals 2 left-justified.
endloop.​

Conclusion

In this blog post I have shown that you need just a few lines of code to add AI powered by IBM Watson to your ABAP application. Certainly, the techniques described here do not only apply to programs, but also to other ABAP objects, for example OData services that are bound to a Fiori application.

Explore the IBM Watson services at https://cloud.ibm.com/apidocs?category=ai and imaging how these services bring AI to your ABAP code. Have Fun!

3 Comments
You must be Logged on to comment or reply to a post.
  • Nice implementation.

     

    One thought:

    Why storing credentials in DB table is better than hard-coding them?

     

    P.S.

    SAP Already has a secure storage (SECSTORE), but sadly it's for SAP internal use only.

    • Hi Shai,

      Thanks for the comment.

      You definitely want to separate credential (customizing) data from program code. For example, you do not want to change your code if you have to apply another IBM service instance. Also, you may want to apply different IBM service instances for development and production, but you have the same (transported) code on both systems.

      You are right, SECSTORE would be the natural location for these kind of credentials, but as you said, is limited to SAP internal programs.

      If storing service credentials in a table does not fit to your security policy, you can implement custom token handling, see https://github.com/watson-developer-cloud/abap-sdk-nwas#iam-authentication.

      Regards, Joachim