I have spent good amount of time developing lots of gateway projects using transaction SEGW.
As programmer, I always been curious to know purpose behind the generated runtime artifacts.
And over period of time I learned a way to develop gateway service without SEGW transaction. In this article I would be walk you through
Gateway Service Development without SEGW
Which is not a recommended way; but best for connecting dots between all generated runtime artifacts ( i.e. Model Provider Classes, Data Provider Classes, Model and Service).
Let’s get started..
We will take Sales Order from Enterprise Procurement Model as use case and consume data from SNWD* tables. We want to expose Sales Order data as Odata service thus we will need 2 entities – Sales Order & Sales Order Items and an association between them.
So we can define model as a ABAP class ZODATA_MODEL_CLASS inherited from super class IWBEP/CL_MGW_ABS_MODEL.
First we will create the entities structures as ABAP structures and the entity sets as ABAP table types in Public section for the class.
Save and activate those declarations. You can see them in Types tab as below
Now refine method ‘DEFINE’ to define the entity, entity sets and associations along with it’s annotations.
Copy below code snippet which is self-explanatory in DEFINE Method.
method DEFINE.
"Declarations
Data :
lo_entity_type TYPE REF TO /iwbep/if_mgw_odata_entity_typ,
lo_property TYPE REF TO /iwbep/if_mgw_odata_property,
lo_association TYPE REF TO /iwbep/if_mgw_odata_assoc,
lo_ref_constraint type ref to /iwbep/if_mgw_odata_ref_constr,
lo_assoc_set type ref to /iwbep/if_mgw_odata_assoc_set,
lo_nav_property type ref to /iwbep/if_mgw_odata_nav_prop.
"Define Sales Order Entity
lo_entity_type = model->create_entity_type('SalesOrder').
"Define Properties
lo_property = lo_entity_type->create_property( iv_property_name = 'Id'
iv_abap_fieldname = 'SO_ID').
lo_property->set_is_key( ). "Mark property as entity key
lo_property->set_conversion_exit( 'ALPHA' ). "Specify Conversion Exit
lo_property = lo_entity_type->create_property( iv_property_name = 'BuyerId'
iv_abap_fieldname = 'BUYER_ID').
lo_property = lo_entity_type->create_property( iv_property_name = 'GrossAmount'
iv_abap_fieldname = 'GROSS_AMOUNT').
"Bind Structure
lo_entity_type->bind_structure('ZODATA_MODEL_CLASS=>TS_SALES_ORDER').
"Create Entity Set
lo_entity_type->create_entity_set('SalesOrderCollection').
"Define Sales Order Item Entity
lo_entity_type = model->create_entity_type('SalesOrderItem').
"Define Properties
lo_property = lo_entity_type->create_property( iv_property_name = 'SalesOrderId'
iv_abap_fieldname = 'SO_ID').
lo_property->set_is_key( ). " Mark property as entity key
lo_property = lo_entity_type->create_property( iv_property_name = 'ItemPosition'
iv_abap_fieldname = 'ITEM_POS').
lo_property->set_is_key( ). " Mark property as entity key
lo_property = lo_entity_type->create_property( iv_property_name = 'ProductId'
iv_abap_fieldname = 'PRODUCT_ID').
"Bind Structure
lo_entity_type->bind_structure('ZODATA_MODEL_CLASS=>TS_SALES_ORDER_ITEM').
"Create Entity Set
lo_entity_type->create_entity_set('SalesOrderItemCollection').
"Define association
lo_association = model->create_association( iv_association_name = 'SalesOrderSalesOrderItem'
iv_left_type = 'SalesOrder'
iv_right_type = 'SalesOrderItem'
iv_right_card = 'N'
iv_left_card = '1' ).
"Referencial cardianlity
lo_ref_constraint = lo_association->create_ref_constraint( ).
lo_ref_constraint->add_property( iv_principal_property = 'Id' iv_dependent_property = 'SalesOrderId' ).
"Association Set
lo_assoc_set = model->create_association_set( iv_association_set_name = 'SalesOrderSalesOrderItemAssocSet'
iv_left_entity_set_name = 'SalesOrderCollection'
iv_right_entity_set_name = 'SalesOrderItemCollection'
iv_association_name = 'SalesOrderSalesOrderItem' ).
"Navigation Property
lo_entity_type = model->get_entity_type( iv_entity_name = 'SalesOrder' ).
lo_nav_property = lo_entity_type->create_navigation_property( iv_property_name = 'SalesOrderItemCollection'
iv_association_name = 'SalesOrderSalesOrderItem' ).
endmethod.
Now we will be implementing the data handling logic. So we will create another ABAP class ZODATA_DATA_CLASS inherited from super class /IWBEP/CL_MGW_ABS_DATA
For now we will only implement Odata GET operation for sales order header data.
Refined the method /iwbep/if_mgw_appl_srv_runtime~get_entity and add below code snippet which is self-explanatory in it.
METHOD /iwbep/if_mgw_appl_srv_runtime~get_entity.
CASE iv_entity_name.
WHEN 'SalesOrder'.
*-------------------------------------------------------------------
* Local data definitions
*-------------------------------------------------------------------
DATA :
ls_inputdata TYPE zodata_model_class=>ts_sales_order,
ls_outputdata TYPE bapi_epm_so_header,
li_return TYPE bapiret2_t.
*-------------------------------------------------------------------
* Process Gateway Request + parameters (if any)
*-------------------------------------------------------------------
* Read converted keys for entity using follwing method
* -> This method invokes conversion exit respective to key fields implicitly and converts key values to desired format
CALL METHOD io_tech_request_context->get_converted_keys
IMPORTING
es_key_values = ls_inputdata.
DATA(lv_so_id) = CONV bapi_epm_so_id( ls_inputdata-so_id ).
*-------------------------------------------------------------------
* Perform backend functionality using RFC / Z Function Module / BAPI / Method /...
*-------------------------------------------------------------------
* Read Sales Order data based on SoId
CALL FUNCTION 'BAPI_EPM_SO_GET_DETAIL'
EXPORTING
so_id = lv_so_id
IMPORTING
headerdata = ls_outputdata
TABLES
return = li_return.
*--------------- End of backend functionality ---------------------------------*
*-------------------------------------------------------------------
* Error / Message Handling
*-------------------------------------------------------------------
IF line_exists( li_return[ type = 'E' ] ).
* Raise Exception on error
ELSE.
* On Success - Send back Entity data
ls_inputdata-buyer_id = ls_outputdata-buyer_id.
ls_inputdata-gross_amount = ls_outputdata-gross_amount.
copy_data_to_ref(
EXPORTING
is_data = ls_inputdata
CHANGING
cr_data = er_entity ).
ENDIF.
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
Now we have Model class containing Sales Order Entity definition and Data class containing Read Sales Order logic.
Let’s do the binding of these ABAP classes in Odata Service.
Go to SPRO transaction and perform following configurations
1. Maintain Model
2. Maintain Service
Now let’s register the service using transaction /iwfnd/maint_service
1. Add Service
2. Verify the Odata ICF node is active and the system alias is properly maintained.
We are all set to test the service with SAP Gateway Client.
Verify the metadata for the service
Now let’s perform GET Sales Order Data operation
You can see the sales order data in response.
So much of effort for a simple Sales Order GET operation!!! We could implement the same operation within 5 minutes with Gateway Project created in SEGW transaction.
Now we understand the Generate Runtime Artifacts Button taking care of creating the Model and Data Class along with Model and Service as per framework recommendation making odata developer’s life easy….