Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
mykola_tokariev2
Explorer
3,320


 

In this article I will show an approach to declare OData entities dynamically.

Why?


In case we should change an business logic types and don't want to change the OData service.

How?


Declare OData entities dynamically.

Contra?


It is more difficult to find the error if something wrong with OData service.

Pro?


It is fast.

In standard case before we start to use OData service we should declare entity types. Basically this is a mapping between business logic types and entity that will be shown for the outside world. In case business logic was changed we should also change the mapping.

Its takes a lot of time especially at the start, where any entities where declared yet. You can see a mapping example below:
METHOD define_dga_in.
TRY.
DATA(entity_type) = model->create_entity_type( iv_entity_type_name = zif_business_logic_types=>entity_in
iv_def_entity_set = abap_false ).

properties = VALUE #( ( key = abap_true property = zif_business_logic_types=>prop_plant abap = zif_business_logic_types=>field_plant )
( key = abap_false property = zif_business_logic_types=>prop_tu_number abap = zif_business_logic_types=>field_tu_number )
( key = abap_true property = zif_business_logic_types=>prop_matnr abap = zif_business_logic_types=>field_matnr )
( key = abap_false property = zif_business_logic_types=>prop_batch_nr abap = zif_business_logic_types=>field_batch_nr )
( key = abap_false property = zif_business_logic_types=>prop_bbdate abap = zif_business_logic_types=>field_bbdate )
( key = abap_false property = zif_business_logic_types=>prop_brutto abap = zif_business_logic_types=>field_brutto )
( key = abap_false property = zif_business_logic_types=>prop_netto abap = zif_business_logic_types=>field_netto )
( key = abap_false property = zif_business_logic_types=>prop_tagew abap = zif_business_logic_types=>field_tagew )
( key = abap_false property = zif_business_logic_types=>prop_gewei abap = zif_business_logic_types=>field_gewei )
( key = abap_false property = zif_business_logic_types=>prop_menge abap = zif_business_logic_types=>field_menge )
( key = abap_false property = zif_business_logic_types=>prop_meins abap = zif_business_logic_types=>field_meins )
( key = abap_false property = zif_business_logic_types=>prop_dmeng abap = zif_business_logic_types=>field_dmeng )
( key = abap_false property = zif_business_logic_types=>prop_dmein abap = zif_business_logic_types=>field_dmein )
( key = abap_false property = zif_business_logic_types=>prop_aufnr abap = zif_business_logic_types=>field_aufnr )
( key = abap_false property = zif_business_logic_types=>prop_qplos abap = zif_business_logic_types=>field_qplos )
( key = abap_false property = zif_business_logic_types=>prop_lgort abap = zif_business_logic_types=>field_lgort )
( key = abap_false property = zif_business_logic_types=>prop_text abap = zif_business_logic_types=>field_text )
( key = abap_false property = zif_business_logic_types=>prop_mess abap = zif_business_logic_types=>field_mess )
( key = abap_false property = zif_business_logic_types=>prop_extnr abap = zif_business_logic_types=>field_extnr ) ).

create_properties( entity_type ).

entity_type->bind_structure( iv_structure_name = 'zif_business_logic_types=>in' ).

entity_type->get_property( zif_business_logic_types=>prop_bbdate )->set_nullable( abap_true ).
entity_type->get_property( zif_business_logic_types=>prop_bbdate )->set_type_edm_string( ).

entity_type->get_property( zif_business_logic_types=>prop_gewei )->disable_conversion( ).
entity_type->get_property( zif_business_logic_types=>prop_meins )->disable_conversion( ).
entity_type->get_property( zif_business_logic_types=>prop_dmein )->disable_conversion( ).


DATA(entity_set) = entity_type->create_entity_set( zif_business_logic_types=>entityset_dga_in ).
entity_set->set_addressable( abap_true ).
entity_set->set_pageable( abap_true ).
entity_set->set_filter_required( abap_false ).
CATCH /iwbep/cx_mgw_med_exception INTO DATA(mgw_error).
RAISE EXCEPTION mgw_error.
CATCH /usi/cx_odata.
ENDTRY.
ENDMETHOD.

The same result we can achieve with dynamic declaration of entity.
METHOD define_optional_material.
DATA: data TYPE zif_business_logic_types=>optional_material.

TRY.
DATA(entity_type) = model->create_entity_type( iv_entity_type_name = zif_business_logic_types=>entity_optional_material iv_def_entity_set = abap_false ).

structure ?= cl_abap_typedescr=>describe_by_data( data ).
components = structure->components.

LOOP AT components INTO DATA(comp).
DATA(pop_entry) = _create_pop_entry( comp ).

CASE pop_entry-abap.
WHEN 'EBORT'. pop_entry-key = abap_true.
ENDCASE.

APPEND pop_entry TO properties.
ENDLOOP.

create_properties( entity_type ).

entity_type->bind_structure( iv_structure_name = CONV #( structure->absolute_name ) ).

DATA(entity_set) = entity_type->create_entity_set( zif_business_logic_types=>entityset_optional_material ).
entity_set->set_filter_required( abap_false ).
CATCH /iwbep/cx_mgw_med_exception INTO DATA(mgw_error).
RAISE EXCEPTION mgw_error.
CATCH /usi/cx_odata.
ENDTRY.

CLEAR properties.
ENDMETHOD.

The method _create_prop_entry( comp ) get a component of the structure, that we use in business logic and create properties for the entity. The definition looks like this:
  METHOD _create_pop_entry.
DATA prop_name TYPE char40.

prop_name = `prop_` && i_comp-name.

ASSIGN zif_business_logic_types=>(prop_name) TO FIELD-SYMBOL(<prop_value>).
IF <prop_value> IS ASSIGNED.
r_result-key = abap_false.
r_result-property = <prop_value>.
r_result-abap = i_comp-name.
ENDIF.

ENDMETHOD.

In this case all what we need it is a global declaration of property names. In this case I use an interface for types declaration.




CONSTANTS:
prop_ebort TYPE char40 VALUE 'InstallationPointForSubitem',
prop_upmng TYPE char40 VALUE 'SubitemQuantity',
prop_uptxt TYPE char40 VALUE 'BOMSubitemText'.

That's all. I hope you got the point.

Summary:


The biggest advantage of this approach you can see if you need to change something in your types. All what you need it is add some new types to you structure and description like as shown above. Your OData service will adapt automatically. Don't forget to inform your UI colleges about the changes 🙂
Labels in this area