32
SAP NetWeaver How-To Guide How To... Create Services Using the OData Channel Applicable Releases: SAP NetWeaver Gateway 2.0 SP3+ Version 1.1 July 2012

How to Create Gateway Services Using the OData Channel API (7)

Embed Size (px)

DESCRIPTION

Creating Gateway Services

Citation preview

  • SAP NetWeaver

    How-To Guide

    How To... Create Services Using the

    OData Channel

    Applicable Releases:

    SAP NetWeaver Gateway 2.0 SP3+

    Version 1.1

    July 2012

  • Copyright 2012 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, Outlook, and PowerPoint are

    registered trademarks of Microsoft Corporation.

    IBM, DB2, DB2 Universal Database, OS/2, Parallel

    Sysplex, MVS/ESA, AIX, S/390, AS/400, OS/390,

    OS/400, iSeries, pSeries, xSeries, zSeries, z/OS, AFP,

    Intelligent Miner, WebSphere, Netfinity, Tivoli, Informix,

    i5/OS, POWER, POWER5, OpenPower and PowerPC are

    trademarks or registered trademarks of IBM Corporation.

    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.

    MaxDB is a trademark of MySQL AB, Sweden.

    SAP, R/3, mySAP, mySAP.com, xApps, xApp, SAP

    NetWeaver, 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 in several other countries all over the world.

    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.

    These materials are subject to change without notice.

    These materials are provided by SAP AG and its affiliated

    companies ("SAP Group") for informational purposes only,

    without representation or warranty of any kind, and SAP

    Group shall not be liable for errors or omissions with

    respect to the materials. The only warranties for SAP

    Group products and services are those that are set forth in

    the express warranty statements accompanying such

    products and services, if any. Nothing herein should be

    construed as constituting an additional warranty.

    These materials are provided as is 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 not be liable for damages of any kind including

    without limitation direct, special, indirect, or consequential

    damages that may result from the use of these materials.

    SAP does not warrant the accuracy or completeness of the

    information, text, graphics, links or other items contained

    within these materials. 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 NetWeaver How-to Guides are intended to simplify

    the product implementation. 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 SAPs 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

    1.10 Upgraded to support SP3+ changes

  • 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.

    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 Create Your Services Model Class .............................................................................. 2 4.2 Implement Your Metadata Classs DEFINE and GET_LAST_MODIFIED Methods .... 4

    4.3 Create Your Services Runtime Class .......................................................................... 6 4.4 Redefine and Implement the GET_ENTITYSET Method ............................................. 6 4.5 Redefine and Activate the GET_ENTITY Service ........................................................ 9 4.6 Redefine and Implement the UPDATE_ENTITY Method ........................................... 10 4.7 Redefine and Implement the CREATE_ENTITY Method ........................................... 12 4.8 Maintain OData Channel Table Configuration ............................................................ 13 4.9 Activate the Service on the Gateway System ............................................................ 17 4.10 Test Your Service ....................................................................................................... 21

  • How To... Create Services Using the OData Channel

    July 2012 1

    1. Business Scenario Your backend SAP system contains Banking business data that you want to expose via a REST

    based API so that it will be easily consumable by the outside world.

    2. Background Information SAP NetWeaver Gateway offers an easy way to expose data via the REST based Open Data (OData)

    format. With Gateway you can generate services based on BOR objects, RFCs, or Screen Scraping.

    There is also another way using the OData Channel API, which is an ABAP Object API. You develop

    classes using this API on the backend system where the SAP data resides, not on the actual Gateway

    system. The OData Channel is very flexible and powerful, it allows you to create simple services or

    complex ones. This guide will focus on creating a simple service with OData Channel. It is the hope of

    the author that once you learn how to create this very simple service you will move on to developing

    more complex and interesting services with OData Channel.

    3. Prerequisites SAP NetWeaver Gateway 2.0 SP3 (or higher) installed and configured.

    Backend SAP System with the BEP (SP3 or higher) gateway add-on installed.

    Backend SAP System is connected to the SAP NetWeaver Gateway system.

    Knowledge of ABAP Object Oriented programming is required. That said, this is a very detailed

    step by step guide which you could probably complete without ABAP OO experiencebut you

    most likely wouldnt be able to fully understand it.

  • How To... Create Services Using the OData Channel

    July 2012 2

    4. Step-by-Step Procedure The following steps will guide you thru creating an OData Channel service based on Bank business

    data. On the backend system you will develop and configure the Bank service using the OData

    Channel API and configuration tables. Once that is done you will activate the service on the Gateway

    system and test it.

    4.1 Create Your Services Model Class The Model class defines the interface of your OData Channel service. This section will show you how

    to create this class and which super class it needs to inherit from. ...

    1. Logon to the backend SAP system that you wish to expose business data from with OData

    Channel based services.

    2. Go to transaction SE80 ABAP Development Workbench

    3. Change the object type drop down to be Class / Interface:

    4. Enter in the class name Z_CL_BANK_MODEL_:

    5. Click the Display icon (the eye glasses icon).

    6. Since the object does not yet exist you will be asked if you want to create it:

    7. Click the Yes button.

    8. Except the default type Class radio button and click the Enter button.

    9. Enter in a Description, accept the default selections and click the Save button.

  • How To... Create Services Using the OData Channel

    July 2012 3

    10. Save your newly created class as a Local Object.

    11. You should now see the following:

    12. Double click on the class you just created, this will open the class editor.

    13. In the class editor switch to the Properties tab:

    14. Make sure you are in Change mode.

    15. Click the Superclass button.

  • How To... Create Services Using the OData Channel

    July 2012 4

    16. Enter in the OData Channel Metadata Class - /IWBEP/CL_MGW_ABS_MODEL:

    17. Save your class. The class should now look like this:

    4.2 Implement Your Metadata Classs DEFINE

    Method.

    The DEFINE method of the Metadata class is where you implement the coding that defines the

    services interface.

    1. Open the Methods > Inherited Methods node of your Class in the Class browser:

  • How To... Create Services Using the OData Channel

    July 2012 5

    2. Right click on the DEFINE method and in the context menu select Redefine:

    3. The method editor for the redefined method will open up:

    4. Enter in the following code that defines the metadata of your Bank service (or copy the contents

    in the attached file bind_structure.txt file):

    " ABAP OData Data Object

    DATA: lo_data_object TYPE REF TO /IWBEP/IF_MGW_ODATA_ENTITY_TYP,

    lo_property TYPE REF TO /IWBEP/IF_MGW_ODATA_PROPERTY.

    "Create a new data object with name Bank

    lo_data_object = model->create_entity_type( 'Bank' ).

    "Define the properties of the Bank object

    "IV_ABAP_FIELDNAME is the ABAP dictionary name

    "IV_PROPRETY_NAME is the OData friendly name

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKS'

    IV_PROPERTY_NAME = 'bankCountry' ).

    "Set as a key

    lo_property->set_is_key( abap_true ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKL'

    IV_PROPERTY_NAME = 'bankID' ).

    "Set as a key

  • How To... Create Services Using the OData Channel

    July 2012 6

    lo_property->set_is_key( abap_true ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKA'

    IV_PROPERTY_NAME = 'bankName' ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'PROVZ'

    IV_PROPERTY_NAME = 'region' ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'STRAS'

    IV_PROPERTY_NAME = 'street' ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'ORT01'

    IV_PROPERTY_NAME = 'city' ).

    "Bind your structure that represents the above properties

    lo_data_object->bind_structure( 'BNKA' ).

    5. Save and Activate your class.

    4.3 Create Your Services Runtime Class The services runtime class is what is called when the service is executed. The runtime class is where

    you implement your business logic. This section will guide you thru the initial setup of the runtime

    class. ...

    1. Follow the exact procedure described in section 4.2 where you created the Metadata class, this

    time naming the class Z_CL_BANK_DATA_, and setting the super class to

    /IWBEP/CL_MGW_ABS_DATA.

    2. Your class should look like the following:

    4.4 Redefine and Implement the GET_ENTITYSET

    Method

    The GET_ENTITYSET method is called for Query type operations. This section will guide you thru

    implementing the GET_ENTITYSET method which will support filtering on the BANK_COUNTRY

    parameter. ...

    1. Open the Methods > Inherited Methods > /IWBEP/IF_MGW_APPL_SRV_RUNTIME node of

    your Bank runtime object:

  • How To... Create Services Using the OData Channel

    July 2012 7

    2. Right click on the method GET_ENTITYSET and in the context menu select Redefine:

    3. The method editor should show displaying the following:

  • How To... Create Services Using the OData Channel

    July 2012 8

    4. Remove the commented out portion of the method.

    5. Implement the following by either typing in the below or copying the contents of the attached file

    named get_entityset.txt. Note: please read the comments to understand what each section of

    code is doing:

    DATA: lt_bank TYPE TABLE OF BNKA,

    wa_bnka TYPE BNKA,

    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,

    "banks - is the bank country element

    lt_range_bank_country TYPE RANGE OF banks,

    ls_range_bank_country LIKE LINE OF lt_range_bank_country.

    "Loop at the filter options internal table that is passed to this method

    LOOP AT it_filter_select_options INTO ls_filter_select_options.

    "Loop over the selection options internal table - each filter option can have

    "more than one selection option

    LOOP AT ls_filter_select_options-select_options INTO ls_mgw_range_options.

    "Change to uppercase so we don't have to worry about case issues

    TRANSLATE ls_filter_select_options-property TO UPPER CASE.

    "Check which property is being filtered on, in our case we will

    "only worry about the BANK_COUTNRY field, but often multiple fields

    "can be filtered on

    CASE ls_filter_select_options-property.

    WHEN 'BANKCOUNTRY'.

    "Setup the range table.

    MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_bank_country.

    APPEND ls_range_bank_country TO lt_range_bank_country.

    ENDCASE.

    ENDLOOP.

    ENDLOOP.

    " Select the data from the BANK table into the internal

    " table

    SELECT banks bankl banka FROM BNKA

    INTO CORRESPONDING FIELDS OF wa_bnka

    WHERE BANKS IN lt_range_bank_country.

    append wa_bnka to lt_bank.

    ENDSELECT.

    "Use the helper method to copy the internal table data into the

    "structure of the OData Service

    copy_data_to_ref( EXPORTING is_data = lt_bank

    CHANGING cr_data = er_entityset ).

    6. Save and Activate your class.

  • How To... Create Services Using the OData Channel

    July 2012 9

    4.5 Redefine and Activate the GET_ENTITY Service

    The GET_ENTITY method is called for Read operations. This section will guide you thru how to

    implement the GET_ENTITY method to support reading in the information of a bank based on the

    bank key field values that are passed to the method.

    1. Open the Methods > Inherited Methods > /IWBEP/IF_MGW_APPL_SRV_RUNTIME node of

    your Bank runtime object.

    2. Right click on the method GET_ENTITY and in the context menu select Redefine.

    3. The method editor should show displaying the following:

    4. Delete the commented out section; we wont be using that.

    5. Add the implementation by type in the following or copying the contents of the attached file

    named get_entity.txt. Note: make sure to read the comments to understand what the code is

    doing.

    DATA: lv_string TYPE string,

    ls_key_tab TYPE /IWBEP/S_MGW_NAME_VALUE_PAIR,

    lv_and(4),

    lv_value TYPE string,

    wa_bnka TYPE BNKA.

    CONSTANTS: con_filler(1) VALUE ''''.

    * Loop over the key values passed in

    LOOP AT it_key_tab INTO ls_key_tab.

    * surround values with ''

    CONCATENATE con_filler ls_key_tab-value con_filler INTO lv_value.

    * Change OData key field names to the BNKA table properties name

    TRANSLATE ls_key_tab-name TO UPPER CASE.

    IF ( ls_key_tab-name = 'BANKCOUNTRY' ).

    ls_key_tab-name = 'BANKS'.

    ELSEIF ( ls_key_tab-name = 'BANKID' ).

    ls_key_tab-name = 'BANKL'.

    ENDIF.

  • How To... Create Services Using the OData Channel

    July 2012 10

    * build where the string

    CONCATENATE lv_string

    lv_and

    ls_key_tab-name

    '='

    lv_value

    INTO lv_string

    SEPARATED BY space.

    * now and is needed.

    lv_and = 'and'.

    ENDLOOP.

    * Get the data from table BNKA

    SELECT SINGLE banks bankl banka provz stras ort01 adrnr FROM BNKA

    INTO CORRESPONDING FIELDS OF wa_bnka

    WHERE (lv_string).

    IF sy-subrc EQ 0.

    * fill the OData structure

    copy_data_to_ref(

    EXPORTING

    is_data = wa_bnka

    CHANGING

    cr_data = er_entity

    ).

    ELSE.

    " throw exception

    ENDIF.

    6. Save and Activate your changes.

    4.6 Redefine and Implement the UPDATE_ENTITY

    Method

    The UPDATE_ENTITY method is called for the Update Operation (HTTP Put verb), this is where you

    will add code to update the given business data. This section will guide you thru implementing this

    method for the Bank service we are creating.

    1. Open the Methods > Inherited Methods > /IWBEP/IF_MGW_APPL_SRV_RUNTIME node of

    your Bank runtime object.

    2. Right click on the method UPDATE_ENTITY and in the context menu select Redefine.

    3. The method editor should show displaying the following:

  • How To... Create Services Using the OData Channel

    July 2012 11

    4. Delete the commented out section, we wont be using that.

    5. Implement the update method calling the BAPI for Bank update by either typing in the following

    code, or copying the contents of the attached file named update_entity.txt:

    DATA: ls_bnka TYPE BNKA,

    ls_bank_address_x TYPE BAPI1011_ADDRESSX,

    ls_bank_address TYPE BAPI1011_ADDRESS,

    return TYPE BAPIRET2.

    * Get the updated bank data

    io_data_provider->read_entry_data( IMPORTING es_data = ls_bnka ).

    * Move data into BAPI structure

    ls_bank_address-bank_name = ls_bnka-banka.

    ls_bank_address-region = ls_bnka-provz.

    ls_bank_address-street = ls_bnka-stras.

    ls_bank_address-city = ls_bnka-ort01.

    * Set X on fields that can be updated

    ls_bank_address_x-bank_name = 'X'.

    ls_bank_address_x-region = 'X'.

    ls_bank_address_x-street = 'X'.

    ls_bank_address_x-city = 'X'.

    CALL FUNCTION 'BAPI_BANK_CHANGE'

    EXPORTING

    BANKCOUNTRY = ls_bnka-banks

    BANKKEY = ls_bnka-bankl

    BANK_ADDRESS = ls_bank_address

    BANK_ADDRESSX = ls_bank_address_x

    * BANK_DETAIL =

    * BANK_DETAILX =

    * BANK_ADDRESS1 =

    * BANK_ADDRESS1X =

    IMPORTING

  • How To... Create Services Using the OData Channel

    July 2012 12

    RETURN = return

    .

    IF ( return-type = 'E').

    " throw exception

    ENDIF.

    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

    copy_data_to_ref(

    EXPORTING

    is_data = ls_bnka

    CHANGING

    cr_data = er_entity

    ).

    6. Save and Activate your changes.

    4.7 Redefine and Implement the CREATE_ENTITY

    Method

    The CREATE_ENTITY method is called for the Create operation (HTTP POST verb). This section will

    guide you thru implementing the CREATE_ENTITY method for the Bank service we are creating.

    1. Open the Methods > Inherited Methods > /IWBEP/IF_MGW_APPL_SRV_RUNTIME node of

    your Bank runtime object.

    2. Right click on the method CREATE_ENTITY and in the context menu select Redefine.

    3. The method editor should show displaying the following:

    4. Delete the commented out section; we wont be using that.

    5. Implement the create_entity method calling the BAPI for Bank create by either typing in the

    below or copying the contents from the attached file name create_entity.txt:

    DATA: ls_bnka TYPE BNKA,

    ls_bank_address TYPE BAPI1011_ADDRESS,

  • How To... Create Services Using the OData Channel

    July 2012 13

    return TYPE BAPIRET2.

    io_data_provider->read_entry_data( IMPORTING es_data = ls_bnka ).

    * Move data into BAPI structure

    ls_bank_address-bank_name = ls_bnka-banka.

    ls_bank_address-region = ls_bnka-provz.

    ls_bank_address-street = ls_bnka-stras.

    ls_bank_address-city = ls_bnka-ort01.

    CALL FUNCTION 'BAPI_BANK_CREATE'

    EXPORTING

    BANK_CTRY = ls_bnka-banks

    BANK_KEY = ls_bnka-bankl

    BANK_ADDRESS = ls_bank_address

    * BANK_METHOD =

    * BANK_FORMATTING =

    * BANK_ADDRESS1 =

    * I_XUPDATE = 'X'

    IMPORTING

    RETURN = return

    * BANKCOUNTRY = ls_bnka-

    BANKKEY = ls_bnka-bankl

    .

    IF ( return-type = 'E').

    " throw exception

    ENDIF.

    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

    copy_data_to_ref(

    EXPORTING

    is_data = ls_bnka

    CHANGING

    cr_data = er_entity

    ).

    6. Save and Activate your changes.

    4.8 Maintain OData Channel Configuration

    For Gateway to access the OData Channel service some configuration tables need to be configured.

    These tables define the metadata class, runtime class, external service name (service to be defined in

    the ICF of the Gateway system), and then relates the metadata configuration to the runtime

    configuration for the service. This section will guide you thru configuring these tables for the Bank

    service. This configuration is done on the backend system where you created your Bank service

    classes.

    1. Go to transaction SPRO and click button title SAP Reference IMG:

  • How To... Create Services Using the OData Channel

    July 2012 14

    2. Navigate the folder structure as shown below:

    SAP Customizing Implementation Guide > SAP NetWeaver > Gateway Service Enablement >

    Backend OData Channel > Service Development for Backend OData Channel

    3. Click the Execute button next to Maintain Serivces:

    4. Doing this will bring you to the maintain service screen:

    5. Enter the Technical Service Name, Z_BANK_SERVICE_ and Service

    Version 0001:

  • How To... Create Services Using the OData Channel

    July 2012 15

    6. Click the Create button.

    7. Enter in the Data Provider Class (Z_CL_BANK_DATA_) and a Description:

    8. Save the service configuration.

    9. Click the Create Model button.

    10. Enter in the Technical Model Name Z_BANK_MODEL_, and Object Model

    Version 0001:

    11. Click the Create button.

    12. Enter in the Model Provider Class (Z_CL_BANK_MODEL_) and a

    Description:

  • How To... Create Services Using the OData Channel

    July 2012 16

    13. Save the configuration.

    14. Click the back button to navigate back to the service configuration:

    15. Click the Assign Model button.

    16. In the popup window enter the Object Model configuration you created in the last step:

    17. Click the Save button.

    18. Your service configuration should now look like the following:

  • How To... Create Services Using the OData Channel

    July 2012 17

    4.9 Activate the Service on the Gateway System

    The OData Channel service isnt automatically activated on the Gateway. You must go in and

    manually activate it using a transaction available on the Gateway system. Once activated, the services

    will be registered in the ICF. This section will guide you thru the process of activating the Bank service. ...

    1. Logon to the Gateway System.

    2. Go to transaction /iwfnd/maint_service.

    3. You should see something similar tothe following:

    4. Click the Add Service button shown below outlined in red:

  • How To... Create Services Using the OData Channel

    July 2012 18

    5. You should now see the following Add Service screen:

    6. Enter in the System Alias, in this case we are using the local system and the alias has been

    defined with the name LOCAL, also enter in the Technical Service Name you defined in the

    prior section Z_BANK_SERVICE_:

    7. Hit the enter button the service you configured earlier should show up:

    8. Click the Technical Service Name link shown outlined in red below:

  • How To... Create Services Using the OData Channel

    July 2012 19

    9. In the Add Service popup window that is displayed set the package to $tmp if you are working

    with local objects (otherwise select an appropriate package):

    10. Keep the defaults for the rest of the values and click the Enter button. Your service has now

    been added to the Gateway system.

    11. Click the back arrow to go to the main service screen shown below:

    12. Click the search icon to search for your service in the list the search icon is outlined in red

    below:

    13. In the Find popup window enter in the Technical Service Name (Z_BANK_SERVICE_) for the search term:

  • How To... Create Services Using the OData Channel

    July 2012 20

    14. Click the enter button, your service should be located in the list:

    15. Click the Technical Service Name link (highlighted below in red), this will cause the Alias

    assignment details be displayed at the bottom of the screen:

    16. The LOCAL alias is assigned to this service for the OData Standard Mode runtime (SData is an

    older runtime that exists for backwards compatibility).

    17. Click the Call Browser button to launch a web browser for the services service document.

  • How To... Create Services Using the OData Channel

    July 2012 21

    18. The browser should display something very similar to the following:

    4.10 Test Your Service

    Now for the fun part! This section will guide you thru the testing of your new service. To test you will

    need a REST Client, there are many availablethe guide is based on the FireFox REST Client plugin

    that is available for free download. ...

    1. Take the URL that was launched in the last step (in my case it is):

    http://server_name:8000/sap/opu/odata/sap/Z_BANK_SERVICE_GEBO5/?$format=xml

    2. Add $metadata after the /BANKGEBO/ in the URL and remove the query string parameters:

    http://server_name:8000/sap/opu/odata/sap/Z_BANK_SERVICE_GEBO5/$metadata

    3. Test the QUERY/GET_ENTITYSET operation. In the URL Replace $metadata? with

    BankCollection?$filter=bankCountry eq 'DE'&sap-ds-debug=true

    http://server_name:8000/sap/opu/sdata/sap/BANKGEBO/BankCollection?$filter=bankCountry

    eq 'DE'&sap-ds-debug=true

    Note: sap-ds-debug is a query string parameter provided by Gateway that helps debugging and testingone of the

    things is does is format the output as HTML making it easier to navigate relationships between entity sets.

  • How To... Create Services Using the OData Channel

    July 2012 22

    4. Test the GET_ENTITY / READ operation. For each bank listed in the BankCollection above

    should be a link to the READ operation:

    5. Click the link to execute the entities get_entity methodthis will display the entitys details:

  • How To... Create Services Using the OData Channel

    July 2012 23

    6. To test the create and update functionality we will need a CSRF token (needed to prevent Cross

    Site Request Forgery attacks)to do this we need to request this token during a read by

    passing in an http header value requesting the token. To pass in a header value we need to use

    the REST Clienthere using the FireFox RESTClient:

    7. Copy the URL used in the test in step 5 above and paste it into the URL input field.

    8. Remove the query string attribute sap-ds-debug=true from the URL.

    9. Click the Headers menu item and select Custom Header:

    10. Enter the name / value as shown below:

    Tip: Check the Save to favorite check box so you can easily add this header for faster testing the next time!

    11. Click the Okay button. You should now see the following:

  • How To... Create Services Using the OData Channel

    July 2012 24

    12. Click the SEND button.

    13. In the Response section at the bottom of the RESTClient copy the value returned for the x-csrf-

    token, shown here outlined in red (note, these token values are generated by the gateway

    server):

    The token will be passed back in when testing the create and update functionality.

    14. Change the value for header attribute x-csrf-token to be the value you copied above, to do this

    just click on the header attribute in the RESTClient you should now see something to the

    following:

    15. Test the UPDATE_ENTITY / UPDATE operation.

    16. Add the content-type header to the Request Headers section. Click the Headers dropdown and

    select Custom Header.

    17. Enter the name/value content-type/application/atom+xml;type=entry:

  • How To... Create Services Using the OData Channel

    July 2012 25

    Tip: Save this as a favorite so you can easily add it again when testing.

    18. Click the Okay button to add the header request.

    19. Switch to the Response Body (Raw) tab and copy the contents there (we will be updating the

    data that was sent back when reading the entity):

    20. Paste the Response Body you just copied into the Request Body section.

    21. Change the Method dropdown to PUT. Your RESTClient should now look similar to the

    following:

    22. To test the update functionality we need to change some of the values in the request body that

    we are sending to the Gateway serverchange the value for street and city:

  • How To... Create Services Using the OData Channel

    July 2012 26

    23. Click the SEND button.

    24. If the update is successful you will get a status code of 204 as shown below:

    25. You can switch the Method back to GET and click the send button again then check the

    response body to see if the values you changed for the update are returned by the read.

    26. Test the CREATE_ENTITY / CREATE operation.

    27. To test the create functionality we need to change the URL to be the same URL you would use

    when testing the GET_ENTITYSET method. All you need to do is remove the ending portion of

    the URL used for the update that starts and ends with parenthesisthe URL should look like

    the following example:

    http://server_name:8000/sap/opu/odata/sap/Z_BANK_SERVICE_GEBO5/BankCollection

    28. Set the Method dropdown to POST.

    29. In the Request Body change the bankID value to be something unique in the system (also, for

    German banks the key must be 8 characters, for US banks the key is 9 characters):

    Note: the important part of this request data is the XML values that you are changesthe rest can be ignored in this

    case.

    30. Your Request should now look similar to the following:

  • How To... Create Services Using the OData Channel

    July 2012 27

    31. Click the SEND button. You should receive back a response status code of 201 if successful:

    32. When the create is successful a call is done to the URL specified in the Location header which

    is the URL used to read the newly created entityyou can see the contents of this call in the

    Response Body:

    33. Congrats! You have successfully created and tested a simple OData service!

    " ABAP OData Data Object DATA: lo_data_object TYPE REF TO /IWBEP/IF_MGW_ODATA_ENTITY_TYP, lo_property TYPE REF TO /IWBEP/IF_MGW_ODATA_PROPERTY.

    "Create a new data object with name Bank lo_data_object = model->create_entity_type( 'Bank' ).

    "Define the properties of the Bank object "IV_ABAP_FIELDNAME is the ABAP dictionary name "IV_PROPRETY_NAME is the OData friendly name lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKS' IV_PROPERTY_NAME = 'bankCountry' ). "Set as a key lo_property->set_is_key( abap_true ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKL' IV_PROPERTY_NAME = 'bankID' ). "Set as a key lo_property->set_is_key( abap_true ).

    lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'BANKA' IV_PROPERTY_NAME = 'bankName' ). lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'PROVZ' IV_PROPERTY_NAME = 'region' ). lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'STRAS' IV_PROPERTY_NAME = 'street' ). lo_property = lo_data_object->create_property( IV_ABAP_FIELDNAME = 'ORT01' IV_PROPERTY_NAME = 'city' ).

    "Bind your structure that represents the above properties lo_data_object->bind_structure( 'BNKA' ).

    DATA: ls_bnka TYPE BNKA, ls_bank_address TYPE BAPI1011_ADDRESS, return TYPE BAPIRET2.

    io_data_provider->read_entry_data( IMPORTING es_data = ls_bnka ).

    * Move data into BAPI structure ls_bank_address-bank_name = ls_bnka-banka. ls_bank_address-region = ls_bnka-provz. ls_bank_address-street = ls_bnka-stras. ls_bank_address-city = ls_bnka-ort01.

    CALL FUNCTION 'BAPI_BANK_CREATE' EXPORTING BANK_CTRY = ls_bnka-banks BANK_KEY = ls_bnka-bankl BANK_ADDRESS = ls_bank_address* BANK_METHOD =* BANK_FORMATTING =* BANK_ADDRESS1 =* I_XUPDATE = 'X' IMPORTING RETURN = return* BANKCOUNTRY = ls_bnka- BANKKEY = ls_bnka-bankl .

    IF ( return-type = 'E'). " throw exception ENDIF.

    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

    copy_data_to_ref( EXPORTING is_data = ls_bnka CHANGING cr_data = er_entity ).

    DATA: lv_string TYPE string, ls_key_tab TYPE /IWBEP/S_MGW_NAME_VALUE_PAIR, lv_and(4), lv_value TYPE string, wa_bnka TYPE BNKA.

    CONSTANTS: con_filler(1) VALUE ''''.

    * Loop over the key values passed in LOOP AT it_key_tab INTO ls_key_tab.

    * surround values with '' CONCATENATE con_filler ls_key_tab-value con_filler INTO lv_value.

    * Change OData key field names to the BNKA table properties name TRANSLATE ls_key_tab-name TO UPPER CASE. IF ( ls_key_tab-name = 'BANKCOUNTRY' ). ls_key_tab-name = 'BANKS'. ELSEIF ( ls_key_tab-name = 'BANKID' ). ls_key_tab-name = 'BANKL'. ENDIF.

    * build where the string CONCATENATE lv_string lv_and ls_key_tab-name '=' lv_value INTO lv_string SEPARATED BY space.* now and is needed. lv_and = 'and'. ENDLOOP.

    * Get the data from table BNKA SELECT SINGLE banks bankl banka provz stras ort01 adrnr FROM BNKA INTO CORRESPONDING FIELDS OF wa_bnka WHERE (lv_string).

    IF sy-subrc EQ 0.* fill the OData structure copy_data_to_ref( EXPORTING is_data = wa_bnka CHANGING cr_data = er_entity ). ELSE. " throw exception ENDIF.

    DATA: lt_bank TYPE TABLE OF BNKA, wa_bnka TYPE BNKA, 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, "banks - is the bank country element lt_range_bank_country TYPE RANGE OF banks, ls_range_bank_country LIKE LINE OF lt_range_bank_country.

    "Loop at the filter options internal table that is passed to this method LOOP AT it_filter_select_options INTO ls_filter_select_options.

    "Loop over the selection options internal table - each filter option can have "more than one selection option LOOP AT ls_filter_select_options-select_options INTO ls_mgw_range_options.

    "Change to uppercase so we don't have to worry about case issues TRANSLATE ls_filter_select_options-property TO UPPER CASE.

    "Check which property is being filtered on, in our case we will "only worry about the BANK_COUTNRY field, but often multiple fields "can be filtered on CASE ls_filter_select_options-property. WHEN 'BANKCOUNTRY'.

    "Setup the range table. MOVE-CORRESPONDING ls_mgw_range_options TO ls_range_bank_country. APPEND ls_range_bank_country TO lt_range_bank_country. ENDCASE. ENDLOOP. ENDLOOP.

    " Select the data from the BANK table into the internal " table SELECT banks bankl banka FROM BNKA INTO CORRESPONDING FIELDS OF wa_bnka WHERE BANKS IN lt_range_bank_country. append wa_bnka to lt_bank. ENDSELECT.

    "Use the helper method to copy the internal table data into the "structure of the OData Service copy_data_to_ref( EXPORTING is_data = lt_bank CHANGING cr_data = er_entityset ).

    DATA: ls_bnka TYPE BNKA, ls_bank_address_x TYPE BAPI1011_ADDRESSX, ls_bank_address TYPE BAPI1011_ADDRESS, return TYPE BAPIRET2.

    * Get the updated bank data io_data_provider->read_entry_data( IMPORTING es_data = ls_bnka ).

    * Move data into BAPI structure ls_bank_address-bank_name = ls_bnka-banka. ls_bank_address-region = ls_bnka-provz. ls_bank_address-street = ls_bnka-stras. ls_bank_address-city = ls_bnka-ort01.

    * Set X on fields that can be updated ls_bank_address_x-bank_name = 'X'. ls_bank_address_x-region = 'X'. ls_bank_address_x-street = 'X'. ls_bank_address_x-city = 'X'.

    CALL FUNCTION 'BAPI_BANK_CHANGE' EXPORTING BANKCOUNTRY = ls_bnka-banks BANKKEY = ls_bnka-bankl BANK_ADDRESS = ls_bank_address BANK_ADDRESSX = ls_bank_address_x* BANK_DETAIL =* BANK_DETAILX =* BANK_ADDRESS1 =* BANK_ADDRESS1X = IMPORTING RETURN = return .

    IF ( return-type = 'E'). " throw exception ENDIF.

    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.

    copy_data_to_ref( EXPORTING is_data = ls_bnka CHANGING cr_data = er_entity ).