How to move from Easy Queries to OData Queries

I recently got the question whether it is possible to extend an OData service that has been created via redefinition based on an Easy Query.

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

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.

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

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.

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.

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.

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.