BITI: Building Services for SAP Gateway
Graham Robinson
Yelcho Systems Consulting
INTRODUCTION
@grahamrobbo
*Photo by Martin Gillet
AGENDA
• Some Warnings
• Service Design
• Code patterns for reusability
• Code patterns for extensibility
AGENDA
• Some Warnings
• Service Design
• Code patterns for reusability
• Code patterns for extensibility
WARNING – THIS IS NOT FOR BEGINNERS
WARNING - HOMEWORK
[Link]
To install you will also need abapGit
[Link]
WARNING – FOCUS ON CONSUMPTION
These code patterns can apply to all actions – but I will focus on consumption
GET_ENTITYSET is more complex because it needs to supports oData query options
CDS views (NW 7.40 SP8) provide other consumption options
WARNING – I DO NOT HAVE ALL THE ANSWERS
AGENDA
• Some Warnings
• Service Design
• Code patterns for reusability
• Code patterns for extensibility
SERVICE DESIGN PRINCIPLES
• Design for Consumers
• Think oData i.e. Entities, Associations, etc.
• Leave SAP domain knowledge at the door
• REST API’s should be self-describing
• Function Imports should be for special cases
GENERAL THEORY OF API DESIGN
CONSUMER VIEW OF API
Source: [Link]
BIND ENTITY TO DDIC STRUCTURE
BIND ENTITY TO DDIC STRUCTURE
BIND ENTITY TO DDIC STRUCTURE
BIND ENTITY TO DDIC STRUCTURE
BIND ENTITY TO DDIC STRUCTURE
Remove
label
suggestions
This means labels are determined at runtime rather than design-time
$METADATA
DATES & TIMES
Use [Link] for date/time/timestamp properties
Don’t be tempted to use [Link] “for convenience”
[Link] replaced in oData V4 specification
AGENDA
• Some Warnings
• Service Design
• Code patterns for reusability
• Code patterns for extensibility
CODE PATTERNS FOR REUSABILITY
WHAT A CLASS IS NOT
An ABAP class that only contains static methods
is not really a class…..
… in all respects except object type it is a...
Function Group
CODE PATTERNS FOR REUSABILITY
CODE PATTERNS FOR REUSABILITY
• I like the singleton design pattern in ABAP
– Be aware that some people don’t
– I don’t care – it works for me
• I like getters (& sometimes setters)
– Be aware that some people don’t
– I don’t care – it works for me
You can implement business logic however you like…
just remember the first & second rules of reusability
SAMPLE DATA MODEL
Based upon SAP Enterprise Procurement Model
DATA PROVIDER CLASS
DPC
Class
MULTIPLE CONSUMERS
DPC DPC DPC
Class
MULTIPLE CONSUMERS
DPC DPC DPC
Common Interface
Class
REPLICATE GW METHOD INTERFACE
AVOID USING DEPRECATED PARAMETERS
[Link]
Nabi Zamani
COMMON INTERFACE
Model
Message Container
Untyped data object
ZCL_GW_MODEL
DPC->GET_MODEL
CALL BO CLASS FROM DPC
ODATA OPERATIONS
Identify Instantiate Call class Fill Entity
Primary Key(s) Class methods
Create
Read
Update
Delete
GET_ENTITY
• Identify primary key(s)
• Instantiate BO class
• Fill entity
GET_ENTITY V1
GET_ENTITY V1 – IDENTIFY PRIMARY KEY
GET_ENTITY V1 – INSTANTIATE BO CLASS
GET_ENTITY V1 – FILL ENTITY
GET_ENTITY V2
GET_ENTITY V2
lt_key_tab = io_tech_request_context->get_keys( ).
READ TABLE lt_key_tab
with KEY name = 'BP_ID'
into ls_key.
lv_bp_id = ls_key-value.
lo_customer = zcl_demo_customer=>get_using_bp_id( lv_bp_id ).
GET REFERENCE OF er_entity INTO lr_entity.
lo_customer->zif_gw_methods~map_to_entity( lr_entity ).
GET_ENTITY V2 – TABLE EXPRESSION
lt_key_tab = io_tech_request_context->get_keys( ).
lv_bp_id = lt_key_tab[ name = 'BP_ID' ]-value.
lo_customer = zcl_demo_customer=>get_using_bp_id( lv_bp_id ).
GET REFERENCE OF er_entity INTO lr_entity.
lo_customer->zif_gw_methods~map_to_entity( lr_entity ).
GET_ENTITY V2 – CONVERSION OPERATOR
lt_key_tab = io_tech_request_context->get_keys( ).
lo_customer = zcl_demo_customer=>get_using_bp_id(
CONV #( lt_key_tab[ name = 'BP_ID' ]-value ) ).
GET REFERENCE OF er_entity INTO lr_entity.
lo_customer->zif_gw_methods~map_to_entity( lr_entity ).
GET_ENTITY V2 – REFERENCE OPERATOR
lt_key_tab = io_tech_request_context->get_keys( ).
lo_customer = zcl_demo_customer=>get_using_bp_id(
CONV #( lt_key_tab[ name = 'BP_ID' ]-value ) ).
lo_customer->zif_gw_methods~map_to_entity(
REF #( er_entity ) ).
GET_ENTITY V2
lt_key_tab = io_tech_request_context->get_keys( ).
lo_customer = zcl_demo_customer=>get_using_bp_id(
CONV #( lt_key_tab[ name = 'BP_ID' ]-value ) ).
*--------------------------------------------------------*
* For update operations we would call class methods here *
*--------------------------------------------------------*
lo_customer->zif_gw_methods~map_to_entity(
REF #( er_entity ) ).
GET_ENTITY V2 – METHOD CHAINING
lt_key_tab = io_tech_request_context->get_keys( ).
zcl_demo_customer=>get_using_bp_id(
CONV #( lt_key_tab[ name = 'BP_ID' ]-value )
)->zif_gw_methods~map_to_entity( REF #( er_entity ) ).
ZIF_GW_METHODS~GET_ENTITY
ZIF_GW_METHODS~GET_ENTITY
Exception
handling
ZIF_GW_METHODS~GET_ENTITY
Use salesorder
key to get
customer
MAP_TO_ENTITY
MAP_TO_ENTITY
CALL_ALL_GETTERS
For each entity component we attempt
to call matching getter functional method
e.g <entity>-prop1 = me->get_prop1( ).
GET_ENTITYSET
Just like GET_ENTITY in a loop…except…
ODATA QUERY OPTIONS
ODATA QUERY OPTIONS
KNOWN CONSTRAINTS
SAP Note 1574568
ZIF_GW_METHODS~GET_ENTITYSET
Goal is to identify primary key(s) as quickly as
possible and use them to fill entities.
ZIF_GW_METHODS~GET_ENTITYSET
• Create anonymous data object
• $orderby
• $filter
• $inlinecount
• $top & $skip
• $count
• $skiptoken
• Fill entities
CREATE ANONYMOUS DATA OBJECT
$ORDERBY
$ORDERBY
$FILTER
$FILTER
COMPLEX $FILTER QUERIES
$filter=substringof(‘Gold’,Name) or substringof(‘Johan’,City)
*Note where_clause may require modification e.g. Table aliases, etc.
$INLINECOUNT
$INLINECOUNT
$INLINECOUNT
$TOP & $SKIP
$TOP & $SKIP
$COUNT
$COUNT
$SKIPTOKEN
$SKIPTOKEN
$SKIPTOKEN
FILL ENTITIES
WHERE IS THE CODE?
[Link]
To install you will also need abapGit
[Link]
AGENDA
• Some Warnings
• Service Design
• Code patterns for reusability
• Code patterns for extensibility
CODE PATTERNS FOR EXTENSIBILITY
• Mainline code built on central development
server
• Mainline code deployed to customer system
via abapGit
• Need to be able to add customer-specific code
without changing mainline code
BO CLASS SUBCLASS
New methods
or redefine
existing
methods
BO CLASS INSTANTIATION
BO CLASS INSTANTIATION
DPC & MPC CLASSES
DPC & MPC SUBCLASSES
MAINTAIN GW MODELS & SERVICES
/IWBEP/R_DST_MODEL_BUILDER
/IWBEP/R_DST_SERVICE_BUILDER
EXTEND GW SERVICE
• Create or Enhance DDIC structure
• Enhance model definition in MPC
• Add code to fill new entities/properties
ENHANCE DDIC STRUCTURE
ENHANCE MODEL
FILL NEW PROPERTY
SUMMARY
• Service Design
– Design for consumers
• Code patterns for reusability
– The first & second rule
• Code patterns for extensibility
WHERE IS THE CODE?
[Link]
To install you will also need abapGit
[Link]
@grahamrobbo
Photo by Frank Hurley – used with permission
THANK YOU
Thank you for your time