Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
yavuzasik
Participant
Firstly, the requirement of this post was originated from quite a basic problem; however it later became really complicated due to the following constraints which we were restricted to.

  • technical constraints of ABAP CDS object

  • SAP system constraints in terms of the technology stack and version


Let me first talk about the actual requirement and then I will write down all the possible solutions I tried out and why I ended up with the current one. Our initial requirement was to expose an SAP field with OData and consume it from a Fiori application. This field was the well-known WBS element field, which is a concatenation of a couple of other fields separated by a '-' symbol. Of course, I was supposed to split this field into different strings and extract the components of the original field. It might sound like a problem with a quite straightforward solution. However once I started researching to find out the possibilities, it was quite frustrating.

Of course, I started with the CDS built-in functions. I have checked them and find out a couple of useful functions including "instr", "substring", "left" etc. However, none of them has completely resolved our problem without certain assumptions (making an assumption on the number of characters for each part of the string for instance). Therefore, unfortunately there is no built-in function, which we could utilize to split up a string into multiple strings at a certain character, '-' in our case.

Second option I came up with was to use some of the powerful tools in ABAP stack, for instance, CDS table function or AMDB, that I can plug our custom ABAP code. That way, I could enhance/enrich our CDS object with some custom ABAP coding, which contains the ABAP command SPLIT ... AT ... INTO ...
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Demo Table Function Parse'
@ClientDependent: false
define table function Z_DEMO_TF_PARSE_WBS
returns {
wbs_element : string40 ,
component1 : string10 ,
component2 : string10 ,
component3 : string10 ,
}
implemented by method
Z_Cl_AMDP_PARSE_STRING=>SPLIT;

That way I planned to implement the parsing of the WBS string with custom Z_Cl_AMDP_PARSE_STRING class. Unfortunately, that also did not work out because our system had a SAP_ABA 750-0010 component version, which this feature is not yet supported.

The final option I could think of was to manually add an extra implementation into the OData runtime artifacts, which was generated by adding the CDS as a reference object to the SEGW service.

I did that extra implementation inside the data provider extension class. In order to implement the parsing of WBS field, I should have first created dummy fields in my CDS object, which was only possible with the CAST command. Hence, I extended my CDS view with the three field from the result of parsing.
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@AbapCatalog.preserveKey: true
@EndUserText.label: 'Demo CDS Parse'
@VDM.viewType: #BASIC

define view Z_DEMO_CDS_PARSE_WBS as select from prps
{
key wbs_element ,
cast(' ' as abap.char(3) ) as component1 ,
cast(' ' as abap.char(10) ) as component2 ,
cast(' ' as abap.char(8) ) as component3
}

Afterwards I started to overwrite some of the methods of the DPC_EXT class, which were necessary for my requirement. For instance I implemented the custom logic to split the WBS by overwriting the GET_ENTITYSET method of the respective CDS entity. This method already has a reference to the super method inherited from DPC class. Because the SEGW service was built on top of the reference to the data source which points to the CDS view. I preserved it and finally added my extra code to split the WBS element and hence the returned entity set is updated.
  METHOD Z_DEMO_CDS_PARSE_WBS_GET_ENTITY_SET.
TRY.
CALL METHOD super->Z_DEMO_CDS_PARSE_WBS_GET_ENTITY_SET
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
is_paging = is_paging
it_key_tab = it_key_tab
it_navigation_path = it_navigation_path
it_order = it_order
iv_filter_string = iv_filter_string
iv_search_string = iv_search_string
io_tech_request_context = io_tech_request_context
IMPORTING
et_entityset = et_entityset
es_response_context = es_response_context.
CATCH /iwbep/cx_mgw_busi_exception .
CATCH /iwbep/cx_mgw_tech_exception .
ENDTRY.

LOOP AT et_entityset REFERENCE INTO DATA(lr_entityset).
SPLIT lr_entityset->wbs_element AT '-' INTO lr_entityset->component1
lr_entityset->component2
lr_entityset->component3.

ENDLOOP.

ENDMETHOD.

I want to emphasize a few points what I have learned from the solution of this issue.

  • Whenever CDS toolset is not adequate for my requirement , I can still use CDS to expose data by referencing it as data source and then exploit the DPC_EXT class to implement own coding. This makes it a hybrid solution whereas on one hand, I can take advantage of CDS features (performance, annotations etc.) and on the other hand, I can still make manual interventions to the entity set that I expose through OData by overwriting the related DPC_EXT class methods.

  • Second thing is that CAST operator is the only option to create dummy fields since CDS is not a database object but actually a view on real database objects. This could be its side role in addition to its actual role, which is casting some data types into some other types.


 
10 Comments
Labels in this area