Extend the OData services by customizing the generated source code using “Redefine”
functionality in the SAP Gateway Service Builder (Service Builder-transaction
SEGW)
Generated Model Provider Classes- An Overview
When redefining a service, a
new OData service generates a new Model Provider Class (MPC), and a new Data Provider
Class (DPC). The MPC includes the MPC of the source service, and the DPC inherits the
DPC of the source service. The image below depicts the dependency between the
classes:
In the illustration above,
two sets of classes (MPC
A, and DPC
A) are
generated for the source service
A, and another set of classes (MPC
B, and DPC
B) are generated for the target
service
B. While the model represented by MPC A is included in the
MPC B for the redefined service, the DPC generated for the target service is inherited
from the DPC of the source service (
DPC_EXT B inherits from DPC B,
which also inherits from
DPC_EXT A). The model in the redefined
service can be further enhanced in the extension class of the extended service
(
MPC_EXT B). The runtime behavior of the newly added properties,
entities, function imports and associations can be handled in the data provider
extension class of the extended service (
DPC_EXT B).
Use Cases for Redefining Services
This section explains the extensibility
functionality based on specific use cases and an example. In the base service
(
ZSALES_ORDER_EXAMPLE_SRV), there are three entity types
SalesOrder,
SalesOrderItems and
SalesOrderProvider and an association
SalesOrderSalesOrderItems. This service is redefined and the
new properties and entity types are added in the redefined service.
- Use case 1: Adding a new property to an existing entity
- Use case 2: Adding a new entity
- Use case 3: Adding a new Function import
- Use case 4: Adding an association and a navigation property
In the description of the use cases, we refer to the following example service,
ZSALES_ORDER_EXAMPLE, which contains two
entity sets:
- SalesOrderSet: Data of sales orders
(header)
- SalesOrderItemSet: Data of items
ordered
- SalesOrderProviderSet
For this example, you have to extend the source service by creating a new project,
ZEXTEND_SALES_ORDER_EXAMPLE by following
these steps:
- Create a new project
ZEXTEND_SALES_ORDER_EXAMPLE which
is referred to as the target service.
- Right click on the Data Model folder and select option from the context menu. The Wizard Step 1 of 2:
Redefine Service appears.
- In the Select Service region, enter the technical name of
the service you wish to redefine in the Technical Service
Name field. Alternatively, you can also use the input help
available for this field.
Note If the metatdata of the selected service resides
in another system, then select Metadata to be fetched from an
external system in the Target System
for Metadata. On selection of the Metadata to be fetched from an external
system the RFC Destination field becomes editable to select the RFC
destination of the external system. Input help is also available for this
field.
- Click Next to continue. The Wizard Step 2 of 2:
Redefine Service opens.
- Select the required artifacts and click Finish. See
Redefining OData Service (SAP GW) to understand the
artifacts selection logic
Refer Redefining Services cook book for pictorial
explaination.
Use Case 1: Adding a New Property to an Existing Entity
The required
process for adding a new property to your target service,
ZEXTEND_SALES_ORDER_EXAMPLE, depends on how
the service is implemented. In the sections that follow, you find explanations for the
following:
- Service implemented with MOVE command and entity bound to DDIC structure
- Entity bound to a DDIC structure; To identify if the entity is bound by the DDIC
structure, do the following:
- Open the Entity Type to check if it has the ABAP Structure
Type Name assigned to it or
- Open the Define_Entity Name Method in either the
_MPC_EXT or
_MPC from the
Runtime Artifacts folder and check if the
following code snippet is
available
lo_entity_type->bind_structure( iv_structure_name = 'SFLIGHT'
iv_bind_conversions = 'X' ). "#EC NOTEXT
- Entity not bound to a DDIC structure
- The entity in the data model is not connected to a data dictionary
(DDIC) structure
Service implemented with MOVE command and entity bound to
DDIC structureThe section describes the process for extending an entity in a model that is connected to a Data
Dictionary (DDIC) structure. When the connected DDIC structure matches the data
source structure (or its attributes by name), and the service has been
implemented using the
MOVE command,
(either single
MOVE, or
MOVE-CORRESPONDING) to assign a
value to
ER_ENTITY, it is sufficient to
extend the DDIC structure, and to extend the model as described in steps 1 to 3
of the section "The Entity in the Data Model" is connected to a Data Dictionary
Structure without changing the code. Below is an example code for the entity
set,
SALES_ORDER_ITEM Get Entity, where
the
MOVE command is
used,(
MOVE ls_et_order_item TO er_entity, to fill the
er_entity; once the structure is extended, it is
automatically moved in the
code.
METHOD salesorderitemss_get_entity.
*-------------------------------------------------------------
*Data declaration
*-------------------------------------------------------------
DATA lv_sales_order_id TYPE zif_zsales_order_get=>char25.
DATA lv_sales_order_item TYPE zif_zsales_order_get=>char25.DATA et_order_item TYPE zif_zsales_order_get=>zsales_order_item_table.
DATA ls_et_order_item TYPE LINE OF zif_zsales_order_get=>zsales_order_item_table
DATA ls_converted_keys LIKE er_entity.
DATA lv_source_entity_set_name TYPE string.
*-------------------------------------------------------------
*Map the runtime request to the RFC - Only mapped attributes
*-------------------------------------------------------------
*Get all input information from the technical request context object
io_tech_request_context->get_converted_keys(
IMPORTING
es_key_values = ls_converted_keys
).
*Maps key fields to function module parameters
lv_source_entity_set_name = io_tech_request_context->get_source_entity_set_name( ).
lv_sales_order_item = ls_converted_keys-salesorderitempos.
lv_sales_order_id = ls_converted_keys-salesorderid.
*-------------------------------------------------------------
*Call RFC function module
*-------------------------------------------------------------
TRY.
CALL FUNCTION 'ZSALES_ORDER_GET'
EXPORTING
iv_sales_order_item = iv_sales_order_item
iv_sales_order_id = iv_sales_order_id
IMPORTING
et_order_item = et_order_item
EXCEPTIONS system_failure = 1000 message
lv_exc_msg
OTHERS = 1002.
*-------------------------------------------------------------------------*
* - Post Backend Call -
*-------------------------------------------------------------------------*
* Map properties from the backend to the SAP Gateway output response structure
* In GetEntity operation, we support only read for the first entry in the response table
READ TABLE et_order_item INTO ls_et_order_item INDEX 1.
MOVE ls_et_order_item TO er_entity.
ENDMETHOD.
Ensure
that, the new property (ABAP field name) name is the same as the name of the data
source attribute.
Note If the service has not been implemented using the MOVE or
MOVE-CORRESPONDING commands, the DPC (extension class) of the extended service
has to be redefined to provide the runtime data for the newly added
properties.
Entity bound to a DDIC
structure
You enhance the structure by adding a new
attribute to the DDIC structure. For the new attribute, you must create a new
property in the specific entity of the model.
Prerequisites: The DDIC can be enhanced.
Do
the following to extend an entity in a model that is connected to a DDIC
structure:
- Follow these steps to add a new field to the DDIC structure
- Enter the transaction SE11,
and choose Data Type, and then enter the name
of the structure you want to enhance
- Click Display. In our example, the structure
is, ZSALES_ORDER_ITEM
- In the Dictionary: Maintain Structure screen,
click GoTo in the menu bar, and select
Append Structure (F5) to create the
append structure with the additional fields. If you have already
appended to the structure you can extend it. For example, we created
an append structure called, ZVALUE, and added
fields NETVALUE and CURRENCY,
to it.
- When you add the fields to the structure, rename the fields using
your own suffix or prefix to prevent naming conflicts.
- Add a new property for the new field to the entity of the model in
the service builder. In the target service, add the new property to
entity of the model and save it. In our example, we added the
fields, NetValue and
Currency, to the entity type,
SALESORDER.
- Save and generate the project for the target service. The new
classes of the target service are generated.
- To change the implementation in DPC, update the code for the methods
of the specific extended entity in the DPC (extension) class for the
target service,
ZEXTEND_SALES_ORDER_EXAMPLE.
To update the methods, you can use one of the following options:
- Redefine the methods for the Create,
Read, Update,
Delete, Query
(CRUDQ) operations of the specific Entity.
Copy the code from the original method and update it by
providing the additional fields.
- Call the super class and add the additional fields in your
code. If the service has been implemented using SAP tools,
such as, Explicit Enhancement Point or BADI, you can use it
instead of redefining the class method.
Note Conversion Exits work without any code change for the
newly added properties.
Entity not Bound to a DDIC Structure
The following is the process for
extending an entity in a model that is not connected to a DDIC structure:
- Add a new property to the entity type and generate the service,
ZEXTEND_SALES_ORDER_EXAMPLE. In our
example, we added a new property, Supplier, to the entity
type, SALESORDER.
- Redefine the dispatching methods (methods that route to the type CRUDQ methods)
of the operations:
- Open the DPC extension class of the target service,
ZEXTEND_SALES_ORDER_EXAMPLE, and
redefine the dispatching methods for Create, Read, Update, and Query (CRUQ)
operations for the extended entity:
- /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITY
-
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_ENTITY
- /IWBEP/IF_MGW_APPL_SRV_RUNTIME~UPDATE_ENTITY
- /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET
- For the dispatching method of each operation, enhance the code for the extended
entity set and call the super method for all other entities.
Optional: To be consistent with SAP development, follow
the next step and build the typed methods, and in the dispatching method route to
the typed methods
- Copy the typed methods for the CRUDQ operations that have been assigned to
the entity set you want to extend.
- Example of method names for the operations:
- Provide a new name, by adding a suffix or prefix, such as, _EXT. In
the example, we copied the methods in the source service,
ZSALES_ORDER_EXAMPLE, to the new methods in the target service, and
added the suffix, _EXT.
- Update the method interfaces with the model provider class (MPC extension)
types in your new project.
- Once you have the new methods, you can update their interfaces.
Note The new
methods are not inherited; therefore you can update their interfaces.
For each method, copy the type structure in the MPC extension class of
the source service, ZSALES_ORDER_EXAMPLE, and replace the type structure
in the MPC extension class in the target service,
ZEXTEND_SALES_ORDER_EXAMPLE .
Make changes to the methods of the operations as follows:
- Change type of ER_ENTITY in CREATE
operation:
- In the source service,
ZSALES_ORDER_EXAMPLE,
the MPC extension class displays,
ZCL_ZSALES_ORDER_EXAMP_MPC=>TS_SALESORDER.
- In the target service,
ZEXTEND_SALES_ORDER_EXAMPLE,
edit the MPC extension class
to,ZCL_ZEXTEND_SALES_ORDE_MPC=>TS_SALESORDER.
- DELETE operation: No changes are required for this
operation.
- In the source service, ZSALES_ORDER_EXAMPLE, the MPC extension class
displays as, ZCL_ZSALES_ORDER_EXAMP_MPC=>TS_SALESORDER
- In the target service, ZEXTEND_SALES_ORDER_EXAMPLE, edit the MPC
extension class to, ZCL_ZEXTEND_SALES_ORDE_MPC=>TS_SALESORDER
- Change type of ER_ENTITY in READ
(GET_ENTITY) operation.
- In the source service,
ZSALES_ORDER_EXAMPLE,
the MPC extension class displays as,
ZCL_ZSALES_ORDER_EXAMP_MPC=>TS_SALESORDER.
- In the target service,
ZEXTEND_SALES_ORDER_EXAMPLE,
edit the MPC extension class
to,ZCL_ZEXTEND_SALES_ORDE_MPC=>TS_SALESORDER.
- Change type of ER_ENTITYSET in QUERY
(GET_ENTITYSET) operation.
- In the source service,
ZSALES_ORDER_EXAMPLE,
the MPC extension class displays as,
ZCL_ZSALES_ORDER_EXAMP_MPC=>TT\_SALESORDER.
- In the target service,
ZEXTEND_SALES_ORDER_EXAMPLE,
edit the MPC extension class
to,ZCL_ZEXTEND_SALES_ORDE_MPC=>TT_SALESORDER.
- Change type of ER_ENTITY in UPDATE
operation.
- In the source service,
ZSALES_ORDER_EXAMPLE,
the MPC extension class displays as,
ZCL_ZSALES_ORDER_EXAMP_MPC=>TT_SALESORDER.
- In the target service,
ZEXTEND_SALES_ORDER_EXAMPLE,
edit the MPC extension class
to,ZCL_ZEXTEND_SALES_ORDE_MPC=>TT_SALESORDER.
- Update the code in the methods, and provide the additional fields. You have
two main options to update the code. The option you choose depends on the
logic you want to implement:
- Call the original method of the entity operation; and then provide
the code for the additional field.
- Copy the code for the method of the specific Entity Set, and the
specific operation, from the original method; and update the code
for the additional fields.
If you choose to implement the first option, you have to use SAP code
with your own code for the additional fields. The disadvantage is that, it
you may call the backend twice; once for the SAP provided fields, and then
again for the additional fields.
Redefine the Dispatching MethodsThe
next process is to redefine each dispatching method in the DPC (extension)
class. There are typed methods with MPC type, and dispatching methods. At
runtime the dispatching methods, one method per each CRUDQ operation, are called
with a generic interface that dispatches the call to specific typed methods. The
specific call is based on the Entity Set name. In each dispatch method, verify
that the specific entity is the extended entity, and then route the entity to
the new methods, if not, route it to a super dispatching method.
Below is an example code for Get Entity:
METHOD /iwbep/if_mgw_appl_srv_runtime~get_entity.
DATA salesorderset_get_entityset
TYPE zcl_zextend_sales_orde_mpc=>ts_salesorder.
DATA lv_entityset_name TYPE string.
DATA lr_entity TYPE REF TO data.
lv_entityset_name = io_tech_request_context->get_entity_set_name( ).
CASE lv_entityset_name.
*------------------------------------------------------------------------- *
* EntitySet - SalesOrderSet
*-------------------------------------------------------------------------
* WHEN 'SalesOrderSet'.
* Call the entity set generated method
salesorderset_get_ent_ext(
EXPORTING iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
it_key_tab = it_key_tab
it_navigation_path = it_navigation_path
io_tech_request_context = io_tech_request_context
IMPORTING er_entity = salesorderset_get_entityset ).
IF salesorderset_get_entityset IS NOT INITIAL.
* Send specific entity data to the caller interface
copy_data_to_ref(
EXPORTING
is_data = salesorderset_get_entityset
CHANGING
cr_data = er_entity ).
ELSE.
* In case of initial values - unbind the entity reference er_entity = lr_entity.
ENDIF.
*-------------------------------------------------------------------------*
* Other enteties => call SAP model
*-------------------------------------------------------------------------
WHEN OTHERS.
TRY.
CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~get_entity
EXPORTING
iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
it_key_tab = it_key_tab it_navigation_path = it_navigation_path
io_tech_request_context = io_tech_request_context
IMPORTING
er_entity = er_entity.
CATCH /iwbep/cx_mgw_busi_exception.
* todo
CATCH /iwbep/cx_mgw_tech_exception.
* todo
ENDTRY.
ENDCASE.
ENDMETHOD.
Use Case 2: Adding a New Entity
The following are the processes for adding a new entity to extend the OData service:
- In your target service,
ZEXTEND_SALES_ORDER_EXAMPLE,
create and add the new entity (Products), and then generate the
project.
- Manually create new methods for the CRUDQ operations you require for the
newly created entity. You can copy existing methods generated for another
entity and use it to update your new entity, and add the relevant code.
- Make sure to change the Associated type of the Method Parameters of the
newly created methods.
- Redefine the dispatching method.
The dispatching methods are inherited from the DPC
source service, and these methods do not recognize the new entity;
therefore you must redefine these methods in your target
service.
METHOD /iwbep/if_mgw_appl_srv_runtime~get_entityset.
DATA productsset TYPE zcl_zextend_sales_orde_mpc=>tt_products.
DATA lv_entityset_name TYPE string.
DATA lr_entity TYPE REF TO data.
lv_entityset_name = io_tech_request_context->get_entity_set_name( ).
CASE lv_entityset_name.
*------------------------------------------------------------------------- *
* entityset - productsset
*-------------------------------------------------------------------------
WHEN 'ProductsSet'.
* call the entity set generated method
productsset_get_entityset(
EXPORTING iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
it_filter_select_options = it_filter_select_options
it_order = it_order
is_paging = is_paging
it_key_tab = it_key_tab
it_navigation_path = it_navigation_path
iv_filter_string = iv_filter_string
iv_search_string = iv_search_string
io_tech_request_context = io_tech_request_context
IMPORTING et_entityset = productsset ).
IF productsset IS NOT INITIAL.
copy_data_to_ref(
EXPORTING
is_data = productsset
CHANGING
cr_data = er_entityset ).
ELSE.
* in case of initial values
ENDIF.
WHEN OTHERS.
TRY.
CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~get_entityset
EXPORTING
iv_entity_name = iv_entity_name
iv_entity_set_name = iv_entity_set_name
iv_source_name = iv_source_name
it_filter_select_options = it_filter_select_options
it_order = it_order
is_paging = is_paging
it_key_tab = it_key_tab
it_navigation_path = it_navigation_path
iv_filter_string = iv_filter_string
iv_search_string = iv_search_string
io_tech_request_context = io_tech_request_context
IMPORTING
er_entityset = er_entityset.
CATCH /iwbep/cx_mgw_busi_exception.
* todo
CATCH /iwbep/cx_mgw_tech_exception.
* todo
ENDTRY.
ENDCASE.
ENDMETHOD.
Use Case 3: Adding a New Function Import
The following are the enhancement
processes for extending an OData service by adding a new function import to the data
model:
- Add a new function import into the model.
- Manually redefine the function import
method,</IWBEP/IF_MGW_CORE_SRV_RUNTIM
=>EXEC_SERVICE_OPERATION>, and write your own
code for the newly added function import and call the super class
</IWBEP/IF_MGW_CORE_SRV_RUNTIM
=>EXEC_SERVICE_OPERATION> method for the function
imports inherited from the base service
Use Case 4: Adding an Association and a Navigation Property
The following
are the enhancement processes for extending an OData service by adding an association
and a navigation property:
- In the target service, add the new association, navigation property, and
referential constraint to the data model.
- Update the code in the query and read operations of the target entity.
Boundary Conditions
The following are the enhancement processes for extending an OData service by adding
a new function import to the data model:
- In the redefined service, RFC mapping editor cannot be used for DPC
generation.
- If your entity is bound to a structure in the base service, it should not be
bound to the new structure in the redefined service.
- Redefining a composed service is not supported.
- DIC binding is not supported when the Backend system is different from the
IW_BEP &
IW_FND system.
- If an entity is bound to a DDIC structure, the abap type of the property
cannot be modified from the ABAP type editor in SEGW.
- Redefining a service from another BEP system is not supported.