how to... build odata services using sap gateway

46
SAP How-to Guide Mobility SAP Mobile Platform Applicable Releases: SAP Mobile Platform 3.0 SAP Gateway 2.0, SP07 Version 1.0 June 2015 How To... Build OData Services Using SAP Gateway

Upload: aresrea11

Post on 10-Feb-2016

185 views

Category:

Documents


26 download

DESCRIPTION

SAP OData service

TRANSCRIPT

   

 

SAP How-to Guide Mobility    SAP  Mobile  Platform  

Applicable Releases:

SAP Mobile Platform 3.0

SAP Gateway 2.0, SP07

Version 1.0

June 2015

How To... Build OData Services Using SAP Gateway

 

 

©  Copyright  2015  SAP  AG.  All  rights  reserved.  

No  part  of  this  publication  may  be  reproduced  or  transmitted  in  any  form  or  for  

any  purpose  without  the  express  permission  of  SAP  AG.  The  information  

contained  herein  may  be  changed  without  prior  notice.    

Some  software  products  marketed  by  SAP  AG  and  its  distributors  contain  

proprietary  software  components  of  other  software  vendors.    

Microsoft,  Windows,  Excel,  Outlook,  and  PowerPoint  are  registered  trademarks  of  

Microsoft  Corporation.    

IBM,  DB2,  DB2  Universal  Database,  System  i,  System  i5,  System  p,  System  p5,  

System  x,  System  z,  System  z10,  System  z9,  z10,  z9,  iSeries,  pSeries,  xSeries,  

zSeries,  eServer,  z/VM,  z/OS,  i5/OS,  S/390,  OS/390,  OS/400,  AS/400,  S/390  Parallel  

Enterprise  Server,  PowerVM,  Power  Architecture,  POWER6+,  POWER6,  POWER5+,  

POWER5,  POWER,  OpenPower,  PowerPC,  BatchPipes,  BladeCenter,  System  

Storage,  GPFS,  HACMP,  RETAIN,  DB2  Connect,  RACF,  Redbooks,  OS/2,  Parallel  

Sysplex,  MVS/ESA,  AIX,  Intelligent  Miner,  WebSphere,  Netfinity,  Tivoli  and  

Informix  are  trademarks  or  registered  trademarks  of  IBM  Corporation.    

Linux  is  the  registered  trademark  of  Linus  Torvalds  in  the  U.S.  and  other  countries.    

Adobe,  the  Adobe  logo,  Acrobat,  PostScript,  and  Reader  are  either  trademarks  or  

registered  trademarks  of  Adobe  Systems  Incorporated  in  the  United  States  and/or  

other  countries.    

Oracle  is  a  registered  trademark  of  Oracle  Corporation.    

UNIX,  X/Open,  OSF/1,  and  Motif  are  registered  trademarks  of  the  Open  Group.    

Citrix,  ICA,  Program  Neighborhood,  MetaFrame,  WinFrame,  VideoFrame,  and  

MultiWin  are  trademarks  or  registered  trademarks  of  Citrix  Systems,  Inc.    

HTML,  XML,  XHTML  and  W3C  are  trademarks  or  registered  trademarks  of  W3C®,  

World  Wide  Web  Consortium,  Massachusetts  Institute  of  Technology.    

Java  is  a  registered  trademark  of  Sun  Microsystems,  Inc.    

JavaScript  is  a  registered  trademark  of  Sun  Microsystems,  Inc.,  used  under  license  

for  technology  invented  and  implemented  by  Netscape.    

SAP,  R/3,  SAP  NetWeaver,  Duet,  PartnerEdge,  ByDesign,  SAP  BusinessObjects  

Explorer,  StreamWork,  and  other  SAP  products  and  services  mentioned  herein  as  

well  as  their  respective  logos  are  trademarks  or  registered  trademarks  of  SAP  AG  

in  Germany  and  other  countries.    

Business  Objects  and  the  Business  Objects  logo,  BusinessObjects,  Crystal  Reports,  

Crystal  Decisions,  Web  Intelligence,  Xcelsius,  and  other  Business  Objects  products  

and  services  mentioned  herein  as  well  as  their  respective  logos  are  trademarks  or  

registered  trademarks  of  Business  Objects  Software  Ltd.  Business  Objects  is  an  

SAP  company.  

Sybase  and  Adaptive  Server,  iAnywhere,  Sybase  365,  SQL  Anywhere,  and  other  

Sybase  products  and  services  mentioned  herein  as  well  as  their  respective  logos  

are  trademarks  or  registered  trademarks  of  Sybase,  Inc.  Sybase  is  an  SAP  

company.    

 

All  other  product  and  service  names  mentioned  are  the  trademarks  of  their  

respective  companies.  Data  contained  in  this  document  serves  informational  

purposes  only.  National  product  specifications  may  vary.    

The  information  in  this  document  is  proprietary  to  SAP.  No  part  of  this  document  

may  be  reproduced,  copied,  or  transmitted  in  any  form  or  for  any  purpose  without  

the  express  prior  written  permission  of  SAP  AG.    

This  document  is  a  preliminary  version  and  not  subject  to  your  license  agreement  

or  any  other  agreement  with  SAP.  This  document  contains  only  intended  

strategies,  developments,  and  functionalities  of  the  SAP®  product  and  is  not  

intended  to  be  binding  upon  SAP  to  any  particular  course  of  business,  product  

strategy,  and/or  development.  Please  note  that  this  document  is  subject  to  change  

and  may  be  changed  by  SAP  at  any  time  without  notice.    

SAP  assumes  no  responsibility  for  errors  or  omissions  in  this  document.  SAP  does  

not  warrant  the  accuracy  or  completeness  of  the  information,  text,  graphics,  links,  

or  other  items  contained  within  this  material.  This  document  is  provided  without  a  

warranty  of  any  kind,  either  express  or  implied,  including  but  not  limited  to  the  

implied  warranties  of  merchantability,  fitness  for  a  particular  purpose,  or  non-­‐

infringement.    

SAP  shall  have  no  liability  for  damages  of  any  kind  including  without  limitation  

direct,  special,  indirect,  or  consequential  damages  that  may  result  from  the  use  of  

these  materials.  This  limitation  shall  not  apply  in  cases  of  intent  or  gross  

negligence.    

The  statutory  liability  for  personal  injury  and  defective  products  is  not  affected.  

SAP  has  no  control  over  the  information  that  you  may  access  through  the  use  of  

hot  links  contained  in  these  materials  and  does  not  endorse  your  use  of  third-­‐

party  Web  pages  nor  provide  any  warranty  whatsoever  relating  to  third-­‐party  Web  

pages.    

SAP  “How-­‐to”  Guides  are  intended  to  simplify  the  product  implementtation.  While  

specific  product  features  and  procedures  typically  are  explained  in  a  practical  

business  context,  it  is  not  implied  that  those  features  and  procedures  are  the  only  

approach  in  solving  a  specific  business  problem  using  SAP  NetWeaver.  Should  you  

wish  to  receive  additional  information,  clarification  or  support,  please  refer  to  SAP  

Consulting.  

Any  software  coding  and/or  code  lines  /  strings  (“Code”)  included  in  this  

documentation  are  only  examples  and  are  not  intended  to  be  used  in  a  productive  

system  environment.  The  Code  is  only  intended  better  explain  and  visualize  the  

syntax  and  phrasing  rules  of  certain  coding.  SAP  does  not  warrant  the  correctness  

and  completeness  of  the  Code  given  herein,  and  SAP  shall  not  be  liable  for  errors  

or  damages  caused  by  the  usage  of  the  Code,  except  if  such  damages  were  caused  

by  SAP  intentionally  or  grossly  negligent.  

Disclaimer  

Some  components  of  this  product  are  based  on  Java™.  Any  code  change  in  these  

components  may  cause  unpredictable  and  severe  malfunctions  and  is  therefore  

expressively  prohibited,  as  is  any  decompilation  of  these  components.  

Any  Java™  Source  Code  delivered  with  this  product  is  only  to  be  used  by  SAP’s  

Support  Services  and  may  not  be  modified  or  altered  in  any  way.  

 

 

Document History

Document  Version   Description  

1.00   First  official  release  of  this  guide  

     

 

 

Typographic Conventions

Type  Style     Description  

Example Text Words  or  characters  quoted  from  the  screen.  These  include  field  names,  screen  titles,  pushbuttons  labels,  menu  names,  menu  paths,  and  menu  options.  Cross-­‐references  to  other  documentation  

Example  text   Emphasized  words  or  phrases  in  body  text,  graphic  titles,  and  table  titles  

Example text File  and  directory  names  and  their  paths,  messages,  names  of  variables  and  parameters,  source  text,  and  names  of  installation,  upgrade  and  database  tools.  

Example text User  entry  texts.  These  are  words  or  characters  that  you  enter  in  the  system  exactly  as  they  appear  in  the  documentation.  

<Example text>

Variable  user  entry.  Angle  brackets  indicate  that  you  replace  these  words  and  characters  with  appropriate  entries  to  make  entries  in  the  system.  

EXAMPLE TEXT   Keys  on  the  keyboard,  for  example,  F2  or  ENTER.  

Icons Icon   Description  

  Caution  

  Note  or  Important  

  Example  

  Recommendation  or  Tip  

       

 

 

Table of Contents

1.   Business  Scenario  ..................................................................................................  1  

2.   Background  Information  ........................................................................................  1  

3.   Prerequisites  .........................................................................................................  1  

4.   Step-­‐by-­‐Step  Procedure  .........................................................................................  2  4.1   Option  1  -­‐  Creating  a  Data  Model  by  Importing  the  OData  Model  data  ..........  2  4.2   Option  2  -­‐  Creating  a  Data  Model  by  Importing  DDIC  Structures  ....................  7  4.3   Implementing  Collection  GET  .........................................................................  15  4.4   Implementing  Filters  ......................................................................................  26  4.5   Implement  Entity  Create,  Update,  and  Delete  ...............................................  30  

4.5.1   Implementing  Entity  Create  ...............................................................  31  4.5.2   Implementing  Entity  Update  ..............................................................  36  4.5.3   Implementing  Entity  Delete  ...............................................................  38  

4.6   Implementing  Delta  Token  Support  ...............................................................  40      

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   1  

1. Business Scenario  The  focus  of  this  guide  is  on  the  SAP  backend  or  server  side  process  and  the  completion  of  the  SAP  backend  implementation  to  prepare  the  OData  service  for  exposure  to  the  outside  world.      

2. Background Information For  those  who  are  new  to  the  OData  services  development  with  SAP  Gateway,  here’s  another  H2G:    OData  CRUD  Crash  Course  -­‐  Getting  ready  with  offline  store          The  difference  of  this  document  is:  

-­‐ The  data  source  is  obtained  via  RFC  -­‐ It  covers  $expand,  deep  insert,  and  $filter  

So  this  H2G  is  intended  to  provide  you  another  implementation  example.    

3. Prerequisites In  order  to  execute  the  tasks  described  in  this  How-­‐To  Guide,  the  following  prerequisites  must  be  met.  • SAP  NetWeaver  Gateway  2.0,  SP07  • ABAP  development  knowledge  is  recommended  

Helpful  Information  • Note  1921547  -­‐  How  to  integrate  OData  service  with  standard  exchange  table    

 

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   2  

4. Step-by-Step Procedure This  section  provides  the  detailed  step-­‐by-­‐step  procedure  for  designing  and  developing  an  end-­‐to-­‐end  OData  service. NOTE:  In  the  next  step,  you  can  choose  one  of  the  listed  methods  below  to  create  the  data  model:  

• Option  1  -­‐  Using  an  external  model  file  • Option  2  -­‐  Importing  a  ABAP  DDIC  structure  or  RFC/BOR  interface  In  order  to  remain  compatible  with  the  code  implementation  sections  that  come  later  in  this  specific  guide,  it  is  recommended  to  use  the  “Import  DDIC  Structure”  option  for  creating  the  data  model.    This  is  simply  due  to  naming  differences  in  the  generated  objects  that  results  in  using  the  different  data  model  creation  methods.  

4.1 Option 1 - Creating a Data Model by Importing the OData Model data

 For  Data  model  design  and  creation  of  OData  services,  a  number  of  tools  exist  to  create  the  OData  data  model.    Modeling  can  begin  in  an  external  client  tool  such  as  Microsoft  Visual  Studio  and  the  OData  Modeler  tool.    The  latter  is  free  and  provided  by  SAP  as  a  plugin  for  eclipse.    An  OData  modeler  is  one  of  the  components  provided  in  the  SMP  tool.  Once  the  models  are  created  using  such  external  tools,  the  model  representation  can  be  exported  as  an  EDMX  or  XML  formatted  file.    EDMX  is  an  Entity  Framework  modeling  XML  format  representing  an  Entity  Data  Model.    SAP  Gateway  Service  Builder  can  take  these  files  as  input  and  completely  generate  a  model  implementation  as  well  as  the  shells  for  corresponding  runtime  implementations.  SAP  Gateway  Service  Builder  is  basically  a  design-­‐time  environment  within  the  ABAP-­‐based  SAP  Gateway  system.    It  equips  developers  with  a  project-­‐based  service  design  and  development  tool  and  supports  developers  throughout  the  entire  development  lifecycle  of  an  OData  service.      

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   3  

A  similar  data  model  can  be  created  using  the  OData  modeling  tool  which  can  then  be  used  as  a  basis  to  generate  the  ABAP  runtime  artifacts  on  the  Gateway  system.  

 Figure  :  OData  Modeler  

 But  note  that  using  an  external  model  file  is  just  one  of  the  options  to  use  as  a  basis  for  creating  the  data  model  using  Service  Builder.    Other  options  such  as  leveraging  inherent  ABAP  data  dictionary  structures,  BOR  objects,  and  RFC  interfaces  are  available  as  well.  

Create a New Project Using Service Builder 1. Log  into  your  SAP  NetWeaver  Gateway  system  and  proceed  to  transaction  SEGW.  2. Click  on  the  Create  Project  button  on  the  main  toolbar.  

 

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   4  

 3. On  the  subsequent  Create  Project  dialog,  enter  a  package  you  want  to  use  for  the  

project.    If  you  don’t  have  one  in  mind,  simply  select  the  Local  Object  button.  

   

Create the Data Model Using an External Model File Entity  Data  Models  can  be  created  using  external  tools  such  as  Microsoft  Visual  Studio  and  recently,  the  OData  Modeler  tool.    The  SMP  tool  has  an  OData  Modeler  component  that  helps  you  create  data  models  for  OData  services.    More  information  can  be  found  on  the  SAP  HANA  Cloud  Documentation  site.  1. Prepare  your  XML  file  –  (you  can  use  the  $metadata  file  of  your  OData  service  too)  2. In  your  created  project,  right-­‐click  on  Data  Model  and  select  Import  à  Data  Model  

from  File  from  the  context  menu.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   5  

3. Browse  to  the  location  of  the  XML  model  file  and  select  Next.  

   

4. The  next  screen  of  the  File  Import  wizard  shows  an  outline  of  the  model  contents.    You  can  see  the  Entity  Types  as  well  as  the  relationships  defined  within  the  model.    

   

5. Click  on  Finish.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   6  

 Your  project  data  model  should  now  reflect  what  was  described  in  the  model  metadata  file.  Save  your  project.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   7  

4.2 Option 2 - Creating a Data Model by Importing DDIC Structures

 You  can  leverage  existing  ABAP  data  dictionary  (DDIC)  structures,  BOR  objects,  and  RFC  interfaces  to  help  you  create  data  model  objects  such  as  entity  types.    In  this  guide,  we  will  use  DDIC  structures.  1. In  your  created  project,  right-­‐click  on  Data  Model  and  select  Import  à  DDIC  Structure  

from  the  context  menu.  

 2. For  the  ABAP  Structure,  enter  BAPI_EPM_BP_HEADER  and  press  <Enter>.  

As  a  result,  you  will  see  a  list  fields/properties  contained  with  the  structure.  3. For  Object  Name,  overwrite  the  defaulted  value  (e.g.  “BapiEpmBpHeader”)  and  replace  

it  with  BusinessPartner.  4. Make  field/property  BP_ID  a  Key  field  by  selecting  Key  in  the  corresponding  Usage  

column  drop-­‐down.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   8  

5. Click  the  Continue  button    on  the  lower  right  to  finish  the  DDIC  import.  As  a  result,  you  should  see  the  BusinessPartner  Entity  Type  created  within  the  Data  Model  of  your  project.  

 6. Repeat  steps  1  through  5  to  import  DDIC  structures  for  the  SalesOrder  and  

SalesOrderItem  entities:  SalesOrder:  -­‐ ABAP  Structure:  BAPI_EPM_SO_HEADER  -­‐ Object  Name:  SalesOrder  -­‐ Key  field:  SO_ID  

   SalesOrder:  -­‐ ABAP  Structure:  BAPI_EPM_SO_ITEM  -­‐ Object  Name:  SalesOrderItem  -­‐ Key  field:  SO_ID,  SO_ITEM_POS    

7. Save  your  project.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   9  

 Now  we  have  corresponding  Entity  Sets.    Entity  Sets  will  represent  Collections  of  entities  in  the  OData  service.  NOTE:  The  screen  captures  in  this  doc  were  taken  in  the  older  SAP  Gateway.  In  your  newer  SP  version  of  Gateway  should  generate  entity  sets  that  has  the  naming  convention  with  “…Set”.  

8.  Now  create  Associations  by  double-­‐clicking  on  the  Associations  node  on  the  left  pane.  On  the  right  pane,  click  on  the  Append  Row  button  (twic)  and  enter  Associations  called  BusinessPartner_SalesOrder  and  SalesOrder_SalesOrderItem.      

9. Enter  the  Principal  and  Dependent  Entity  and  corresponding  Cardinalities  as  shown  below.  

Each  association  reflects  a  one-­‐to-­‐many  (1  to  M)  relationship  between  the  principal  and  dependent  entities.    So,  put  simply,  a  Business  Partner  can  have  many  Sales  Orders  and  a  Sales  Order  can  have  many  Sales  Order  Items.  As  you  might  have  noticed,  Associations  defines  the  relationships  between  entities.  

10. Now  create  a  Referential  Constraint  for  the  SalesOrder_SalesOrderItem  association.    A  Referential  Constraint  is  similar  to  the  concept  of  foreign  keys  in  relational  tables.  Double-­‐click  on  the  Referential  Constraint  node  under  the  SalesOrder_SalesOrderItem  association.  

11. On  the  right  pane,  click  on  Append  Row  and  simply  select  the  SoID  value  for  the  Principal  Key  and  also  for  the  Dependent  Property,  then  press  <Enter>.    The  other  fields  will  populate  automatically.  

 12. Based  on  the  relationships  defined  in  the  Associations,  we  can  build  Navigation  

Properties  for  specific  entity  types.    For  example,  since  a  BusinessPartner  can  have  many  Sales  Orders,  we  want  to  build  a  Navigation  Property  that  can  be  used  to  “navigate”  from  a  BusinessPartner  instance  to  its  associated  SalesOrder  collection.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   10  

13. Double-­‐click  on  Navigation  Properties  under  the  BusinessPartner  Entity  Type.  Click  on  Append  Row  and  enter  SalesOrders  for  the  Name  and  select  BusinessPartner_SalesOrder  for  Relationship  Name.  

 14. Double-­‐click  on  Navigation  Properties  under  the  SalesOrder  Entity  Type  and  append  

two  new  rows.    Name  the  Navigations  BusinessPartner  and  Items  with  Relationship  Names  BusinessPartner_SalesOrder  and  SalesOrder_SalesOrderItem  respectively.  

 15. Save  your  project.  16. Finally  create  Association  Sets.    An  association  set  is  simply  a  logical  container  for  

association  instances  of  the  same  type.  17. Create  an  association  set  by  right-­‐clicking  on  Data  Model  and  selecting  Create  à  

Association  Set  from  the  context  menu.  

   Enter  BusinessPartner_SalesOrder_AssocSet  as  the  Name  and  select  BusinessPartner_SalesOrder  as  the  association.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   11  

18. Append  a  new  row  and  add  an  association  set  called  SalesOrder_SalesOrderItem_AssocSet  with  SalesOrder_SalesOrderItem  as  the  association  and  press  <Enter>.  

 The  resulting  association  sets  should  appear  as  below.  

 19. Save  your  project.  20. Generate  the  runtime  objects  by  selecting  the  Generate  button  on  the  main  toolbar.  

 You  can  leave  in  the  default  values  and  press  Continue/Enter   .  Note  that  the  Technical  Service  Name  field  within  the  Service  Registration  section  reflects  the  name  of  the  service  exposed  in  the  Service  URL.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   12  

Select  Local  Object  unless  you  have  a  specific  Package  you  want  to  use  for  these  objects.  

 As  a  result,  based  on  the  Data  Model  created,  a  number  of  runtime  ABAP  objects  were  generated  in  the  background.    Corresponding  model  class  implementations  along  with  data  provider  shells  were  generated  to  prepare  the  OData  service  to  be  exposed  to  the  outside  world.  

Service Maintenance and Initial Test We  have  used  the  Service  Builder  to  help  us  create  an  OData  model  and  generate  the  runtime  ABAP  components.    Now  we  need  to  expose  the  service  on  Gateway  and  conduct  an  initial  test.  The  Service  Maintenance  function  in  the  Service  Builder  enables  you  to  register  and  maintain  each  service  in  an  SAP  Gateway  system.  Prerequisites  The  SAP  Gateway  systems  in  which  you  want  to  register  the  service  must  be  configured  under  the  following  path:  SPRO  à  SAP  NetWeaver  à  Gateway  Service  Enablement  à  Backend  OData  Channel  à  Connection  Settings  to  SAP  NetWeaver  Gateway  à  SAP  NetWeaver  Gateway  Settings.  1. In  Service  Builder,  double-­‐click  on  the  Service  Maintenance  folder  within  your  project  

to  view  the  configured  systems.  2. Select  the  system  you  want  to  register  the  service  in  and  click  on  the  Register  Service  

button.    If  you  do  not  have  any  system  listed,  see  the  prerequisites  above.  

   Select  Yes  in  the  warning  dialog.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   13  

 As  a  result,  the  registration  status  next  for  the  system  you  registered  the  service  should  be  green.  

 3. Now  let’s  do  an  initial  service  call  to  test  the  service.  Select  the  Maintain  button.  

 4. In  the  lower  left  section,  launch  the  Gateway  Client  by  selecting  the  Gateway  Client  

button.  

 The  Gateway  Client  should  open  in  another  window.  

5. The  Request  URI  value  represents  the  OData  Service  Document  URL  of  this  service.  6. Select  the  Execute  (F8)  button.  

 7. As  a  result,  the  response  section  on  the  right  should  show  an  HTTP  response  code  of  

200…  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   14  

…and  you  should  see  the  Service  Document  showing  the  Collections  (BusinessPartners,  SalesOrders,  and  SalesOrderItems)  available  for  this  service.  

 8. To  view  the  metadata  of  the  service,  overwrite  the  “?$format=xml”  at  the  end  of  the  

URL  with  $metadata.  

 9. As  a  result,  the  metadata  for  the  service  is  displayed.    If  you  examine  it  closely,  you  

should  see  that  it  directly  corresponds  to  the  data  model  you  created  in  the  previous  steps.  

   

Back  out   to  exit  the  GW  Client  for  now  and  then  back  again  to  return  to  main  Service  Builder  screen.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   15  

 

4.3 Implementing Collection GET  Each  Entity  (e.g.  BusinessPartner)  has  a  corresponding  Service  Implementation  that  is  executed  at  runtime.    Standard  operations  such  as  Create,  Read,  Update,  and  Delete  (CRUD)  as  well  as  Query  can  be  implemented  to  support  the  maintenance  of  the  entity.      As  mentioned  earlier,  after  a  project  and  its  data  model  are  generated,  the  runtime  implementation  shells  are  generated  as  well.    In  order  for  the  corresponding  service  operations  to  be  useful,  they  must  be  implemented  in  ABAP  to  return  or  process  business  data.  A  standard  set  of  five  method  shells  will  be  generated  for  each  entity  type:  

• <Entity>_GET_ENTITYSET  • <Entity>_GET_ENTITY  • <Entity>_CREATE_ENTITY  • <Entity>_UPDATE_ENTITY  • <Entity>_DELETE_ENTITY  

Depending  on  the  Entity,  operation  type,  and  the  corresponding  business  object  in  the  business  backend,  the  actual  implementation  can  vary  from  quite  simple  to  complex.    Although  we  do  not  cover  it  in  this  guide,  note  that  other  OData  operations  such  as  Function  Import  can  be  implemented  as  well.  We  begin  with  the  implementation  of  GET_ENTITYSET  which  corresponds  to  a  common  “Get  List”  query  and  is  also  functionally  equivalent  to  a  full  MBO  download.    Without  any  filters,  a  standard  GET_ENTITYSET  operation  call  returns  the  entire  entity  collection.  The  GET_ENTITYSET  method  will  be  implemented  for  all  three  of  our  entity  sets:  BusinessPartnerSet,  SalesOrderSet,  and  SalesOrderItemSet.  

Implement Method BUSINESSPARTNERS_GET_ENTITYSET 1. In  Service  Builder,  expand  the  Service  Implementation  and  then  the  BusinessPartnerSet  

node.    Right-­‐click  on  GetEntitySet  (Query)  and  select  Go  to  ABAP  Workbench  from  the  context  menu.  

 

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   16  

 

An  information  dialog  will  display.    Select  the  Continue    button  to  proceed  with  the  implementation.  

 2. Once  in  the  Class  Builder,  1)  toggle  into  edit  mode,  2)  scroll  down  and  place  the  cursor  

in  the  BUSINESSPARTNERS_GET_ENTITYSET  method  row,  and  3)  select  the  Redefine  button.  

 This  opens  up  the  BUSINESSPARTNERS_GET_ENTITYSET  implementation.  

3. From  the  Edit  menu,  select  Pattern.  

 4. Enter  function  name  BAPI_EPM_BP_GET_LIST  and  press  <Enter>.  

 

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   17  

 5. Uncomment  the  line  with  TABLES  and  BPHEADERDATA  by  deleting  the  asterisk  (*)  and  

add  et_entityset  as  the  table  variable  to  correspond  to  BPHEADERDATA.  

   If  desired,  you  can  cut  and  paste  from  below  instead.  

method BUSINESSPARTNERS_GET_ENTITYSET. CALL FUNCTION 'BAPI_EPM_BP_GET_LIST' * EXPORTING * MAX_ROWS = TABLES * SELPARAMBPID = * SELPARAMCOMPANYNAME = BPHEADERDATA = et_entityset * BPCONTACTDATA = * RETURN = . endmethod.  

As  you  can  see,  the  implementation  is  simple.    The  BAPI_EPM_BP_GET_LIST  function  is  called  to  get  the  list  of  business  partners  and  the  result  is  captured  and  passed  out  through  et_entityset.  

6. Select  the  Activate  button.  

   

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   18  

Confirm  that  the  three  objects  are  selected  for  activation  as  shown  below  and  continue   .

 If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.    

7. Go  back  to  the  Class  Interface  screen.  

   

Implement Method SALESORDERS_GET_ENTITYSET 1. Scroll  down  to  the  SALESORDERS_GET_ENTITYSET  method,  place  the  cursor  in  the  row,  

and  select  the  Redefine  button.  2. Implement  the  method  with  the  following  code.  

method SALESORDERS_GET_ENTITYSET. field-symbols: <fs_key> type /iwbep/s_mgw_name_value_pair. data: ls_company_name type SNWD_COMPANY_NAME. data: lt_range type table of BAPI_EPM_CUSTOMER_NAME_RANGE, ls_range type BAPI_EPM_CUSTOMER_NAME_RANGE, lv_bp_id(10) type N. * Return all SalesOrders if no navigation path. if it_navigation_path is initial. CALL FUNCTION 'BAPI_EPM_SO_GET_LIST' * EXPORTING * MAX_ROWS = TABLES SOHEADERDATA = et_entityset * SOITEMDATA = * SELPARAMSOID = * SELPARAMBUYERNAME = * SELPARAMPRODUCTID = * RETURN = .

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   19  

else. * Navigation path from BusinessPartners. Return sales orders for a specific business partner. * However, can only lookup using "Company Name", not BP_ID. So need to get Company Name using BP_ID first. read table it_key_tab assigning <fs_key> index 1. lv_bp_id = <fs_key>-value. * Look up buyer name based on BP_ID select single company_name from snwd_bpa into ls_company_name where bp_id = lv_bp_id. ls_range-sign = 'I'. ls_range-option = 'EQ'. ls_range-low = ls_company_name. append ls_range to lt_range. CALL FUNCTION 'BAPI_EPM_SO_GET_LIST' * EXPORTING * MAX_ROWS = TABLES SOHEADERDATA = et_entityset * SOITEMDATA = * SELPARAMSOID = SELPARAMBUYERNAME = lt_range * SELPARAMPRODUCTID = * RETURN = . endif. endmethod.    

For  Sales  Orders,  the  resulting  list  of  sales  order  entities  depends  primarily  on  whether  a  navigation  path  (e.g.  from  BusinessPartnerSet)  is  being  followed  or  not.    If  so,  we  need  to  read  the  key  of  the  BusinessPartner  instance  passed  in  and  look  up  Sales  Orders  that  belong  to  that  Business  Partner.    One  twist  is  that  the  function  we  want  to  use  to  return  the  sales  order  list,  BAPI_EPM_SO_GET_LIST,  has  a  selection  parameter  for  the  buyer  name  (or  company  name),  not  the  BP_ID.    This  opens  up  the  possibility  that  a  duplicate  company  name  will  return  sales  orders  of  a  different  buyer.    However,  for  simplicity,  we  will  stick  with  this.    If  a  navigation  path  does  not  exist,  then  all  the  sales  orders  entities  are  returned.  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen.    

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   20  

Implement Method SALESORDERITEMS_GET_ENTITYSET  

5. Scroll  down  to  the  SALESORDERITEMS_GET_ENTITYSET  method,  place  the  cursor  in  the  row,  and  select  the  Redefine  button.  

6. Implement  the  method  with  the  following  code.  

method SALESORDERITEMS_GET_ENTITYSET. data: lt_range type table of BAPI_EPM_SO_ID_RANGE, ls_range type BAPI_EPM_SO_ID_RANGE, lv_so_id(10) type N. field-symbols: <fs_key> type /iwbep/s_mgw_name_value_pair. * We want to limit access to SalesOrderItmes only through a navigation path or $expand option. if it_navigation_path is initial. * If it's not, raise an exception. RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = /iwbep/cx_mgw_busi_exception=>business_error_unlimited message_unlimited = 'SalesOrderItems can only be accessed from a Sales Order navigation path or using the $expand=Items option.'. else. * There is a navigation path. Read only items for a particular SO * SO ID should be in it_key_tab. read table it_key_tab assigning <fs_key> index 1. lv_so_id = <fs_key>-value. ls_range-sign = 'I'. ls_range-option = 'EQ'. ls_range-low = lv_so_id. append ls_range to lt_range. CALL FUNCTION 'BAPI_EPM_SO_GET_LIST' * EXPORTING * MAX_ROWS = TABLES * SOHEADERDATA = SOITEMDATA = et_entityset SELPARAMSOID = lt_range * SELPARAMBUYERNAME = * SELPARAMPRODUCTID = * RETURN = . endif.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   21  

endmethod.    

For  Sales  Order  Items,  we  only  want  to  return  items  within  the  context  of  its  parent  Sales  Order,  so  if  a  navigation  path  does  not  exist,  an  exception  is  raised.    Otherwise,  the  SO_ID  is  read  from  the  key  table  (it_key_tab)  and  used  to  get  the  list  of  sales  order  items  that  belong  to  the  sales  order.  

7. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

8. Go  back  to  the  Class  Interface  screen.  

Test the GET_ENTITYSET Implementations 9. Navigate  to  the  Gateway  Client  via  Service  Maintenance  (i.e.  double-­‐click  Service  

Maintenance  folder  on  left  and  select  the  Maintain  button  on  the  right).      You  can  also  open  a  separate  Gateway  Client  window  by  entering  /o/IWFND/GW_CLIENT  transaction  code.    In  this  case,  replace  the  default  Request  URI  with  the  base  service  URI  of  our  service  (/sap/opu/odata/sap/Z_EPM_RKT_SRV/).  

10. First  test  getting  the  BusinessPartnerSet  entity  set.  11. Append  BusinessPartnerSet  to  the  end  of  the  Request  URI  and  select  Execute  (F8).  

 12. As  a  result,  you  should  get  a  list  of  BusinessPartner  entries  returned.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   22  

 13. Now  overwrite  BusinessPartnerSet  with  SalesOrderSet  in  the  Request  URI  and  select  

Execute  (F8).  

 As  a  result,  you  should  get  a  complete  list  of  SalesOrder  entries  returned.  

 

Implement GET_ENTITY for SalesOrder and BusinessPartner Remember  that  for  sales  order  items,  the  only  items  returned  are  those  in  the  context  of  a  specific  sales  order.    So  we  first  have  to  complete  the  implementation  of  reading  a  specific  sales  order  first.    This  is  done  in  the  GET_ENTITY  method.    Whereas  a  GET_ENTITYSET  method  corresponds  to  a  QUERY  operation  that  returns  0  to  many  entries,  a  GET_ENTITY  method  corresponds  to  a  READ  operation  that  returns  0  to  at  most  1  entry.  While  we’re  at  it,  we’ll  implement  the  GET_ENTITY  method  for  the  BusinessPartner  entity  as  well.  1. Scroll  down  to  the  SALESORDER_GET_ENTITY  method,  place  the  cursor  in  the  row,  and  

select  the  Redefine  button.  2. Implement  the  method  with  the  following  code.  

method SALESORDERS_GET_ENTITY. DATA: lt_keys TYPE /IWBEP/T_MGW_TECH_PAIRS, ls_key TYPE /IWBEP/S_MGW_TECH_PAIR,

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   23  

ls_so_id type BAPI_EPM_SO_ID, lv_so_id(10) type N. lt_keys = IO_TECH_REQUEST_CONTEXT->GET_KEYS( ). READ TABLE lt_keys with key name = 'SO_ID' INTO ls_key. lv_so_id = ls_key-value. ls_so_id-so_id = lv_so_id. CALL FUNCTION 'BAPI_EPM_SO_GET_DETAIL' EXPORTING SO_ID = ls_so_id IMPORTING HEADERDATA = er_entity * TABLES * CONTACTDATA = * RETURN = lt_return . endmethod.    

The  BAPI  function  BAPI_EPM_SO_GET_DETAIL  is  used  to  return  the  sales  order  header  information  using  the  SO_ID  key  passed  in.  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen.  5. Scroll  down  to  the  BUSINESSPARTNER_GET_ENTITY  method,  place  the  cursor  in  the  

row,  and  select  the  Redefine  button.  6. Implement  the  method  with  the  following  code.  

method BUSINESSPARTNERS_GET_ENTITY. DATA: lt_keys TYPE /IWBEP/T_MGW_TECH_PAIRS, ls_key TYPE /IWBEP/S_MGW_TECH_PAIR, ls_bp_id type BAPI_EPM_BP_ID, lv_bp_id(10) type N. lt_keys = IO_TECH_REQUEST_CONTEXT->GET_KEYS( ). READ TABLE lt_keys with key name = 'BP_ID' INTO ls_key. lv_bp_id = ls_key-value. ls_bp_id-bp_id = lv_bp_id. CALL FUNCTION 'BAPI_EPM_BP_GET_DETAIL' EXPORTING BP_ID = ls_bp_id IMPORTING HEADERDATA = er_entity * TABLES

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   24  

* CONTACTDATA = * RETURN = lt_return . endmethod.    

The  BAPI  function  BAPI_EPM_BP_GET_DETAIL  is  used  to  return  the  business  partner  header  information  using  the  BP_ID  key  passed  in.  

7. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

8. Go  back  to  the  Class  Interface  screen.    

Test the GET_ENTITY Implementations and Navigation Functionality 1. Navigate  to  the  Gateway  Client  via  Service  Maintenance  (i.e.  double-­‐click  Service  

Maintenance  folder  on  left  and  select  the  Maintain  button  on  the  right).      You  can  also  open  a  separate  Gateway  Client  window  by  entering  /o/IWFND/GW_CLIENT  transaction  code.    In  this  case,  replace  the  default  Request  URI  with  the  base  service  URI  of  our  service  (/sap/opu/odata/sap/Z_EPM_RKT_SRV/).  First  test  reading  a  single  SalesOrder  entry.  

2. Again,  append  SalesOrderSet  to  the  end  of  the  Request  URI  and  select  Execute  (F8).  3. In  the  result,  go  to  an  <entry>  element  and  look  for  a  href  link  specifying  a  specific  

SalesOrder  entry  such  as  SalesOrderSet('500000000').  

 4. Append  the  href  value  (e.g.  SalesOrderSet('500000000'))  to  the  end  of  the  URL  and  

select  Execute  (F8).  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   25  

 One  entry  should  be  returned  showing  the  detailed  properties  of  the  specified  sales  order.  

5. Now  append  Items  to  the  current  URI  and  execute  (F8).  

 6. As  a  result,  all  the  sales  order  items  for  the  specified  sales  order  are  returned.  

 7. Now  overwrite  “/Items”  with  ?$expand=Items  and  execute  (F8).  

What  is  the  difference  between  this  query  and  the  previous  one?      You  may  notice  that  this  result  also  contains  all  the  sales  order  items  for  a  given  sales  order.  But  in  addition,  at  the  bottom,  it  also  includes  the  sales  order  header  information.  System  Query  Option  –  $expand  The  $expand  OData  system  query  option  (OData  –  $expand)  makes  it  possible,  for  example,  to  Read  a  full  sales  order  using  one  call  –  i.e.,  a  sales  order  header  along  with  all  of  its  corresponding  item  entries  in  an  inline,  deep  format.  This  is  possible  due  to  the  associations  and  navigation  properties  set  up  in  our  data  model.    The  one-­‐to-­‐many  association  between  SalesOrder  and  SalesOrderItem  along  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   26  

with  the  navigation  property,  Items  (allowing  for  navigation  from  SalesOrder  to  SalesOrderItemSet),  is  the  basis  for  reading  or  creating  our  sales  order  header  entries  “deeply”  with  inline  sales  order  item  entries.  The  central  runtime  interface,  /IWBEP/IF_MGW_APPL_SRV_RUNTIME,  also  provides  the  GET_EXPANDED_ENTITY  and  GET_EXPANDED_ENTITYSET  methods  for  reading  or  querying  entity  data  in  a  deep/inline  format.      

Note The  SAP  Gateway  framework  provides  a  default  implementation  of  these  methods,  which  can  completely  handle  expand  requests  in  a  generic  way.  However,  you  do  have  the  option  to  redefine  the  methods  with  your  own  implementation  if  necessary  (e.g.  in  case  of  performance-­‐critical  scenarios  or  if  you  experience  a  bad  response  time).  

8. To  make  sure  the  GET_ENTITY  for  the  BusinessPartner  is  working,  append  BusinessPartnerSet  to  the  end  of  the  Request  URI  and  select  Execute  (F8).  

9. In  the  result  set,  find  a  valid  business  partner  ID  (e.g.  BusinessPartnerSet('100000000'))  and  execute  again.  As  a  result,  a  single  BusinessPartner  entry  along  with  its  details  should  be  returned.  

 

4.4 Implementing Filters  The  OData  $filter  system  query  option  provides  the  functionality  to  query  for  a  subset  of  the  Entries  from  the  Collection  of  Entries  using  an  expression  specified  in  the  query  option.  For  example,  the  expression  .../SalesOrderSet?$filter=SoID  eq  '500000000'  would  return  the  Sales  Order  with  SoID  equal  to  ‘500000000’.    As  another  example,  the  expression  …/SalesOrderSet?$filter=BuyerName  eq  'SAP'  would  return  Sales  Orders  bought  from  customer  ‘SAP’.  As  such,  the  filtering  capability,  along  with  delta  query  functions  (discussed  in  later  chapters),  can  potentially  be  used  to  functionality  meet  the  requirements  set  for  MBOs  and  its  use  for  load  parameters,  sync  parameters,  and  personalization  keys.      However,  due  to  the  inherent  differences  between  MBOs  and  the  OData  standard,  a  direct  mapping  between  respective  features  cannot  be  achieved  and  limitations  from  either  perspective  are  to  be  expected.    In  this  context,  we  proceed  below  with  details  on  how  to  implement  filter  handling  in  OData  query  operations  (GET_ENTITYSET  methods).  1. Go  back  to  the  Class  Builder  screen  for  class  ZCL_Z_EPM_RKT_DPC_EXT  and  open  the  

implementation  of  the  method  BUSINESSPARTNERS_GET_ENTITYSET.  Change  to  edit  mode  if  necessary.  

2. Re-­‐implement  the  method  with  the  following  code.    New  code  is  highlighted  in  green.  

method BUSINESSPARTNERS_GET_ENTITYSET. DATA:ls_filter_select_options TYPE /iwbep/s_mgw_select_option,

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   27  

ls_mgw_select_options TYPE /iwbep/s_mgw_select_option, ls_mgw_range_options TYPE /iwbep/s_cod_select_option, ls_range_bpid TYPE BAPI_EPM_BP_ID_RANGE, lt_range_bpid TYPE TABLE OF BAPI_EPM_BP_ID_RANGE, ls_range_companyname TYPE BAPI_EPM_COMPANY_NAME_RANGE, lt_range_companyname TYPE TABLE OF BAPI_EPM_COMPANY_NAME_RANGE. DATA:lv_bpid_low(10) TYPE N, lv_bpid_high(10) TYPE N, ls_max_rows TYPE BAPI_EPM_MAX_ROWS. * Process filters LOOP AT it_filter_select_options INTO ls_filter_select_options. LOOP AT ls_filter_select_options-select_options INTO ls_mgw_range_options. TRANSLATE ls_filter_select_options-property TO UPPER CASE. CASE ls_filter_select_options-property. WHEN 'BPID'. lv_bpid_low = ls_mgw_range_options-low. "Workaround for adding leading zeros if ls_mgw_range_options-high is not initial. lv_bpid_high = ls_mgw_range_options-high. endif. MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_bpid. ls_range_bpid-low = lv_bpid_low. if ls_range_bpid-high is not initial. ls_range_bpid-high = lv_bpid_high. endif. APPEND ls_range_bpid TO lt_range_bpid. WHEN 'COMPANYNAME'. MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_companyname. APPEND ls_range_companyname TO lt_range_companyname. ENDCASE. ENDLOOP. ENDLOOP.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   28  

ls_max_rows-bapimaxrow = is_paging-top. CALL FUNCTION 'BAPI_EPM_BP_GET_LIST' EXPORTING MAX_ROWS = ls_max_rows TABLES SELPARAMBPID = lt_range_bpid SELPARAMCOMPANYNAME = lt_range_companyname BPHEADERDATA = et_entityset * BPCONTACTDATA = * RETURN = . endmethod.  

We  are  mainly  adding  some  code  to  account  for  filtering  before  the  call  to  BAPI  function  BAPI_EPM_BP_GET_LIST  is  made.  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen.  5. Open  the  implementation  of  the  method  SALESORDERS_GET_ENTITYSET  and  change  

to  edit  mode  if  necessary.  6. Re-­‐implement  the  method  with  the  following  code.    New  code  is  highlighted  in  green.  

method SALESORDERS_GET_ENTITYSET. DATA:ls_filter_select_options TYPE /iwbep/s_mgw_select_option, ls_mgw_select_options TYPE /iwbep/s_mgw_select_option, ls_mgw_range_options TYPE /iwbep/s_cod_select_option, ls_range_soid TYPE BAPI_EPM_SO_ID_RANGE, lt_range_soid TYPE TABLE OF BAPI_EPM_SO_ID_RANGE, ls_range_buyername TYPE BAPI_EPM_CUSTOMER_NAME_RANGE, lt_range_buyername TYPE TABLE OF BAPI_EPM_CUSTOMER_NAME_RANGE. DATA:lv_soid_low(10) TYPE N, lv_soid_high(10) TYPE N, ls_max_rows TYPE BAPI_EPM_MAX_ROWS. field-symbols: <fs_key> type /iwbep/s_mgw_name_value_pair. data: ls_company_name type SNWD_COMPANY_NAME. data: lt_range type table of BAPI_EPM_CUSTOMER_N

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   29  

AME_RANGE, ls_range type BAPI_EPM_CUSTOMER_NAME_RANGE, lv_bp_id(10) type N. * Return all SalesOrders if no navigation path. if it_navigation_path is initial. * Process filters LOOP AT it_filter_select_options INTO ls_filter_select_options. LOOP AT ls_filter_select_options-select_options INTO ls_mgw_range_options. TRANSLATE ls_filter_select_options-property TO UPPER CASE. CASE ls_filter_select_options-property. WHEN 'SOID'. lv_soid_low = ls_mgw_range_options-low. "Workaround for adding leading zeros if ls_mgw_range_options-high is not initial. lv_soid_high = ls_mgw_range_options-high. endif. MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_soid. ls_range_soid-low = lv_soid_low. if ls_range_soid-high is not initial. ls_range_soid-high = lv_soid_high. endif. APPEND ls_range_soid TO lt_range_soid. WHEN 'BUYERNAME'. MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_BUYERNAME. APPEND ls_range_BUYERNAME TO lt_range_BUYERNAME. ENDCASE. ENDLOOP. ENDLOOP. ls_max_rows-bapimaxrow = is_paging-top. CALL FUNCTION 'BAPI_EPM_SO_GET_LIST' EXPORTING MAX_ROWS = ls_max_rows TABLES SOHEADERDATA = et_entityset * SOITEMDATA = SELPARAMSOID = lt_range_soid

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   30  

SELPARAMBUYERNAME = lt_range_buyername * SELPARAMPRODUCTID = * RETURN = . else. * Navigation path from BusinessPartners. Return sales orders for a specific business partner. * However, can only lookup using "Company Name", not BP_ID. So need to get Company Name using BP_ID first. read table it_key_tab assigning <fs_key> index 1. lv_bp_id = <fs_key>-value. * Look up buyer name based on BP_ID select single company_name from snwd_bpa into ls_company_name where bp_id = lv_bp_id. ls_range-sign = 'I'. ls_range-option = 'EQ'. ls_range-low = ls_company_name. append ls_range to lt_range. CALL FUNCTION 'BAPI_EPM_SO_GET_LIST' * EXPORTING * MAX_ROWS = TABLES SOHEADERDATA = et_entityset * SOITEMDATA = * SELPARAMSOID = SELPARAMBUYERNAME = lt_range * SELPARAMPRODUCTID = * RETURN = . endif. endmethod.  

We  are  mainly  adding  some  code  to  account  for  filtering  before  the  call  to  BAPI  function  BAPI_EPM_BP_GET_LIST  is  made.  

7. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

8. Go  back  to  the  Class  Interface  screen.    

4.5 Implement Entity Create, Update, and Delete  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   31  

An  OData  service  provides  functionality  by  leveraging  REST  compliant,  HTTP  based  requests  using  the  POST,  PUT,  and  DELETE  methods  to  Create,  Update,  or  Delete  entities  respectively.    SAP  Gateway  exposes  such  OData  services  and  provides  an  OData  channel  runtime  API  that  can  be  used  to  implement  the  Create,  Update,  and  Delete  operations  on  the  ABAP  backend.  The  ABAP  interface  /IWBEP/IF_MGW_APPL_SRV_RUNTIME  is  the  central  implemented  by  every  data  provider  class  of  a  Gateway  exposed  OData  service.    It  contains  the  all  the  relevant  methods  for  Creating,  Updating,  and  Deleting  entities,  as  well  as  those  used  for  retrieving  or  downloading  data  (e.g.  GET_ENTITYSET)  used  in  previous  sections.    For  Create,  Update,  and  Delete  the  relevant  methods  are:  

• CREATE_ENTITY  and  CREATE_DEEP_ENTITY  • UPDATE_ENTITY  • DELETE_ENTITY  

Details  on  how  to  implement  these  methods  are  provided  in  the  following  sections.    

4.5.1 Implementing Entity Create  Creating  an  implementation  for  the  CREATE  operation  can  be  done  in  one  of  two  ways.      

1.) The  first  method  uses  the  CREATE_ENTITY  method  where  a  single  entry  is  created  with  one  call.      

2.) The  second  method  uses  the  CREATE_DEEP_ENTITY  method  where  a  single  entry  along  with  related  inline  entries  is  created  with  one  call.    For  example,  a  sales  order  along  with  its  sales  order  line  items  is  created  together  in  one  operation.  

For  our  scenario,  we  will  use  CREATE_ENTITY  for  creating  a  BusinessPartner  entity  and  CREATE_DEEP_ENTITY  for  creating  a  SalesOrder  along  with  SalesOrderItemSet.  1. On  the  Class  Builder  screen  for  class  ZCL_Z_EPM_RKT_DPC_EXT,  scroll  down  to  the  

BUSINESSPARTNERS_CREATE_ENTITY  method,  place  the  cursor  in  the  row,  and  select  the  Redefine  button.  

2. Implement  the  method  with  the  following  code.  

method BUSINESSPARTNERS_CREATE_ENTITY. data: lv_id type snwd_partner_id, ls_id type bapi_epm_bp_id. data: ls_headerdata type bapi_epm_bp_header, lt_return type table of bapiret2, ls_return type bapiret2, err_msg type string, lo_message_container type ref to /iwbep/if_message_container. data: ls_message type scx_t100key, lt_keys type /iwbep/t_mgw_tech_pairs, ls_snwd_bpa type snwd_bpa.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   32  

DATA: lv_timestamp TYPE timestamp. field-symbols: <ls_key> type /iwbep/s_mgw_tech_pair. io_data_provider->read_entry_data( importing es_data = ls_headerdata ). call function 'BAPI_EPM_BP_CREATE' exporting headerdata = ls_headerdata " EPM: BP header data importing businesspartnerid = ls_id tables return = lt_return. " Return Parameter if lt_return is not initial. loop at lt_return into ls_return. err_msg = ls_return-message . endloop. ls_message-msgid = 'SY'. ls_message-msgno = '002'. ls_message-attr1 = err_msg. raise exception type /iwbep/cx_mgw_busi_exception exporting textid = ls_message. endif. CALL FUNCTION 'BAPI_EPM_BP_GET_DETAIL' EXPORTING BP_ID = ls_id IMPORTING HEADERDATA = er_entity * TABLES * CONTACTDATA = * RETURN = lt_return . endmethod.    

The  body  of  the  request  is  passed  in  through  the  es_data  structure  and  captured  in  ls_headerdata.      The  data  is  then  used  as  input  for  the  BAPI  function  BAPI_EPM_BP_CREATE.  The  OData  standard  specifies  that  for  a  POST/CREATE  operation,  the  created  entity  data  should  be  returned  in  the  body  of  the  response.    This  is  why  in  the  above  implementation,  a  call  to  function  BP_EPM_BP_GET_DETAIL  is  made,  using  the  BP_ID  resulting  from  the  create  call,  to  capture  and  return  the  BusinessPartner  entry  data  in  the  er_entity  structure,  which  is  used  to  pass  back  the  data  in  the  response  body.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   33  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen.  5. Scroll  to  the  /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY  method.  

 Note  that  in  your  view,  the  text  color  will  still  be  in  blue  indicating  it  has  yet  to  be  redefined.  

6. Place  the  cursor  in  the  row,  and  select  the  Redefine  button.  7. Implement  the  method  with  the  following  code.  

method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY. types: ty_t_soitem type standard table of zcl_z_epm_rkt_mpc=>ts_salesorderitem with default key. * Represents full Sales Order structure - header with one or more items types: begin of ty_s_so. include type zcl_z_epm_rkt_mpc=>ts_salesorder. types: items type ty_t_soitem, end of ty_s_so. data: ls_so type ty_s_so, ls_item type zcl_z_epm_rkt_mpc=>ts_salesorderitem, lv_compare_result type /iwbep/if_mgw_odata_expand=>ty_e_compare_result.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   34  

data: lv_so_id type BAPI_EPM_SO_ID, ls_sohdr type BAPI_EPM_SO_HEADER, ls_sohdr2 type BAPI_EPM_SO_HEADER, ls_soitem type BAPI_EPM_SO_ITEM, lt_soitem type standard table of BAPI_EPM_SO_ITEM, lt_soitem2 type standard table of BAPI_EPM_SO_ITEM, lt_return type bapirettab, ls_return TYPE bapiret2, lx_busi_exc TYPE REF TO /iwbep/cx_mgw_busi_exception, lo_meco TYPE REF TO /iwbep/if_message_container, ls_message type scx_t100key, err_msg type string, ls_snwd_so type snwd_so. constants: lc_soitems TYPE string VALUE 'Items'. * Validate whether the current request including the inline SO Item data matches lv_compare_result = io_expand->compare_to( lc_soitems ). * Upon match, access data from IO_DATA_PROVIDER if lv_compare_result EQ /iwbep/if_mgw_odata_expand=>gcs_compare_result-match_equals. io_data_provider->read_entry_data( IMPORTING es_data = ls_so ). * Move header SO data into BAPI structure move-corresponding ls_so to ls_sohdr. * Move SO line items into BAPI table structure loop at ls_so-items into ls_soitem. append ls_soitem to lt_soitem. endloop. CALL FUNCTION 'BAPI_EPM_SO_CREATE' EXPORTING HEADERDATA = ls_sohdr IMPORTING SALESORDERID = lv_so_id TABLES ITEMDATA = lt_soitem RETURN = lt_return . if lt_return is not initial. loop at lt_return into ls_return. err_msg = ls_return-message . endloop.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   35  

ls_message-msgid = 'SY'. ls_message-msgno = '002'. ls_message-attr1 = err_msg. raise exception type /iwbep/cx_mgw_busi_exception exporting textid = ls_message. else. CALL FUNCTION 'BAPI_EPM_SO_GET_DETAIL' EXPORTING SO_ID = lv_so_id IMPORTING HEADERDATA = ls_sohdr2 TABLES ITEMDATA = lt_soitem2 * RETURN = . move-corresponding ls_sohdr2 to ls_so. ls_so-items = lt_soitem2. copy_data_to_ref( EXPORTING is_data = ls_so CHANGING cr_data = er_deep_entity ). endif. endif. endmethod.    

One  of  the  unique  aspects  of  this  method  is  the  structure  of  the  data  incoming.    Since  it  consists  of  two  entity  types,  arranged  in  a  parent-­‐child  nested-­‐like  structure,  a  similar  structure  must  be  declared  to  capture  such  data.    This  is  done  by  defining  a  type  ty_s_so:  

 The  type  ty_s_so  consists  of  a  structure  of  type  zcl_z_epm_rkt_mpc=>ts_salesorder  (which  in  turn  is  of  type  BAPI_EPM_SO_HEADER)  and  a  table  type  of  made  up  of  structure  zcl_z_epm_rkt_mpc=>ts_salesorderitem  (which  is  turn  is  of  type  BAPI_EPM_SO_ITEM).    A  structure  variable  ls_so  is  declared  using  type  ty_s_so  and  used  to  capture  the  sales  order  header  data  along  with  the  multiple  line  items  passed  into  the  method.  

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   36  

Then  the  data  is  broken  up  into  the  required  header  and  item  data  structures  needed  as  input  for  function  BAPI_EPM_SO_CREATE.  Upon  success,  the  created  sales  order  entity  along  with  its  corresponding  line  items  are  read  and  sent  back  to  the  consumer  in  the  response  body.  

8. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

9. Go  back  to  the  Class  Interface  screen.    

4.5.2 Implementing Entity Update  Creating  an  implementation  for  the  UPDATE  operation  can  be  done  using  the  UPDATE_ENTITY  method.    For  our  scenario,  we  will  update  a  single  SalesOrder  entry  using  the  SALESORDERS_UPDATE_ENTITY  method.  1. On  the  Class  Builder  screen  for  class  ZCL_Z_EPM_RKT_DPC_EXT,  scroll  down  to  the  

SALESORDERS_UPDATE_ENTITY  method,  place  the  cursor  in  the  row,  and  select  the  Redefine  button.  

2. Implement  the  method  with  the  following  code.  

method SALESORDERS_UPDATE_ENTITY. DATA: lv_id(10) TYPE N, ls_id TYPE bapi_epm_so_id. DATA: ls_headerdata TYPE bapi_epm_so_header, lt_return TYPE TABLE OF bapiret2, ls_return TYPE bapiret2, err_msg TYPE string, lo_message_container TYPE REF TO /iwbep/if_message_container. DATA: ls_message TYPE scx_t100key, lt_keys TYPE /iwbep/t_mgw_tech_pairs. DATA ls_headerdatax TYPE bapi_epm_so_headerx. FIELD-SYMBOLS: <ls_key> TYPE /iwbep/s_mgw_tech_pair. lt_keys = io_tech_request_context->get_keys( ). READ TABLE lt_keys WITH KEY name = 'SO_ID' ASSIGNING <ls_key>. IF sy-subrc EQ 0. lv_id = <ls_key>-value. ENDIF.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   37  

IF lv_id IS INITIAL. ls_message-msgid = 'SY'. ls_message-msgno = '002'. ls_message-attr1 = 'No Sales Order ID provided'. RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = ls_message. ENDIF. io_data_provider->read_entry_data( IMPORTING es_data = ls_headerdata ). ls_id-so_id = lv_id. " EPM: Sales Order header data fields that can be updated " using the OData service ls_headerdatax-so_id = lv_id. ls_headerdatax-note = 'X'. ls_headerdatax-LIFECYCLE_STATUS = 'X'. ls_headerdatax-BILLING_STATUS = 'X'. ls_headerdatax-DELIVERY_STATUS = 'X'. CALL FUNCTION 'BAPI_EPM_SO_CHANGE' EXPORTING SO_ID = ls_id SOHEADERDATA = ls_headerdata SOHEADERDATAX = ls_headerdatax TABLES RETURN = lt_return . IF lt_return IS NOT INITIAL. LOOP AT lt_return INTO ls_return. err_msg = ls_return-message . ENDLOOP. ls_message-msgid = 'SY'. ls_message-msgno = '002'. ls_message-attr1 = err_msg. RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = ls_message.

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   38  

ENDIF. MOVE-CORRESPONDING ls_headerdata TO er_entity. endmethod.    

The  BAPI  function  BAPI_EPM_SO_CHANGE  is  used  to  update  the  data  using  the  SO_ID  key  passed  in.    The  implementation  defines  four  fields  (Note,  Lifecycle  Status,  Billing  Status,  and  Delivery  Status)  that  can  be  updated  by  using  the  ls_headerx  structure.  Upon  success  for  an  Update/PUT  operation,  updated  data  is  not  returned  in  the  response  body,  which  complies  with  the  OData  standard  for  a  PUT  operation.    A  HTTP  response  code  of  204  is  confirmation  that  the  update  operation  succeeded.  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen.    

4.5.3 Implementing Entity Delete  Creating  an  implementation  for  the  DELETE  operation  can  be  done  using  the  DELETE_ENTITY  method.    For  our  scenario,  we  will  delete  a  single  SalesOrder  entry  using  the  SALESORDERS_DELETE_ENTITY  method.    1. On  the  Class  Builder  screen  for  class  ZCL_Z_EPM_RKT_DPC_EXT,  scroll  down  to  the  

SALESORDER_DELETE_ENTITY  method,  place  the  cursor  in  the  row,  and  select  the  Redefine  button.  

2. Implement  the  method  with  the  following  code.  

method SALESORDERS_DELETE_ENTITY. DATA: lt_keys TYPE /IWBEP/T_MGW_TECH_PAIRS, ls_key TYPE /IWBEP/S_MGW_TECH_PAIR, ls_so_id type BAPI_EPM_SO_ID, lv_so_id(10) type N. lt_keys = IO_TECH_REQUEST_CONTEXT->GET_KEYS( ). READ TABLE lt_keys with key name = 'SO_ID' INTO ls_key. lv_so_id = ls_key-value. ls_so_id-so_id = lv_so_id. CALL FUNCTION 'BAPI_EPM_SO_DELETE' EXPORTING SO_ID = ls_so_id * TABLES

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   39  

* RETURN = lt_return . endmethod.    

The  BAPI  function  BAPI_EPM_SO_DELETE  is  used  to  delete  a  sales  order  using  SO_ID  key  passed  in.  Upon  success  for  a  DELETE  operation,  no  data  is  returned.    An  HTTP  response  code  of  204  is  confirmation  that  the  Delete  operation  succeeded.  

3. Activate  the  implementation.    If  you  get  any  warnings  about  errors,  recheck  the  code,  correct  any  mistakes,  and  then  re-­‐activate.  

4. Go  back  to  the  Class  Interface  screen  and  then  back  again  to  return  to  the  main  Service  Builder  screen.  

 

 

How  To...  Build  OData  Services  Using  SAP  Gateway    

June  2015   40  

4.6 Implementing Delta Token Support  In  SMP  3.0  the  responsibility  of  Delta  tracking  has  been  relegated  to  the  backend  system  itself.  SAP  Gateway,  starting  from  version  2.0  SP07,  provides  delta  query  support.    Delta  querying  means  “give  me  all  entities  that  were  created/changed/deleted  since  I  last  asked”.  In  other  words,  the  delta  query  protocol  defines  a  pull-­‐model  protocol  for  clients  to  obtain  changes  in  an  entity  set.    The  methods  GET_ENTITYSET  and  GET_ENTITYSET_DELTA  are  used  to  enable  delta  handling  via  Gateway.  GET_ENTITYSET_DELTA  will  be  called  when  the  client  provides  a  Delta  Token  in  the  request.  When  the  client  requests  the  entity  set  the  first  time  the  entire  collection  is  returned,  but  along  with  this  collection  a  Delta  Token  is  returned.  This  Delta  Token  is  normally  a  date  time  stamp  combined  with  a  GUID.  This  Delta  Token  must  be  persisted  by  the  client  and  then  provided  during  the  next  call  to  the  entity  set  and  it  is  here  that  the  GET_ENTITYSET_DELTA  function  is  called  instead  of  the  GET_ENTITYSET.  So  now  we  understand  the  mechanism,  but  how  do  we  implement  GET_ENTITYSET_DELTA  and  keep  track  of  changes  that  occur  in  the  backend.  It  turns  out  in  an  SAP  ABAP  system  that  there  is  not  just  one  way  of  doing  this  and  depending  on  the  type  of  object  being  tracked  the  approach  will  change.  Currently  there  are  two  approaches  that  might  be  considered  for  delta  handling:  1)   Using  Delta  Request  Log  Component  2)   Using  Syclo  xChange  Framework    The  implementation  details  are  explained  in  the  another  H2G.    

www.sap.com/contactsap

www.sdn.sap.com/irj/sdn/howtoguides