Upload
nikki-orial
View
230
Download
5
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 ).