Skip to Content

Introduction

Over the last week i spent a vast amount of time playing around with the Smart Table Control and trying to generate an ODATA Service in our Gateway Backend delivering the needed Annotations for this Control.

After endless hours of trial and error and analyzing the Smart Table Example in the Explored App

https://sapui5.hana.ondemand.com/explored.html#/sample/sap.ui.comp.sample.smarttable/preview

i finally managed to get the needed Annotations like the LineItem for setting default Columns delivered by our Gateway.

In this Blog i will share my Experience with this and show the method i used to maybe save others this time consuming task of trial.

The only Requirement for this to work is that you are using SAPUI5 Version 1.30.3 or above as they fixed the parsing of Collections and Records for Annotations in this Version which is neccesary for this to work properly.

In this Part of the Blog we will look on how to implement the ODATA Service in the Backend Gatway System.

The Problem

The Smart Table Control requires not only the Standard SAP Annotations like creatable, filterable etc. but also the use of ODATA Annotation which are supported by Netweaver Gateway for a while now. The Problem is in the current state of the Gateway Service Builder Transaction you could choose to either use the SAP or the ODATA Annotations not both of them at the same time.

The Solution

By utilizing the possibility to create seperate Annotation Models to enrich the Standard Service with SAP Annotations with the needed ODATA Annotations and linking the ODATA Model on the Clientside with the Annotation Model you will be able to use both Annotation Types. However this requires some manual Coding as the Service Builder by now is not able to generate the needed Annotations (as far as i know).

This requires some steps which i will explain in the following sections.

Creating the ODATA Service

To deliver some Data to actually display in the Smart Table we need to create an basic ODATA Service. For this Service i used the BAPI BAPI_CUSTOMER_GETLIST to get a List of Customers to display in the Table.

Base_Service_Project.PNG

Be sure to select “Service with SAP Annotation” for the Project Type.

I´m not going into Details here about creating the mapping and this stuff as this should be relatively well documented by now.

Just get sure you are checking some of the Entity Properties as filterable to enable the Filtering for these in the Smart Table.

After setting up the Service generate the Runtime Artifacts.

Creating the Annotation Model

To enrich the previous Service with the additional Annotations, for example the LineItem for the default Columns we need to create an Annotation Model.

In Service Builder create a new Project of Type “Annotationmodel for referenced Service”.

Annotationmodel_Project.PNG

Then open this Project in Edit Mode and right Click on the Data Model, select Import and Servicereference

Reference.png

In the Popup select the Service you want to annotate. This will import the Data Model into your Annotation Model.

Then do the same again but this time select Vocabulary and import the Vocabularies you want to use.

You can now generate the Annotation Model for the Service as from now on the Gateway Builder will not be able to generate the needed Changes.

Extending the Annotation Model

Generating the Runtime Artifacts for the Annotation Model will generate an Extension Class (ZCL_MODELNAME__01_APC_EXT) for you.

Open this Class go to the Methods, select the Method “DEFINE_VOCAB_ANNOTATIONS” and click on redefine.

In the Redefinition of this Method we want to implement the Annotation for the LineItem Collection for the Smart Table like this:


METHOD define_vocab_annotations.
*Data Declaration
    DATA: lo_ann_target TYPE REF TO /iwbep/if_mgw_vocan_ann_target.                 
    DATA: lo_annotation TYPE REF TO /iwbep/if_mgw_vocan_annotation. 
    DATA: lo_collection TYPE REF TO /iwbep/if_mgw_vocan_collection. 
    DATA: lo_function  TYPE REF TO /iwbep/if_mgw_vocan_function.   
    DATA: lo_fun_param  TYPE REF TO /iwbep/if_mgw_vocan_fun_param.   
    DATA: lo_property  TYPE REF TO /iwbep/if_mgw_vocan_property.   
    DATA: lo_record    TYPE REF TO /iwbep/if_mgw_vocan_record.     
    DATA: lo_simp_value TYPE REF TO /iwbep/if_mgw_vocan_simple_val.
    DATA: lo_url        TYPE REF TO /iwbep/if_mgw_vocan_url.       
    DATA: lo_label_elem TYPE REF TO /iwbep/if_mgw_vocan_label_elem. 
    DATA: lo_reference  TYPE REF TO /iwbep/if_mgw_vocan_reference.   
*Calling the generated mehtod for creating annotations
    CALL METHOD super->define_vocab_annotations( ).
*Creating the references for the vocabularies
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_CAPABILITIES'
                                                                iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'Org.OData.Capabilities.V1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_CORE'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'Org.OData.Core.V1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_COMMON'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.Common.v1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_COMMUNICATION'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.Communication.v1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_MEASURES'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'Org.OData.Measures.V1' ).
    lo_reference = vocab_anno_model->create_vocabulary_reference( iv_vocab_id = '/IWBEP/VOC_UI'
                                                                  iv_vocab_version = '0001').
    lo_reference->create_include( iv_namespace = 'com.sap.vocabularies.UI.v1' ).
*Creating the Annotation Target
    lo_ann_target = vocab_anno_model->create_annotations_target( iv_target = 'ZCUSTOMER_SRV.Addressdata' ).
*Creating the LineItem Collection
lo_annotation = lo_ann_target->create_annotation( iv_term = 'com.sap.vocabularies.UI.v1.LineItem' ).
    lo_collection = lo_annotation->create_collection( ).
*Creating the Records
    lo_record = lo_collection->create_record( iv_record_type = 'com.sap.vocabularies.UI.v1.DataField' ).
    lo_property = lo_record->create_property( iv_property_name = 'Value').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_path( 'Customer' ).
    lo_property = lo_record->create_property( iv_property_name = 'Label').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_string( 'Kunde' ).
*
    lo_record = lo_collection->create_record( iv_record_type = 'com.sap.vocabularies.UI.v1.DataField' ).
    lo_property = lo_record->create_property( iv_property_name = 'Value').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_path( 'Country' ).
    lo_property = lo_record->create_property( iv_property_name = 'Label').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_string( 'Land' ).
*
    lo_record = lo_collection->create_record( iv_record_type = 'com.sap.vocabularies.UI.v1.DataField' ).
    lo_property = lo_record->create_property( iv_property_name = 'Value').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_path( 'Name' ).
    lo_property = lo_record->create_property( iv_property_name = 'Label').
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_string( 'Name' ).
*
  ENDMETHOD.






In Line 36 we are creating an Annotation for our Entity (i called it Adressdata).

You must set the target with the Pattern ServiceNamespace.Entity. You can find this Namespace in your Service Metadata Definition.

We are then creating an Annotation for the LineItem and add a Collection to it. In the Collection Records you can then set your Default Columns.

The Path in the Value Property must correspond to one of your Entity Properties while the Label can be anything you want (this is the Text which is shown in the Table as Column Title).

Activate this Class and we are done with the Backend Coding.

You can verify that everything went smoothly by calling your Annotation Model in the Gateway Client with the URL:

/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName=’YOURMODELNAME_MDL’,Version=’0001′)/$value

You should see the Annotations we made on the bottom of the Response.

Annotation_ODATA.PNG

In the next Part we will look on the Coding required on the SAPUI5 Application to tell the Smart Table about the created Annotation Model.

Regards,

Florian

To report this post you need to login first.

17 Comments

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

  1. Florian Kruse

    Hi Florian,

    I have eactly this problem when trying to set up a SmartTable. The popup at the beginning

    telling me to select coloumns first is very annoying.

    So i was very happy to find your post exactly on this.

    But there is one problem for me. I followed your instructions step by step and even checked my existing OData Service if it’s suitable for this.

    Everything went well, but when i am trying to test my annotations using your link i get the following error:

    Keine Vokabularannotationsdatei für ID “SERVICE_MODEL_NAME”, Version “0001”, gefunden

    Everything is activated and saved. Do you have any further ideas on this?

    Greetings from Bielefeld,

    Florian Kruse

    (0) 
    1. Florian Hafner Post author

      Hello Florian,

      I noticed this problem too but as of now its gone for me. But basically you can just throw the Coding into your MPC_EXT Class of your Service and it should work too. You just loose this nice Separation between Servicedefinition and Annotationdefinition (it´s very cool in my opinion as you can just generate many different Annotations fo a single service if you need to).

      Regards,

      Florian

      (0) 
      1. Arshad Ansary

        Hi Florian

        I am getting “Select atleast one column to search ” in my UI5 application even though I have filled LineItem annotation property for my entity type

        Is there anything I am missing here ?

        Odata_annot.png

        (0) 
        1. Florian Hafner Post author

          Hello Arshad,

          If you are using a separate Annotation File you have to set the property annotationURI of your oData Model to the Annotation File.

          I wanted to point this out in Part 2 but didnt had the time since to do so.

          Regards

          Florian

          (0) 
          1. Florian Hafner Post author

            Hello Arshad,

            Can you try it like this:

            var sServiceUrl = “yourServiceUrl”;

            var oConfig = {

              metadataUrlParams: {},

              json: true,

              annotationURI: “yourAnnotationModelUrl”,

              loadAnnotationsJoined : true,

              defaultBindingMode: “TwoWay”,

              defaultCountMode: “Inline”,

              useBatch: true

              };

              var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl, oConfig);

            This worked for me.

            You can verify that the Annotations are loaded by calling the Model in Debugger and look at the oAnnotations Property.

            It should look similar to this:

            oAnnotations.PNG

            Edit: And i guess you have an Error in your LineItem Annotation you need 2 Propertys per Record.

            One with Path=”yourServiceProperty” and Property=”Value” and another one with String=”anyCustomName” and Property=”Label”.

            Look at my ABAP Coding Lines 40-47.

            There im creating two 2 Propertys for the Customer Record. One is the Reference to the actual Entity Property and the other is a Custom Label which is shown in your table.

            Regards,

            Florian

            (0) 
    2. Marcos Andrade

      Hello Florian,

      I had the same problem and realized that I havent Activate the Odata Service in the transaction /IWFND/MAINT_SERVICE

      after that it worked.

      Regards,

      Marcos

      (0) 
      1. Tejas S. Gargeya Sastry

        Hi Florian,

        I have mentioned the oConfig properly and the annotations load properly on the SAPGateway Client. However, it just doesn’t load when called from the UI.

        1. oAnnotations: E.extend.constructor
          1. bAsync: true
          2. bLoaded: false
          3. bValidXML: true
          4. mEventRegistry: Object
          5. oAnnotations: Object
          6. oError: null
          7. oFailedEvent: null
          8. oLoadEvent: null
          9. oMetadata: Object
          10. oRequestHandles: Array[0]
          11. xPath: null
          12. __proto__: d

        Any thoughts as to why this might be happening? Looking forward to your response. Thank you.


        Regards,

        Tejas.

        (0) 
  2. Sashko Janev

    Hi Florian,

    I have created the oData service as you did, but when I try to create the annotation reference model i only see 2 options: Screenshot_4.jpg

    And I’m guessing you are using another option, right?

    Am I missing some step in configuration?

    (0) 
    1. Florian Hafner Post author

      Hello Sashko,

      yes you should see a third option there.

      Maybe you have to update your SAP_GWFND Component.

      I guess the SEGW is part of the Gateway Component.

      What is your patchlevel there?

      but as stated in the response for Florian you could also slap the annotations inside your model definition in your mpc_ext Class of your service.

      Regards

      Florian

      (0) 
      1. Sashko Janev

        I think it’s the latest version:Screenshot_1.jpg

        About the code you mentioned, where should I insert it, because i don’t have that method that you talk about in the tutorial. Should I create a new one or put it in some of the existing methods:

        Screenshot_2.jpg

        Thanks.

        (0) 
        1. Florian Hafner Post author

          Hello Sashko,

          Inside the DEFINE Method you should see the definition of your Model Entitys and Property.

          When you redefine this Method you can add the Code there.

          The Method DEFINE_VOCAB_ANNOTATIONS is a generated Method for the Annotation Classes which you will not get because you are extending a basic ODATA Service and not a Annotation Service.

          Here is a example:

          DEFINE.PNG

          Regards,

          Florian

          (0) 
  3. Heidrun Meisel

    Hi Florian,

    I have a problem using this reference service in UI5 because there is not really an external serice with this name and if I try to create it, I get the message that there is no backend service. SEGM shows me the definition of the original service for the reference service too. Would it be possible to explain how this reference service can be used for smart tables? A comination of the original service and the reference annotation model did also not solve my problem with missing metadata information concerning initially used columns.

    Regards,

    Heidrun Meisel

    (0) 

Leave a Reply