Skip to Content
Technical Articles
Author's profile photo Andre Fischer

How to move from Easy Queries to OData Queries

If you have not yet started with the development of OData services based on BW queries you should be aware that there are three options how to build such services.

  • The oldest one is to use Easy Query which was invented with focus on SOAP services with SAP Netweaver 730 and is in maintenance.
  • ODataQuery is the successor for Easy Query starting SAP Netweaver 740.
  • The third approach uses CDS views.

All are described in detail in the following blog post

BW Query on CDS View, OData from BW and value of BW Query in S/4HANA | SAP Blogs

Why then this blog post?

The reason to publish this blog post was a question of a customer whether it is possible to extend an OData service that has been created via redefinition based on an Easy Query.

OData services based on Easy Queries cannot be extended

The answer is unfortunately, no, this is not possible. And SEGW will show the following dialogue when you try to redefine your data model a second time by choosing:

Redefine –> BW Query Service.

 

Redefining Services from External Framework (SPI, BW Query, GenIL) – SAP Help Portal

 

OData Services based on OData queries can be extended

ODataQuery is the successor for Easy Query starting SAP Netweaver 740 and it is the recommended way to publish BW queries as OData services as described in the following SAP Note:

3154424 – Recommendations for Using EasyQuery and ODataQuery – SAP ONE Support Launchpad

Since the OData service that is generated when saving your BW query having the flag “with OData” checked is based on a generic model provider class and a generic data provider class any change in the underlying query is automatically reflected in the generated OData service.

You can now use the option to redefine this OData service when you want to use nice and human readable names for the properties of your OData service.

Redefining OData Service (SAP GW) – SAP Help Portal

The Redefine SAP Gateway Service function allows the user to do the following:

  • Redefine a service – to redefine a service for the first time in the Service Builder.
  • Extend current model – to add more artifacts to your model from an existing model. If your model already has artifacts from a reference model, you can add more artifacts from this model only.

The option “Extend current model” is not available when your OData model is based on an external framework.

Sample service

For this blog post I used the BW Query 0D_FC_NW_C01_Q0001 which is part of BW demo content.

SAP DemoContent for Features – SAP Help Portal

Beautification

The reason why redefinition is used is that it allows the developer to choose human readable names for the OData service opposed to the technical names that are based on the technical names of the BW query.

In the Service Builder UI this looks as follows.

Technically the Service Builder will store these changes in the model provider class with the extension _MPC which is regenerated each time the SEGW project is regenerated.

When you have renamed the properties in a SEGW project that is based on an Easy Query you will find the following method call in the DEFINE method of your _MPC class.

change_external_names( ).

The method change_external_names then contains the following code:

  method CHANGE_EXTERNAL_NAMES.
*&---------------------------------------------------------------------*
*&           Generated code for the MODEL PROVIDER BASE CLASS          &*
*&                                                                     &*
*&  !!!NEVER MODIFY THIS CLASS. IN CASE YOU WANT TO CHANGE THE MODEL   &*
*&        DO THIS IN THE MODEL PROVIDER SUBCLASS!!!                    &*
*&                                                                     &*
*&---------------------------------------------------------------------*


DATA:
  lo_entity_type        TYPE REF TO /iwbep/if_mgw_odata_entity_typ,            "#EC NEEDED
  lo_complex_type       TYPE REF TO /iwbep/if_mgw_odata_cmplx_type,            "#EC NEEDED
  lo_child_complex_type TYPE REF TO /iwbep/if_mgw_odata_cmplx_type,            "#EC NEEDED
  lo_property           TYPE REF TO /iwbep/if_mgw_odata_property,              "#EC NEEDED
  lo_association        TYPE REF TO /iwbep/if_mgw_odata_assoc,                 "#EC NEEDED
  lo_assoc_set          TYPE REF TO /iwbep/if_mgw_odata_assoc_set,             "#EC NEEDED
  lo_ref_constraint     TYPE REF TO /iwbep/if_mgw_odata_ref_constr,            "#EC NEEDED
  lo_nav_property       TYPE REF TO /iwbep/if_mgw_odata_nav_prop,              "#EC NEEDED
  lo_action             TYPE REF TO /iwbep/if_mgw_odata_action,                "#EC NEEDED
  lo_parameter          TYPE REF TO /iwbep/if_mgw_odata_property,              "#EC NEEDED
  lo_entity_set         TYPE REF TO /iwbep/if_mgw_odata_entity_set.            "#EC NEEDED


* Change the external names for the entity types' properties
   lo_entity_type = model->get_entity_type( iv_entity_name = 'Z0D_FC_NW_C01_Q0001Result' ).      "#EC NOTEXT
   lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_CNTRY' ).      "#EC NOTEXT
   lo_property->set_name( 'CountryKey' ).            "#EC NOTEXT

   lo_entity_type = model->get_entity_type( iv_entity_name = 'Z0D_FC_NW_C01_Q0001Result' ).      "#EC NOTEXT
   lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_CNTRY_T' ).      "#EC NOTEXT
   lo_property->set_name( 'Country' ).            "#EC NOTEXT

   lo_entity_type = model->get_entity_type( iv_entity_name = 'Z0D_FC_NW_C01_Q0001Result' ).      "#EC NOTEXT
   lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_PROD__0D_NW_PRDCT' ).      "#EC NOTEXT
   lo_property->set_name( 'ProductCategoryKey' ).            "#EC NOTEXT

   lo_entity_type = model->get_entity_type( iv_entity_name = 'Z0D_FC_NW_C01_Q0001Result' ).      "#EC NOTEXT
   lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_PROD__0D_NW_PRDCT_T' ).      "#EC NOTEXT
   lo_property->set_name( 'ProductCategory' ).            "#EC NOTEXT
  endmethod.

 

How to reuse existing mappings?

The following description might appy to you if you have created one or more OData services based on redefining Easy Queries and if you have renamed the properties in those services.

When you have an existing OData service based on an Easy Query and if you have performed a renaming of property names and labels you can try to do the following.

  1. Copy the BW query that is flagged as an Easy Query and activate the OData flag instead and clear the EasyQuery flag.
  2. Save your newly created query (here: ZDEMO_AF_ODATA_EPM_01)

As a result an OData Service called ZDEMO_AF_ODATA_EPM_01_SRV will be generated that uses the generic OData provider class CL_NAT_GENERIC_DPC and the generic model provider class CL_NAT_GENERIC_MPC.

  1. Create a new project in SEGW called ZDEMO_AF_ODATA_EPM_01_REDEF
  2. Redefine the OData service ZDEMO_AF_ODATA_EPM_01_SRV

The SEGW project will have a model provider extension class called ZCL_ZDEMO_AF_ODATA_EPM_MPC_EXT.

Here you can redefine the DEFINE method and basically copy the coding of the change_external_names( ) method mentioned above that resides in the SEGW project using redefinition of the original Easy Query.

Please note that you have to replace the name of the entity type. Here we have to replace ‘Z0D_FC_NW_C01_Q0001Result’ with ‘ZDEMO_AF_ODATA_EPM_01Result’. Since the ABAP internal name of the properties are the same the code works with these slight adaptations.

 METHOD define.

    DATA:
      lo_entity_type        TYPE REF TO /iwbep/if_mgw_odata_entity_typ, "#EC NEEDED
      lo_complex_type       TYPE REF TO /iwbep/if_mgw_odata_cmplx_type, "#EC NEEDED
      lo_child_complex_type TYPE REF TO /iwbep/if_mgw_odata_cmplx_type, "#EC NEEDED
      lo_property           TYPE REF TO /iwbep/if_mgw_odata_property, "#EC NEEDED
      lo_association        TYPE REF TO /iwbep/if_mgw_odata_assoc, "#EC NEEDED
      lo_assoc_set          TYPE REF TO /iwbep/if_mgw_odata_assoc_set, "#EC NEEDED
      lo_ref_constraint     TYPE REF TO /iwbep/if_mgw_odata_ref_constr, "#EC NEEDED
      lo_nav_property       TYPE REF TO /iwbep/if_mgw_odata_nav_prop, "#EC NEEDED
      lo_action             TYPE REF TO /iwbep/if_mgw_odata_action, "#EC NEEDED
      lo_parameter          TYPE REF TO /iwbep/if_mgw_odata_property, "#EC NEEDED
      lo_entity_set         TYPE REF TO /iwbep/if_mgw_odata_entity_set. "#EC NEEDED

    super->define(  ).

* Change the external names for the entity types' properties
    lo_entity_type = model->get_entity_type( iv_entity_name = 'ZDEMO_AF_ODATA_EPM_01Result' ). "#EC NOTEXT
    lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_CNTRY' ). "#EC NOTEXT
    lo_property->set_name( 'CountryKey' ).                  "#EC NOTEXT

    lo_entity_type = model->get_entity_type( iv_entity_name = 'ZDEMO_AF_ODATA_EPM_01Result' ). "#EC NOTEXT
    lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_CNTRY_T' ). "#EC NOTEXT
    lo_property->set_name( 'Country' ).                     "#EC NOTEXT

    lo_entity_type = model->get_entity_type( iv_entity_name = 'ZDEMO_AF_ODATA_EPM_01Result'  ). "#EC NOTEXT
    lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_PROD__0D_NW_PRDCT' ). "#EC NOTEXT
    lo_property->set_name( 'ProductCategoryKey' ).          "#EC NOTEXT

    lo_entity_type = model->get_entity_type( iv_entity_name = 'ZDEMO_AF_ODATA_EPM_01Result'  ). "#EC NOTEXT
    lo_property = lo_entity_type->get_property( iv_property_name = 'A0D_NW_PROD__0D_NW_PRDCT_T' ). "#EC NOTEXT
    lo_property->set_name( 'ProductCategory' ).             "#EC NOTEXT
  ENDMETHOD.

 

As a result the service that has been created as a redefinition of the OData Query OData service now has nice property names:

 

The “problem” when using this approach is however that the renaming takes place as a code based implementation and not in the SEGW UI.

Extension of the query

When we extend the underlying query by an additional free characeristic field (we add the Ship-to-Party) we can redefine our service a second time using the option “Extend Current Model”.

In the second screen of the wizard we would then have the option to add the new query field.

The newly added field would then show up in the payload of your OData request.

How to reuse existing mappings and edit property names in Service Builder?

If you want to edit the property names in the Service Builder UI rather then doing the same in the source code of your model provider extension class it would be possible to create a second SEGW project ZDEMO_AF_ODATA_EPM_01_REDEF_2 for each BW query.

In the project ZDEMO_AF_ODATA_EPM_01_REDEF_2 you could use redefinition to redefine the project ZDEMO_AF_ODATA_EPM_01_REDEF.

As you can see the nice property names that have been added to the service ZDEMO_AF_ODATA_EPM_01_REDEF_SRV via code based implementation can be changed via redefinition for the service ZDEMO_AF_ODATA_EPM_01_REDEF_2_SRV.

 

 

 

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andreas Pöschl
      Andreas Pöschl

      Hello Andre,

      thank you for this great blog about ODataQuery and EasyQuery. This helped me starting my development in the right way from the start.

      However I have a question regarding the redefinition of an ODataQuery. I have exposed my Query as an ODataQuery and then redefined this query by using creating a project in service builder. I then redefined my characteristics fields and gave them meaningful names. However I'm not able to filter then anymore on these fields. If I undo the redefinition it is possible to filter on the field, but not on the renamed field. I couldn't find any restriction on this, there I'm wondering why this is not working.

      Best regards,
      Andreas