SAP UI5, SAPUI5, SAP Fiori, SAP HTML5, SAP OData, SAPUX, SAPX03, SAPX04, SAPX05, GW100
SAP UI5, SAPUI5, SAP Fiori, SAP HTML5, SAP OData, SAPUX, SAPX03, SAPX04, SAPX05, GW100Full description
A quick guide to create a SAP Gateway service for biginers.Full description
sdasdasddasd
Full description
Arquitectura del SAPDescripción completa
hvac
Flm User Manual_07!08!2018Full description
Study on building services
Building Services Introduction Such as Mechanical,Electrical & Plumbing
Our efficient team of 3D artists and modelers with qualified professionals and engineers work to drive your market endeavors through 3D rendering services.
Full description
Portal Development
SAP Netweaver PI Monitoring Using Solution Manager- Configuration Guide
Project2: Group assignment for the module Building Services (ARC 2423) from the degree programme Bachelor of Science (Honours) Architecture, Taylor's University Lakeside.
GW100 Building OData Services Using SAP NetWeaver Gateway SAP NetWeaver
Date Training Center Instructors Education Website
Trademarks Microsoft, Windows, Excel, Outlook, PowerPoint, Silverlight, and Visual Studio 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, z10, z/VM, z/OS, OS/390, zEnterprise, PowerVM, Power Architecture, Power Systems, POWER7, POWER6+, POWER6, POWER, PowerHA, pureScale, PowerPC, BladeCenter, System Storage, Storwize, XIV, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, AIX, Intelligent Miner, WebSphere, Tivoli, Informix, and Smarter Planet are trademarks or registered trademarks of IBM Corporation. Linux is the registered trademark of Linus Torvalds in the United States and other countries. Adobe, the Adobe logo, Acrobat, PostScript, and Reader are trademarks or registered trademarks of Adobe Systems Incorporated in the United States and other countries. Oracle and Java are registered trademarks of Oracle and its affiliates. 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. Apple, App Store, iBooks, iPad, iPhone, iPhoto, iPod, iTunes, Multi-Touch, Objective-C, Retina, Safari, Siri, and Xcode are trademarks or registered trademarks of Apple Inc. IOS is a registered trademark of Cisco Systems Inc. RIM, BlackBerry, BBM, BlackBerry Curve, BlackBerry Bold, BlackBerry Pearl, BlackBerry Torch, BlackBerry Storm, BlackBerry Storm2, BlackBerry PlayBook, and BlackBerry App World are trademarks or registered trademarks of Research in Motion Limited. Google App Engine, Google Apps, Google Checkout, Google Data API, Google Maps, Google Mobile Ads, Google Mobile Updater, Google Mobile, Google Store, Google Sync, Google Updater, Google Voice, Google Mail, Gmail, YouTube, Dalvik and Android are trademarks or registered trademarks of Google Inc. INTERMEC is a registered trademark of Intermec Technologies Corporation. Wi-Fi is a registered trademark of Wi-Fi Alliance. Bluetooth is a registered trademark of Bluetooth SIG Inc. Motorola is a registered trademark of Motorola Trademark Holdings LLC. Computop is a registered trademark of Computop Wirtschaftsinformatik GmbH.
g201251154345
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer, StreamWork, SAP HANA, 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. Crossgate, m@gic EDDY, B2B 360°, and B2B 360° Services are registered trademarks of Crossgate AG in Germany and other countries. Crossgate 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.
Disclaimer 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.
g201251154345
g201251154345
About This Handbook This handbook is intended to complement the instructor-led presentation of this course, and serve as a source of reference. It is not suitable for self-study.
Typographic Conventions American English is the standard used in this handbook. The following typographic conventions are also used. Type Style
Description
Example text
Words or characters that appear on the screen. These include field names, screen titles, pushbuttons as well as menu names, paths, and options. Also used for cross-references to other documentation both internal and external.
2012
Example text
Emphasized words or phrases in body text, titles of graphics, and tables
EXAMPLE TEXT
Names of elements in the system. These include report names, program names, transaction codes, table names, and individual key words of a programming language, when surrounded by body text, for example SELECT and INCLUDE.
Example text
Screen output. This includes file and directory names and their paths, messages, names of variables and parameters, and passages of the source text of a program.
Example text
Exact user entry. These are words and characters that you enter in the system exactly as they appear in the documentation.
Variable user entry. Pointed brackets indicate that you replace these words and characters with appropriate entries.
Contents Course Overview .......................................................... ix Course Goals ........................................................... ix Course Objectives ..................................................... ix
Unit 1: Gateway Overview and Introduction ......................... 1 Introduction to Gateway ................................................3 Introduction to REST ................................................. 22 Introduction to OData................................................. 30
Unit 2: Gateway Data Model Generator ............................. 61 Generating Data Model for Read ................................... 62 Generating Data Model for Update ................................100
Unit 3: Gateway Service Monitoring ................................ 129 Monitoring Gateway .................................................130
Unit 4: OData Channel Model Provider ............................ 137 Developing Model Provider Class .................................138 Creating Gateway Services.........................................159 Creating Complex Types............................................185
Unit 5: OData Channel Data Provider .............................. 201 Developing Data Provider Class for Read ........................202 Developing Data Provider Class for Update......................233 Using Associations and Navigation Paths ........................263
Unit 6: Front-end Application Development ...................... 281 Consuming Gateway Services .....................................282
Course Overview Target Audience This course is intended for the following audiences: • •
ABAP application developers Business Process developers
Course Prerequisites Required Knowledge • •
BC400 Introduction to the ABAP Workbench BC401 ABAP Objects
Recommended Knowledge • •
BC402 Advanced ABAP Java, JavaScript, HTML
Course Goals This course will prepare you to: • •
Use SAP NetWeaver Gateway to connect to data of a NetWeaver Application Server ABAP. Consume Gateway Services on different platforms and in different programming languages.
Course Objectives After completing this course, you will be able to: • • • • •
2012
Understand the various development and installation options for SAP NetWeaver Gateway. Explain what functionality SAP NetWeaver Gateway do and does not provide. Understand how to generate a Gateway Service starting from an RFC ABAP Function Module or an Object from the Business Object Repository. Develop from scratch your own Gateway Service in ABAP. Consume a Gateway Service using either a Java application or a JavaScript (browser) based application.
Unit 1 Gateway Overview and Introduction Unit Overview This unit provides you with a semi-technical introduction to the Gateway software and how it functions within the wider scope of an SAP system landscape. It covers the different installation options for Gateway, and how each installation option then affects the manner in which Gateway Services are developed. This is followed by an introduction to the concepts of how Gateway services are actually developed. Once developed, a Gateway service can then be consumed by applications written in a wide variety of programming languages. Since the topic of REST and RESTful services is widely talked about in software marketing and the computing press, an entire (short) chapter is provided to explain exactly what REST is – and more importantly, what REST is not. The last lesson of Unit 1 provides a semi-technical introduction to the OData protocol and its history. It shows how XML messages are structured and how they can be interpreted.
Unit Objectives After completing this unit, you will be able to: • • • • • • • •
Understand the high-level architecture of SAP NetWeaver Gateway Understand the different deployment and development scenarios Understand the different development options for creating Gateway Services and consuming Gateway Services Understand what Representational State Transfer (REST) is. Understand how REST has been implemented as HTTP(S). Understand the architecture of the Atom and OData protocols. Understand how SAP NetWeaver Gateway makes use of OData. Understand how to issue read-only OData requests from your browser.
Unit Contents Lesson: Introduction to Gateway ................................................3 Lesson: Introduction to REST .................................................. 22
Lesson: Introduction to OData ................................................. 30 Exercise 1: Getting Started with OData .................................. 51
Lesson Objectives After completing this lesson, you will be able to: • • •
Understand the high-level architecture of SAP NetWeaver Gateway Understand the different deployment and development scenarios Understand the different development options for creating Gateway Services and consuming Gateway Services
Business Example High Level Gateway Architecture
Figure 1: SAP NetWeaver Gateway – High Level Architecture
Gateway sits in between an SAP Business Suite or ECC 6.0 system and the outside world. When we say the “outside world”, what is meant is any software external to the backend Business Suite or ECC system. Typically, this will be some client-based application that consumes an OData service and interacts directly with an end user. However, it is also possible for the Gateway interface to supply information to server-based software, which then forwards the information to one or more client devices. In the case of SAP Workflow events, the Gateway interface can push a workflow event out to some server that consumes the information and then forwards its it to however many client devices have subscribed to that event. The software to consume workflow events coming out of the SAP system is not covered in the GW100 training course. The Sybase Unwired Platform (SUP) software offers a possible solution to event consumption, but is not the only software option a customer could use. Open The OData interface is an open standard that can be consumed by any software or device that can communicate using the HTTP(S) protocol and can parse and construct an XML document. People Gateway has been designed to provide a Business to Consumer (B2C) interface. Although it would be technically possible to use Gateway in a B2B style interface, this would be a use case that lies outside SAP's intended set of use cases for Gateway. Timeless Since the Gateway software has been implemented as a set of ABAP add-ons, these can be deployed to a wide range of SAP Business Systems. Delivery of the Gateway software as ABAP add-ons ensures the minimum level of interference with existing systems. Developers There are two major advantages that come with the use of an OData interface: •
•
4
The OData interface is implemented using either XML or JSON. Both of these formats are well known, plain text protocols for the transmission of information over the Web. Irrespective of the protocol used to transmit an OData message, that message is self-describing. Therefore, any Web developer will be able to understand the message content without needing to have any internal knowledge of how an SAP system works.
In the past, there has always been the issue that in order to consume SAP functionality from an external program over the RFC interface, developers have needed to have at least a basic knowledge of the internal workings of an SAP system. Now however, when taken together, these two factors lower the consumption barrier to the lowest possible level. A developer now needs no knowledge of the internal workings of an SAP system in order to consume a Gateway (OData) service. Standards The Gateway interface implements the OData protocol as described on www.odata.org
OData is a Microsoft developed standard that is built on the existing Atom Publishing and Atom Syndication protocols. •
Prior to development of OData, there were some major standardisation problems with the use of RESTful APIs. This topic will be covered in more detail in chapter 3 where we look at the specific details of OData, and how OData improves on the underlying protocols such as Atom.
•
The term “ODBC for the Web” is conceptually accurate, but there is no sense in which OData allows you to execute an exact SQL statement over the Web. Nonetheless, the OData interface exposes an API that allows collections of entities to be retrieved using syntax that provides a similar level of functionality to that offered by SQL. There is no cost or license agreement needed for the use of OData. The standard is open and can be used by anyone who cares to implement it. One of the reasons SAP chose to implement OData (over Google's GData) was that OData is extensible. This is particularly useful in cases where SAP specific values need to be described in this protocol; for instance, currency fields. A currency field contains two separate values, the currency amount and the currency code. These two values must always be treated as a linked pair, and OData's extensibility allows for this.
• •
Development and Deployment Scenarios
Figure 3: SAP NetWeaver Gateway Deployment Scenarios: 1/3
In the first deployment scenario, the Gateway add-ons are deployed to an independent server that acts as the communication end point for all OData communication. This server is known as the “Gateway Hub” and does not hold any business data. •
In this scenario, the backend server needs to have the IW_BEP component installed. The IW_BEP component allows an ABAP programmer to develop a Gateway service directly in the back end server. This service is then exposed to the outside world through the Gateway Hub server.
The advantage of this development and deployment scenario is that the Gateway Service is developed within the same server wherein the actual business data resides. This development scenario offers the ABAP developer a much greater range of business flexibility. •
This deployment scenario relies on the fact that the customer permits the installation of add-ons into their productive system. It cannot be assumed that all customers will allow this.
Figure 4: SAP NetWeaver Gateway Deployment Scenarios: 1/3
As far as the deployment of SAP NetWeaver Gateway add-ons is concerned, this slide is identical to the previous slide. However, if the customer has no in-house ABAP developers, then it is possible to create Gateway Services using the service generation tool. This tool runs directly in the Gateway Hub and generates a fully functional Gateway service. No ABAP coding is needed.
The generated service is executed in the Gateway Hub server, and relies on the fact that the required functionality is available from the backend server in the form of BAPIs or RFC Function Modules. Alternatively, if a basic ABAP dynpro screen implements the required functionality, then a Gateway Service can be created using screen scraping. For this to work, the IW_SCS component must be installed in the backend system. Either way, no ABAP coding needs to be written.
Figure 5: SAP NetWeaver Gateway Deployment Scenarios: 2/3
There are several situations in which it will not be possible to install the add-ons IW_BEP or IW_SCS into the backend business system. Either: The backend system is the wrong version (too old) to support these add-ons, or The installation of add-ons into the customer's system landscape would necessitate a repeat of some external compliance certification (this is particular true for customers in the defence or pharmaceuticals sectors), or The complexity of the customer's system landscape makes the installation of IW_BEP (and therefore the development of Gateway services directly on the backend server) impractical. Note: IW_BEP can also be installed in the Gateway Hub.
Custom Gateway services can be developed in whichever system contains IW_BEP; the difference here however is that since the custom Gateway Service is running in the Gateway Hub and not directly in the backend, RFC calls will need to be made into the backend system in order to perform the required business functionality. For partner organisations developing their own Gateway Service, it is safe first to assume that IW_BEP cannot be installed in the backend business system. This is known as the non-invasive approach to Gateway Service development. That is, a Gateway Service developed using IW_BEP functionality, but this is for IW-BEP installed in the Gateway Hub, not the backend business system. A Backend Operation Proxy (BOP) is a wrapper that can be generated in the Gateway Hub in order to call an RFC module in the backend system. Such a wrapper is needed in cases where the Gateway Hub server and the backend business system are running on different SAP system versions. Not only this, but very often, the ABAP dictionary fields used to describe an RFC module's interface in the backend business system may well not exist in the Gateway Hub. In these cases it is necessary to have a wrapper generated that uses simple data types to describe the fields in the RFC module's interface. BOPs can be generated by accessing the transaction through the IMG.
2012
•
In this case, the backend system could be any at version back to R/3 4.6C.
•
Since the backend system cannot have any add-ons installed (either because it is too old, or because the customer does not permit it), the Gateway Service will not be able to use any screen scraping or event push functionality offered by IW_SCS and IW_BEP respectively.
Figure 6: SAP NetWeaver Gateway Deployment Scenarios: 3/3
This is known as the all-in-one option. •
•
•
This is where all the Gateway add-ons are installed directly on the backend business system. This scenario is suitable for proof-of-concept development, or the deployment of Gateway Services within an intranet only environment. The backend server must conform to the minimum requirements for a Gateway Hub server, since the backend system has now become the Gateway Hub server. This is scenario is most definitely not recommended for deployment of services to the public internet since this would make the backend server directly accessible from the public internet.
The advantage of having a separate Gateway Hub server is that it sits in your network DMZ and communicates with the backend server through a firewall. This ensures that only the Gateway Hub server is visible to the public Internet and not the actual business system.
Figure 7: SAP NetWeaver Gateway Development Tools: Generators
SAP NetWeaver Gateway content generators do not support direct coding of the Gateway Service. They allow not only the reuse of existing Business Objects or screens but also provide data adaptation capabilities. Data coming from multiple objects can be aggregated, filtered and adapted based on the client application requirements. These generators can be used to generate structures that are then enhanced using the programming tools. Generation of new GW Data Models based on recordings of SAP transaction screens, and enables information from the recorded transactions to be consumed in an OData compliant way. Dynpro based Gateway Services utilize the transaction recorder (Batch Input) in order to capture business processes from the SAP System. However, any dynpros that contain web or ActiveX controls are not supported. The Gateway Service Generator is a tool that will take a BAPI, RFC Module or basic Dynpro as input, and from it create a Gateway service. This option is suitable for prototyping or where ABAP development skills are not available.
Figure 8: Gateway Services Based on RFMs or BOR Objects Overview
The screen shot is taken from the RFC and BAPI Gateway Service Generation Tool. It shows that the individual CRUD operations are mapped to RFC modules.
Figure 9: Gateway Services Based on Screen Scraping Overview
This screen shot is taken from the Screen Scraping Gateway Service Generation Tool. It shows much the same information as the previous slide, except that individual CRUD operations are mapped to screens instead of function modules.
Two of the most frequent use cases for screen scraping are to expose search help functionality and to implement simple button push events for ABAP Dynpros where such functionality has not equivalent over the RFC interface.
Figure 11: Gateway Service Mapping Tool
General features provided by the service mapping tool.
Figure 12: SAP NetWeaver Gateway Development Tools: Good ol' ABAP
ALREADY IN NOTES: The development of custom Gateway services takes place in whichever system component IW_BEP has been installed. This component provides (among other things) the ABAP classes that act as super-types for your own Gateway classes. From the perspective of developing custom Gateway Services, it is important to understand that this type of development takes place in whichever system the component IW_BEP has been installed. For partners developing a Gateway Service that is to be sold to a wide range of SAP customers (i.e. you cannot predict whether the customer will permit the installation of the IW_BEP add-on in their system landscape), the development will take place in the Gateway Hub. However, it could be...
Figure 13: SAP NetWeaver Gateway Development Tools: Good ol' ABAP
... the backend server – as long as the installation of add-ons is permitted.
Figure 14: Gateway Service Architecture (OData Channel) – 1/5
When creating a Gateway Service, two distinct ABAP classes need to be developed. The metadata provider class defines the service's interface. The information provided by this class is used when an external application wishes to consume a Gateway Service. This class provides the consumer with a full description of the entities available from this service and how those entities are associated with each other.
The data provider class provides the actual runtime implementation of the business functionality described by the metadata class.
Figure 15: Gateway Service Architecture (OData Channel) – 2/5
There is no direct programmatic relationship between the model and data provider classes. This may at first seem strange because most developers assume that if the data provider class is going to output information, then it will need to have a reference to the model provider class in order to understand its own interface. In fact, this is not the case. •
The relationship between the data and model provider classes is implemented through configuration, not coding. Two different configuration wrappers need to be created.
A configuration wrapper is created for the model provider class. •
16
And a configuration wrapper is created for the data provider class.
Figure 16: Gateway Service Architecture (OData Channel) – 3/5
ALREADY IN NOTES: The configuration screen asks you to enter the internal service name and then uses this value as the external service name. Be careful to enter the name here that you want the end user to see. There is no need to start the internal service name with a Z character, and remember that the value you enter is case-sensitive. When the configuration wrapper for the data provider class (Service Group) is created, you need to supply an internal service name. • •
The internal and external service names are important because The name you specify for the internal name is copied to the external name
Also, the external name becomes the name seen by the user in the URL when addressing the Gateway Service from outside the SAP system. It is very important therefore that the external name is relevant and meaningful for the end user. This means that the name used for the internal name must also be relevant and meaningful to the end user. In other words, do not use a name starting with Z or some other technical internal name.
Figure 17: Gateway Service Architecture (OData Channel) – 4/5
Once you have created the two configuration wrappers, these are associated with each other by a further configuration step, and you have a Gateway Service. However, that service is not quite ready to use.
Figure 18: Gateway Service Architecture (OData Channel) – 5/5
ALREADY IN NOTES: Creating an entry in the Service Catalog takes place in whichever SAP system has the GW_CORE component. This may well be a different system than the one in which you developed the Gateway Service.
The final step is to create a Service Catalogue entry. This is done in whichever server acts as the Gateway Hub – which depending on which deployment scenario you are using, may, or may not, be the same system in which the Gateway Service was developed. •
After the Service Catalogue entry has been created, the Gateway Service can be accessed from some external client device or browser.
Gateway Service Consumption
Figure 19: Consuming a Gateway Service: General Approach
ALREADY IN NOTES: SAP does not make any recommendations or impose any restrictions on which development language should be used for the consumption of a Gateway service. You can use any language with which you are familiar so long as that language has facilities for HTTP(S) communication, and can construct and parse an XML document. Beyond that, you are free to use any language you like.
Figure 20: Consuming a Gateway Service: IDE Plug-Ins
ALREADY IN NOTES: The Gateway consumption tools will create a proxy object that wraps access to a Gateway service. This object can then be used in your own application. Optionally, the consumption tools will also generate a basic application that makes use of the generated proxy object. The Gateway consumption tools are not designed to generate fully functional applications. Instead, they are designed jump start your development process by creating a basic, but functional application that can then be used as the starting point for the development of your own application. The Gateway consumption tools are available for the following languages: • • •
Java C# Objective C
SAP offers various tools for OData proxy objects in Java, C# and Objective C. These proxy objects can then be included in a client device application. •
20
Nonetheless, the use of these tools is not mandatory. On the www.odata.org website, many different OData libraries can be downloaded for a wide variety of languages.
Lesson Summary You should now be able to: • Understand the high-level architecture of SAP NetWeaver Gateway • Understand the different deployment and development scenarios • Understand the different development options for creating Gateway Services and consuming Gateway Services
ALREADY IN NOTES: The term “Representational State Transfer” or REST was first introduced by Roy Fielding in his doctoral dissertation “Architectural Styles and the Design of Network-based Software Architectures ” published in 2000. •
•
•
REST is not a network protocol! Nonetheless, there is a widespread misunderstanding that REST is some kind of network protocol and you will often see boxes or arrows in system block diagrams labelled “REST”. Such diagrams are just simply wrong! REST is a set of six architectural constraints, or design principles. Anyone so motivated could build a RESTful software system. As long as the software is designed to follows these standards, your home-grown software will be genuinely RESTful. The World Wide Web is the best example of a RESTful system.
Figure 22: The Architectural Constraints of REST - 1/6
The example of client and server software being developed independently is demonstrated by the fact that browsers are developed and released independently of webservers.
Figure 23: The Architectural Constraints of REST - 2/6
When a browser communicates with a proxy server, it does so in exactly the same way as it would if it were communicating directly with the target webserver. This is an example of the layering principle in REST.
Figure 24: The Architectural Constraints of REST - 3/6
Stateless communication is one of the defining features in RESTful communication. This constraint however is often misunderstood to mean that the server never holds any form of state information about the client. This is not the case though: if the server chooses to hold state information about the client, that's fine. It's just that the client must always know and be always be able to identify the session state held by the server. This is typically achieved in a browser by setting a session state cookie.
Figure 25: The Architectural Constraints of REST - 4/6
A uniform interface is one that always means the same thing to the participants at all times. Firstly the server has to provide the client with some consistent representation of a resource it is holding. In OData, this achieved by the server sending an XML or JSON message to the client that conforms to a known syntax and structure. •
Once the client has received a representation of the server side resource, the client must additionally have some means for altering the state of (or manipulating) that resource.
This is where the CREATE, READ, UPDATE, DELETE operations have been defined, since these four operations are the most fundamental that can be performed by a client on a server-side resource. •
•
2012
A RESTful response sent to a client must not be structured in such a way that the client needs to make subsequent request to the server to provide further clarification or explanation of what the information in the first message meant. In other words, all REST communication must be self-describing. A hypermedia link is defined as the only acceptable mechanism by which the client can manipulate a server-side resource.
This one principle has been isolated and given the acronym HATEOS, or “Hypermedia As The Engine Of Application State” •
HATEOS is generally regarded as the core concept of REST.
Figure 26: The Architectural Constraints of REST - 5/6
In order to improve communication efficiency, servers should define that transmitted information is cacheable. In this way, if a client requires the same information again, it can look in its local cache to find it rather than issue duplicate network requests.
Figure 27: The Architectural Constraints of REST - 6/6
If a client detect that it does not have the correct capability to handle the information is has (or is about to) receive, it can make a request to server send is some executable coding that will extend its functional capability. This is an academic way of describing what happens when a browser requests a JavaScript file etc.
HTTP - An Implementation of the Principles of REST
Figure 28: HTTP(S) - An Implementation of the REST Constraints
ALREADY IN NOTES: There is much more that could be said about how HTTP implements the principles of REST; however, the key point here is to understand that HTTP(S) provides you with the ability to manipulate server-side resources through the use of the methods GET, PUT, POST and DELETE. The HTTP protocol that drives the World Wide Web is an example of a fully RESTful communication system. The four fundamental operations are described using the acronym CRUD.
Lesson Summary You should now be able to: • Understand what Representational State Transfer (REST) is. • Understand how REST has been implemented as HTTP(S).
Lesson: Introduction to OData Lesson Overview This lesson covers: • •
The architecture of the Atom and OData protocols • How SAP NetWeaver Gateway makes use of OData How to issue read-only OData requests from your browser
Lesson Objectives After completing this lesson, you will be able to: • • •
Understand the architecture of the Atom and OData protocols. Understand how SAP NetWeaver Gateway makes use of OData. Understand how to issue read-only OData requests from your browser.
Business Example Atom and OData
Figure 30: What is the Open Data Protocol (OData)?
OData is a Microsoft developed standard that is built on the existing Atom Publishing and Atom Syndication protocols. •
Prior to development of OData, there were some major standardisation problems with the use of RESTful APIs. This topic will be covered in more detail in chapter 3 where we look at the specific details of OData, and how OData improves on the underlying protocols such as Atom.
•
The term “ODBC for the Web” is conceptually accurate, but there is no sense in which OData allows you to execute an exact SQL statement over the Web. Nonetheless, the OData interface exposes an API that allows collections of entities to be retrieved using syntax that provides a similar level of functionality to that offered by SQL. There is no cost or license agreement needed for the use of OData. The standard is open and can be used by anyone who cares to implement it. One of the reasons SAP chose to implement OData (over Google's GData) was that OData is extensible. This is particularly useful in cases where SAP specific values need to be described in this protocol; for instance, currency fields. A currency field contains two separate values, the currency amount and the currency code. These two values must always be treated as a linked pair, and OData's extensibility allows for this.
• •
For more detailed information, please refer to http://www.odata.org
The Atom Syndication format is the foundational protocol that does little more than provide an XML description of: • • •
Various documents that are available from a website Each document is structured as a “feed” Within a “feed, the consumer will find zero or more units of information known as ”entities
The Atom Publishing protocol that allows the XML data provided by Atom Syndication to be manipulated using HTTP. The problem with both of these Atom formats is that they do not provide a mechanism for describing the data being transported. In other words, they offer no facility for providing a metadata description of the data they provide.
Figure 32: What Does OData Add to Atom?
OData adds the ability to define the metadata of an Atom message. This in turns means that an OData message can now be consumed by an external service without that service first needing to know the message's structure. In other words, the Atom feed can now provide the consumer with a description of itself.
ALREADY IN NOTES: Although it is not as convenient as JSON, languages such as JavaScript can consume XML format messages using libraries such the one found at http://datajs.codeplex.com The consumption of a Gateway XML message directly in JavaScript is also documented in the SAP How To Guide “How To: Consume A Gateway Service From JavaScript”. http://www.sdn.sap.com/irj/sdn/gateway?rid=/library/uuid/505619a7-73bf-2e10fe96-da9a86b23120 • •
2012
The Gateway server will be able to output an OData message in JSON format once SP4 is installed and the kernel has been patched. In SP3 and earlier, a Gateway system can only out OData messages in XML format.
Figure 34: OData Service Documents - The Starting Point
The starting point for consuming an OData service is to issue the URL for the service's Service Document. The Service Document provides the top-level description of an OData service.
Figure 35: OData Service Documents - General Structure
The XML received in the OData Service Document is always structured with a element as the root element, under which in a element. Within the element is a single element followed by zero or more elements.
Figure 36: An Example of an OData Service Document - 1/3
Figure 37: An Example of an OData Service Document - 2/3
Figure 38: An Example of an OData Service Document - 3/3
Figure 39: Accessing an OData Collection - Construct the URL
The URL used to derive an OData service's Service Document is known as the “Base URL”. When working with an OData message in XML format (as opposed to JSON format), the base URL is always listed as the xml:base parameter of the element. Within the Service Document, the URLs that point to collections provided by that service are listed as URLs relative to the base URL.
The metadata description of an OData service is used by the SAP Gateway Consumption Tools when generating an OData proxy object in some language like Java or C#.
Figure 52: Retrieving a Partial Collection - Filtering
Figure 53: Retrieving a Partial Collection - Paging
The $top command specifies how many entries are to be returned. Unless used in conjunction with the $skip command, these entries are always taken from the top of the collection. The $skip command omits the specified number of entries starting from the top of the collection. By using both $top and $skip together, you can implement paging. View the first page by showing only the top 10 entries. View the second page by skipping the first 10 entries and showing only the next 10.
View the third page by skipping the first 20 entries and showing only the next 10. The OData website contains more information on this topic.
The READ Operation
Figure 54: Retrieving a Single Entry - ReadEntity Operation 1/2
The syntax for reading a single entity from a collection is provided with the first element found within an element.
Figure 55: Retrieving a Single Entry - ReadEntity Operation 2/2
Notice that the syntax for defining the element to be read is not the normal query string syntax. Instead you must create what is called a “Key Predicate”. This is a comma-separated list of name/value pairs enclosed within parentheses.
Any non-numeric value within a key predicate must be given as a quoted string.
Figure 56: XML Returned by ReadEntitySet and ReadEntity - 1/2
A QUERY operation will return zero or more entries. Therefore, the XML will always be enclosed within an element. If the QUERY operation locates an entries, these are supplied within elements inside the element.
Figure 57: XML Returned by ReadEntitySet and ReadEntity - 2/2
If a READ operation is performed, then at most, a single entry will be returned. Therefore, the XML will be supplied as a single element – even if zero entries are found.
The OData and Atom standards use different terminology to describe the same objects. These terms can be used interchangeably; however, in the XML, the Atom terminology is used, and within the ABAP coding used for creating custom Gateway services, the OData terminology is used.
Figure 63: Displaying Atom XML in your Browser
MIME stands for “Multipurpose Internet Mail Extension”. Its use has grown far beyond the original concept of extending emails to support content in non-ASCII character sets, binary attachments and multi-part messages. Now, the MIME type is universally used to identify the type of content being supplied to the client. The client then examines the MIME type and determines how that content should be processed.
Exercise 1: Getting Started with OData Exercise Objectives After completing this exercise, you will be able to: • Investigate OData information supplied by a Gateway service
Business Example You wish to perform an initial investigation on how consume a business service provided by a backend business system through an OData interface. These exercises are designed to help you become familiar with OData XML. Therefore, you will need to use a browser that does not format the OData response, but instead, shows you the raw XML. You should not use Firefox or Safari for these exercises because they automatically format the response; instead, you should use either Internet Explorer or Chrome.
Task: 1.
First Steps With OData In this exercise you will examine the basic structure of an OData Service Document. Question: Using nothing more than the relative URLs supplied in the OData XML, how could we obtain a list of all flights that depart from a certain airport? Answer: Do the next exercise! :-)
2.
Using OData Links In this exercise you will become familiar with the use of OData navigation links.
3.
OData Metadata In this exercise, you will start to become familiar with the metadata supplied by an OData service.
First Steps With OData In this exercise you will examine the basic structure of an OData Service Document. Question: Using nothing more than the relative URLs supplied in the OData XML, how could we obtain a list of all flights that depart from a certain airport? Answer: Do the next exercise! :-) a)
Open a browser and display the Service Document for the FlightInfomation service on the public SAP NetWeaver Gateway Server. The URL is: http://gw.esworkplace.sap.com/sap/opu/odata/sap/FlightInformation/ You will be asked for a user id and password: User: gwdemo Password: DEMO4GW You should see some XML like the following: DataFlightsFlightBookingsBookingAirportsAirport
Look in the root . The service’s base URL is shown here in the xml:base parameter.
c)
Now display the “Airports” collection. To do this, locate this collection’s relative URL and append it the base URL to construct the URL for this collection.
d)
Now repeat step c), but this time for the “Flights” collection.
e)
Question: Using nothing more than the relative URLs supplied in the OData XML, how could we obtain a list of all flights that depart from a certain airport? Answer: Do the next exercise! :-)
2.
Using OData Links In this exercise you will become familiar with the use of OData navigation links. a)
Display the contents of the “Airports” collection.
b)
Within the Atom element returned for this collection, you will see multiple elements. Select an element and within it, look for the elements.
c)
Locate the href parameter belonging to the first element. This is always a self-reference that identifies the current entry. Modify the URL in the browser’s address line so that only this single entry is returned.
d)
You should now see a single element describing that one airport. E.G. Here is the entry for Frankfurt airport:
Continued on next page
Within the element you will see an element. What properties does an Airport have? ___________________________________________________________ Are these properties all simple types? ___________________________________________________________
f)
Locate the href parameters of the second and third elements. Judging by the value of the title parameter for each link, what type of information would you say these links return? Continued on next page
In the browser’s address line, issue the URL derived from the value of the third link parameter (called DepartingFlights).
h)
You are now looking at a list of all the flights that depart from the selected airport.
i)
Question: From a business perspective, what have you been doing here? (And don’t say “Following hypertext links”) Answer: The FlightInformation data model that sits behind this OData interface has defined within it, multiple entity types such as “Flight” and “Airport”. These entity types are associated with each other, and these associations are implemented by means of “navigation links”. From a business perspective, a navigation link allows a user to walk through the data in the data model without needing to calculate how to take the next step. This is an example of the HATEOS principle at work and brings significant ease of use to the end user.
3.
OData Metadata In this exercise, you will start to become familiar with the metadata supplied by an OData service. a)
From your browser’s address line, issue the OData service’s base URL again, but this time append the command $metadata. You should see quite a large amount of XML that looks similar to this:
Continued on next page
The element for “Airport” has multiple properties, but only one of those properties (“IATACode”) has been defined as a key field. An OData entity type is exactly the same as an ABAP dictionary structure, and the entity set (or collection) formed from multiple instances of the entity type is exactly the same as a database table definition.
c)
56
Look at the metadata describing the Airport entity type. There are 5 properties, one of which is nominated to be the key. Continued on next page
There are also 2 elements. These two elements define the ability for a user to see, for instance, all the flights that leave from any particular airport. But how is this relationship defined? Are the entity types directly related to each other in the navigation property? ___________________________________________________________ Is some other definition used in the declaration of the Navigation Property? ___________________________________________________________ d)
The element within the Airport refers to two roles. Where are these defined? Hint: Look further down the XML at the elements. Locate the correct element referred to by the and inside it, you will find two elements. Each element gives a name to the association (specified by the role parameter), the entity type involved in the association and the cardinality (or multiplicity) as seen from that end of the relationship.
e)
Continue looking down the XML until you see a group of elements. An element defines the name of the aggregation formed from a particular entity type. Here is where the existence of a collection is declared. E.G. An aggregation called “Airports” is formed from the entity type “flightinformation.Airport”. (An entity type is referenced using its fully qualified name). Generally, the entity set name will simply be the plural of the entity type name, but this is only a convenience for the end user, not a semantic requirement. Collections created automatically usually have the word “Collection” appended to the entity type name. Also, you may often see the term “Collection” used in place of “Entity Set” and the term “Entry” used in place of “Entity”. These terms are interchangeable.
The terms “Collection” and “Entry” belong to Atom terminology, whereas the terms “EntitySet” and “Entity” belong to OData terminology. f)
Now look further down the XML and locate the elements. The difference here is that an element declares that two entity types are related, but an element declares that two entity sets are related. You should now have a good working understanding of the XML used to communicate an OData message and also the XML used to describe an OData message (i.e. the metadata).
Lesson Summary You should now be able to: • Understand the architecture of the Atom and OData protocols. • Understand how SAP NetWeaver Gateway makes use of OData. • Understand how to issue read-only OData requests from your browser.
Unit Summary You should now be able to: • Understand the high-level architecture of SAP NetWeaver Gateway • Understand the different deployment and development scenarios • Understand the different development options for creating Gateway Services and consuming Gateway Services • Understand what Representational State Transfer (REST) is. • Understand how REST has been implemented as HTTP(S). • Understand the architecture of the Atom and OData protocols. • Understand how SAP NetWeaver Gateway makes use of OData. • Understand how to issue read-only OData requests from your browser.
Unit 2 Gateway Data Model Generator Unit Overview In this unit, you will learn how to create a Gateway service using the generator tool. This process requires no knowledge of the ABAP programming language; however, it does require the user to have a good understanding of the business process being delivered. You will start by creating a Gateway service that offers read-only capabilities, then you will add update and create capabilities.
Unit Objectives After completing this unit, you will be able to: • • • • • •
Create a read-only Gateway Service based on a Remote Function Module or an Object in the Business Object Repository (BOR). Expose a Gateway Service for consumption. Test your Gateway Service from a browser. Extend an existing RFM or BOR based Gateway Service to include update functionality. Understand the danger posed by Cross-Site Request Forgery attacks and how the SAP NetWeaver Gateway Server prevents them. Test the new functionality of your Gateway Service from a browser.
Unit Contents Lesson: Generating Data Model for Read .................................... 62 Procedure: Generate a Gateway Data Model ........................... 65 Exercise 2: Generate a Read-Only Gateway Service .................. 83 Lesson: Generating Data Model for Update.................................100 Procedure: Change a Gateway Data Model ............................101 Exercise 3: Extend a Generated Gateway Service to Include Update Functionality ................................................................. 115
Lesson: Generating Data Model for Read Lesson Overview This lesson covers: • • •
Create a read-only Gateway Service based on a Remote Function Module or an Object in the Business Object Repository (BOR) Expose a Gateway Service for consumption Test your Gateway Service from a browser
Lesson Objectives After completing this lesson, you will be able to: • • •
Create a read-only Gateway Service based on a Remote Function Module or an Object in the Business Object Repository (BOR). Expose a Gateway Service for consumption. Test your Gateway Service from a browser.
Business Example Remote Function Calls and Business Object Repository Overview
Exercise 2: Generate a Read-Only Gateway Service Exercise Objectives After completing this exercise, you will be able to: • Create a Gateway service providing read-only functionality.
Business Example You need to provide a Gateway service that provides a Bank information lookup service. Log on to the Gateway training system using the userid and password supplied to you by your trainer. Whenever you need to create a new model or class, always append your group number to the name to ensure the name remains unique. All ABAP development is being done using the package $TMP (Local Object)
Task: 1.
Create a Gateway Data Model
2.
Create a Gateway Consumption Model There are two ways to create a Gate Consumption Model. You can either create it as an independent object, which in a second step, is then assigned to the Data Model, or from within the Data Model itself, you can create and assign the Consumption Model in a single step. Here we will take the two-step approach.
3.
Assign Data Model to Consumption Model
4.
Assign System Alias to Gateway Service
5.
Test the Gateway Service in a Browser
6.
Correct the Data Model Configuration To discover the error, we must look back at our Data Model definition.
7.
Performing a READ Operation So far, all we have done is to build a faulty Gateway Service and then correct it. This service has two operations, QUERY and READ, but up till now, we have used only the QUERY operation.
Solution 2: Generate a Read-Only Gateway Service Task: 1.
Create a Gateway Data Model a)
Run transaction SE80 (ABAP Development Workbench)
b)
Select “GW Data Model” from the drop-down list and enter the name of a new Data Model. The name will be Z_GW100_RFM_BANK_ where nn is your group number.
Figure 105: Data Model
c)
After confirming that you want to create a new object, enter the Data Model name, a Type of “PS” and select the “Generate from Data Source Object” radio button.
d)
Do not switch off the “OData Channel” checkbox. If you do, the Gateway Service will be generated using the older Generic Channel class hierarchy, which will create several problems: 1.
The rest of the instructions in this document will not function correctly. Continued on next page
None of the newer debugging facilities will be available to you.
On the next pop-up screen, enter the following values: •
A description such as “GW100 Bank Demo – Group nn”
•
A Data Source Type of “2 Remote Function Calls”
•
A System Alias of LOCAL
f)
Save all your objects as Local Objects ($TMP).
g)
SE80 will now take you to the Gateway Modelling Tool. Here use the Binoculars button to search for the Bank related BAPIs. Use the search patter BAPI*BANK*.
h)
Select BAPI_BANK_GETLIST and then click the Create Mapping button on the right side of the screen .
i)
Select “Query” from the Operation Type drop down menu and then press the green tick icon at the bottom right of the screen .
j)
Your data model interface now contains the fields supplied by the BAPI_BANK_GETLIST function module. We must now nominate which of those fields define the model’s key. Right click on BANK_CTRY and set it as a key field. Repeat this process for field BANK_KEY
From the search results list on the left, select BAPI_BANK_GETDETAIL and press Create Mapping.
l)
Select an Operation Type of Read and uncheck the BANK_DETAIL and RETURN data structures. We will not be using these.
m)
Right click on BANKCOUNTRY and select “Change Mapping Route”. Caution: Remember: right clicking on the field selects it without switching off the selection check box.
n)
Map BANKCOUNTRY to the model key field BANK_CTRY
o)
Map BANKKEY to the model key field BANK_KEY
p)
Now the BANK_ADDRESS data structure needs to be flattened. To do this, right click on each field in the BANK_ADDRESS data structure (apart from BANK_NAME and CITY) and press “Change Mapping Route”.
q)
In the Change Mapping Route pop-up, select the root node of the OData Service interface.
Figure 107: Change Mapping Route
r)
After each property of the BANK_ADDRESS structure has been reassigned to the root node of the OData Service’s interface, your mapping structure will look like this.
Press F3 or Back on the toolbar to return to the SE80 screen. In the name field underneath “GW Data Model” you will see the name of the generated data model. Copy this value into the clipboard, as you will need it in the following step.
Figure 111: GW Data Model
2.
Create a Gateway Consumption Model There are two ways to create a Gate Consumption Model. You can either create it as an independent object, which in a second step, is then assigned to the Data Model, or from within the Data Model itself, you can create and assign the Consumption Model in a single step.
From the drop down menu in which “GW Data Model” is displayed, select “GW Consumption Model”. Enter a name of Z_GW100_BANK_CM_nn where CM indicates “consumption model” and nn is your group number. Press enter to create this new model.
b)
Whatever name you enter into the “Service Technical Name” field will become the Gateway Service name used by an external consumer. Therefore, don’t use an ABAP class name or some other internal value. So choose the name carefully – it should be relevant and meaningful to someone with no knowledge of an SAP system.
Figure 112: Consumption Model
Do not switch off the “OData Channel” checkbox! If you do, your consumption model will use the old Generic Channel runtime, thus making it incompatible with the Data Model we just created, which uses the OData Channel runtime. Due to the fact that we are using a generated service in a training environment, certain constraints are in operation here. In our case, the service name must start with a Z because we are using customer namespace, and secondly, to avoid name collisions with the services created by other students, we must add a group number to the end of the name.
Once the Consumption Model has been created, the Data Model needs to be assigned to it. Right click on the consumption model name and select “Add GW Data Model”. Now paste in the name of the data model you copied in section 1, step 19.
Figure 113: GW Data Model 1/2
b)
Once the Data Model has been assigned, your Consumption Model will look like this.
Figure 114: GW Data Model 2/2
4.
Assign System Alias to Gateway Service a)
The Gateway Service is not quite ready to execute yet. The last step is to assign a System Alias to the Gateway Service.
b)
Start transaction /IWFND/MAINT_SERVICE. Here you will see a list of all Services known to this Gateway server.
c)
Click the column header for “External Service Name” and sort the table. This will help you locate you service faster.
Select your service in the table and examine the properties in the lower two panes.
Figure 116: ICF Nodes
The pane on the left shows that a node in the ICF has been created, but the pane on the right shows that the Gateway Service does not yet have a system alias assigned to it. e)
Click the “Add System Alias” and in the next screen click “New Entries”.
f)
You now need to enter the name of the “Service Document Identifier”. This name is the external service name followed by the version number. So using the name defined in step 21, this will be Z_BANK_INFO_nn_0001 (where nn is your group number).
Figure 117: Added Entries
g)
Save your changes and return to the /IWFND/MAINT_SERVICE screen.
h)
You service now has a System Alias assigned.
Figure 118: ICF Nodes
5.
Test the Gateway Service in a Browser Continued on next page
Test the service by pressing the “Call Browser” button.
b)
You will be asked to provide your userid and password in order to run the Gateway Service.
Figure 119: Gateway Service in a Browser
c)
The Gateway Service Document will now be displayed
Figure 120: Gateway Service Document
d)
Look at href parameter of the element in the returned XML. The Bank collection name is z_gw100_rfm_bank_01Collection. Notice that the uppercase service name used in the SAP system has been translated to lower case here and used to form the collection name.
In the browser’s address line, add the collection name to the end of the Service Document’s URL and press enter.
Figure 121: Gateway Service Document
e)
This error should not be surprising, because we know that the function module BAPI_BANK_GETLIST has BANK_CTRY as a mandatory input field and we have made no attempt to supply the required value – so it blows up in our face. Before we add the $filter parameter needed to pass in a value for BANK_CTRY, we must first check what name this required input parameter has in the OData interface. This is important because all collection and field names in OData are case-sensitive. To do this, remove the collection name from the URL and replace it with the $metadata command and press enter.
Figure 122: Gateway Service Document
f)
In the element, we can see that two fields are defined. From our knowledge of the business case, we know that for the QUERY operation, only bank_ctry is needed. The other field, bank_key, is a key field, but is needed only for the READ operation.
In the URL in the browser’s address line, remove $metadata and replace it with a query string containing the $filter command and press enter. /z_bank_info_01/z_gw100_rfm_bank_01Collection? $filter=bank_ctry eq 'US' Caution: •
• • • •
g)
The $filter command is a normal URL query string parameter; therefore, if this is the first value in the query string, you must start with a “?” question mark character; or, if this is a subsequent query string parameter, you must use the “&” ampersand separator character. The field name bank_ctry is case-sensitive. The operator (eq, gt, lt, ne etc) must be specified in lower case. The operator must have a space character or %20 on either side. Any non-numeric value must be enclosed in single quotes. If you are copying and pasting the string from a formatted document, make sure that the straight quote character ' has not been substituted for the “smart” quotes ‘ and ’.
This is not what we were hoping for!
Figure 123: Gateway Service Document
Why has this request failed? Keep this browser window open – we will need to refresh it after correcting the error. 6.
Correct the Data Model Configuration Continued on next page
To discover the error, we must look back at our Data Model definition. a)
Rerun transaction SE80.
b)
Select “GW Data Model” and your Data Model name should reappear in the input field. Press enter to display this object. If the name does not reappear, then you can construct it using the following __ will be Z_GW100_RFM_BANK_nn is always 0001 is PS
c)
Double click on the Data Model name in the hierarchy view and then press the Gear icon that appears in the tool bar
.
d)
Switch into Change Mode, select the QUERY operation on the right side of the screen and then press Change Mapping.
e)
Notice that the BANK_CTRY field has no mapping route assigned? This means that this particular field has not been added to the OData Service’s interface. So even though we know it is a key field and have attempted to assign a value to it using the $filter command in the URL, all such attempts will fail because this field does not exist in the interface. Right click on BANK_CTRY to select it and press the “Change Mapping Route” button.
This service has two operations, QUERY and READ, but up till now, we have used only the QUERY operation. a)
Look at the XML generated from the above successful QUERY operation. Inside each element, towards the end, you will an element. This element is a self reference to the current . Select the contents of this element and paste it into the browser’s address line.
b)
Simply by specifying the exact parameters needed to identify a single bank, you have implicitly instructed the Gateway Service to perform a READ operation instead of the QUERY operation.
Figure 127: Gateway Service Document
c)
Notice the difference in the XML returned by the QUERY and READ operations. When you perform a QUERY operation, you will receive zero or more Atom entries; but when you perform a READ operation, you will receive zero or one entry. This difference means that not many how many or few entries a QUERY operation returns, the results will always be container within an element. In contrast, the READ operation will only ever return a single element – even if it has no contents. This completes the exercise on creating and testing a read-only Gateway Service using the Generator Tools.
Lesson Summary You should now be able to: • Create a read-only Gateway Service based on a Remote Function Module or an Object in the Business Object Repository (BOR). • Expose a Gateway Service for consumption. • Test your Gateway Service from a browser.
Lesson: Generating Data Model for Update Lesson Overview This lesson covers: • • •
Extend an existing RFM or BOR based Gateway Service to include update functionality Understand the danger posed by web-based attacks (CSRF) and how the SAP NetWeaver Gateway Server prevents them Test the new functionality of your Gateway Service from a browser
Lesson Objectives After completing this lesson, you will be able to: • • •
Extend an existing RFM or BOR based Gateway Service to include update functionality. Understand the danger posed by Cross-Site Request Forgery attacks and how the SAP NetWeaver Gateway Server prevents them. Test the new functionality of your Gateway Service from a browser.
Cross-Site Request Forgery Attacks At this point, we must take a digression away from the Gateway development process in order to understand how to protect web-based applications from attack. Whenever a web-based application is run, certain levels of trust are set up between the user and the webserver with which they are interacting. There are two attacks that both work by exploiting this trust relationship…
CSRF attacks can be prevented by sending any non-guessable value (known as a token) to the user once they have logged on. The token is stored as a cookie and must be returned in all subsequent requests. The attacker can deduce that such a token is required, but cannot possibly know the token’s value because the coding to generate the fraudulent request executes on the hacker’s webserver – where it has no access to the browser’s cookies.
Exercise 3: Extend a Generated Gateway Service to Include Update Functionality Exercise Objectives After completing this exercise, you will be able to: • Extend the Gateway service created in the previous exercise to include create and update functionality.
Business Example You need to provide a Gateway service that provides not only Bank look up information, but allows users to create and edit Bank information. Log on to the Gateway training system using the userid and password supplied to you by your trainer. Whenever you need to create a new model or class, always append your group number to the name to ensure the name remains unique. All ABAP development is being done using the package $TMP (Local Object) In order to complete this exercise, you must first have successfully completed Exercise 2 – Generating a Read-Only Gateway Service. Testing the functionality added in this exercise will be performed using the RESTClient add-on installed in the Firefox browser.
Solution 3: Extend a Generated Gateway Service to Include Update Functionality Task: 1.
Edit Your Existing Gateway Data Model a)
Run transaction SE80 (ABAP Development Workbench)
b)
Select “GW Data Model” from the drop-down list and the name of your Data Model should appear in the input field. If it does not, you can construct the name using the following pattern: Z_GW100_RFM_BANK__0001_PS where is your group number.
c)
When the object hierarchy is displayed, double click on the root node (the GW Data Model name). This will display the Data Model’s properties on the right side of the screen. In addition to showing the object’s properties, a “gear wheel” icon will appear in the toolbar. Clicking this will take you to the Gateway Mapping Service Tool.
Figure 160: Gear Wheel Icon
d)
Switch to change mode.
e)
Press the binoculars icon and search for BAPI*BANK*.
f)
First, select the BAPI_BANK_CHANGE function module and click the Create Mapping toolbar button on the right side of the screen.
The mapping tool pop-up window now opens. Select “Update” from the drop down list.
Figure 162: Update
h)
As soon as this selection is made, the mapping tool automatically exposes the RFM’s two key fields to the OData interface, but does so using their existing field names. However, we have already nominated the BANK_CTRY and BANK_KEY fields belonging to the QUERY and READ operations to be the Data Model’s key fields. Therefore, you must correct the mapping of these two fields to point to the model’s key fields: BANKCOUNTRY → BANK_CTRY BANKKEY → BANK_KEY The field mapping should now look like this
Hint: Remember: right clicking on the field selects it without switching off the selection check box. i)
Deselect all non-mandatory parameter fields and structures. The second check box column indicates whether a parameter is mandatory or not.
j)
When we created the READ operation, we needed to map each field in the BANK_ADDRESS data structure to the Data Model’s root node. Without this step, we would have had to make a second HTTP request in order to retrieve the data within this data structure. The normal sequence of processing steps is that a user will first perform a READ operation, modify the data, and then perform an UPDATE operation. In order to allow the data coming out of the READ operation to be passed into the UPDATE operation, we must ensure that the BANK_ADDRESS fields belonging to the input side of BAPI_BANK_CHANGE are mapped to the same Data Model fields that the READ operation populates. For each field in the BAPI_BANK_CHANGE’s input data BANK_ADDRESS do the following: 1. 2. 3. 4.
Right click on the field name to select it without switching off the selection checkbox. Click “Change Mapping Route” In the pop-up window, map the RFM field to the corresponding Data Model field name directly under the root node. Press the green tick icon in the bottom right of the screen to complete the mapping.
From the list of function modules on the left of the screen, select BAPI_BANK_CREATE, press the Create Mapping button and map it to the Create operation.
l)
Repeat the mapping process described above, being careful to check that: 1. 2. 3.
4.
The input fields BANK_CTRY and BANK_KEY are mapped to the model key fields of the same name. All the fields in the BANK_ADDRESS input structure are mapped to the model fields below to the root node. The output fields BANKCOUNTRY and BANKKEY are mapped to the data model directly under the root node. These fields are not used in our scenario, but since they contain the key values of the Bank we have just created, should be kept for the sake of completeness. All other non-mandatory RFM interface fields are deselected.
In the SE80 display of your GW Data Model, expand the “Related GW Consumption Models” branch and double click on the consumption model name.
b)
In the properties view to the right, copy the service document URL to the clipboard.
Figure 166: Service Document URL
c)
Start Firefox and paste your Gateway Service Document URL into the address line. Edit the URL to perform a QUERY request (i.e. display the collection of banks). Continued on next page
Choose a bank from the collection and copy the URL in its tab into the clipboard. This is the URL for a READ request of that particular bank.
e)
Start the RESTClient from the Tools menu in Firefox. A new tab will open.
Figure 167: RESTClient
f)
Paste the URL for the READ request into the RESTClient’s Address line and add the query string ?sap-ds-debug=true.
g)
Press the “Add Request Header” button in the RESTClient toolbar.
h)
Add the variable name X-CSRF-Token and a value of Fetch. Neither of these values are case sensitive.
Figure 168: X-CSRF-Token / Fetch
3.
i)
Check that the HTTP method is set to GET and press Send.
j)
Copy the XML from the “Response Body” section at the bottom of the screen to the “Request Body” in the centre of the screen.
Prepare the UPDATE Operation a)
Since the previous READ request was issued with the query string parameter sap-ds-debug=true, we received detailed debugging information. This can be seen by selecting the “Rendered HTML” section in the RESTClient and clicking on the SAP icon in the bottom right of the screen. Continued on next page
Make sure that the query string parameter sap-ds-debug=true has been deleted from the URL. If you leave this query string parameter in the PUT request, the UPDATE operation will not succeed, but you will still receive an HTTP 200 OK status code in return.
f)
Change the HTTP Method to PUT.
g)
The XML returned from the READ operation cannot immediately be used for the UPDATE operation; it needs to be edited. The header line should be kept (but the UPDATE operation will succeed without it).
h)
The entire element must be kept, including all the namespace parameters.
i)
The tag can be deleted as it serves no purpose for an UPDATE operation. However, leaving in the XML will not cause any problems.
j)
The and tags start the elements that will contain all the bank details. These must not be removed.
k)
There now follows an element for each property belonging to a Bank. 1060 West Addison St021800089USCITIUSXX021800089ChicagoILHoosier StBank of the Blues Brothers
All empty elements are explicitly set to have a null value. See the values highlighted in red above. This requirement applies only to Gateway 2.0 SP3. In SP4 and later, the requirement to specify m:null=“true” will be relaxed. The values of bank_ctry and bank_key should not be altered, as these are the key fields. You change the values of those fields to be updated.
l)
Then follows the two tags and . These must not be deleted; otherwise the XML would no longer be well formed.
m)
The tags , , and can be deleted as they serve no purpose for an UPDATE operation.
n)
Send the request and look for an HTTP Status Code of “204 No Content” in the “Response Header” section.
Figure 171: Status Code: 204 No Content
4.
Prepare the CREATE Operation a)
Remove the key predicate (highlighted) from the URL used for the UPDATE operation. The key predicate is used to identify and existing entry within a collection. Since we are creating a new bank entry, this part of the URL is no longer necessary z_gw100_rfm_bank_01Collection( bank_key='021800089', bank_ctry='US')
b)
Change the HTTP Method to POST
c)
The HTTP Header fields used for the UPDATE operation are also needed for a CREATE operation, so you do not need to touch these values. The X-CSRF-Token will remain valid for as long as the browser session remains open.
d)
The XML used for the UPDATE operation has the same structure as the XML needed for a CREATE operation. Continued on next page
Therefore, we will use this XML as our starting point. 1060 West Addison St021800094USCITIUSXX021800094ChicagoILRay's Music ExchangeBank of the Blues Brothers
At the very least, the only values that need to change are the key values. In the example above, a new bank_key value has been supplied (highlighted in red). e)
Send the request and look for an HTTP Status Code of 201 Created. Caution: Remember! If you get an HTTP Status Code of 200 OK, then the create operation was not successful.
Figure 172: HTTP Headers
The Location field in the HTTP Header gives the URL you can issue to perform a READ operation on the newly created bank.
Lesson Summary You should now be able to: • Extend an existing RFM or BOR based Gateway Service to include update functionality. • Understand the danger posed by Cross-Site Request Forgery attacks and how the SAP NetWeaver Gateway Server prevents them. • Test the new functionality of your Gateway Service from a browser.
Unit Summary You should now be able to: • Create a read-only Gateway Service based on a Remote Function Module or an Object in the Business Object Repository (BOR). • Expose a Gateway Service for consumption. • Test your Gateway Service from a browser. • Extend an existing RFM or BOR based Gateway Service to include update functionality. • Understand the danger posed by Cross-Site Request Forgery attacks and how the SAP NetWeaver Gateway Server prevents them. • Test the new functionality of your Gateway Service from a browser.
Unit 3 Gateway Service Monitoring Unit Overview In this unit, you will learn about the various tools available within an SAP system for monitoring Gateway service activity and errors.
Unit Objectives After completing this unit, you will be able to: •
Understand the different logging and tracing tools for monitoring SAP NetWeaver Gateway Services.
Unit Contents Lesson: Monitoring Gateway ..................................................130
Lesson: Monitoring Gateway Lesson Overview This unit covers the different logging and tracing tools for monitoring SAP NetWeaver Gateway Services.
Lesson Objectives After completing this lesson, you will be able to: •
Understand the different logging and tracing tools for monitoring SAP NetWeaver Gateway Services.
Business Example Alert Monitoring with CCMS
Figure 173: Alert Monitoring with CCMS - 1/2
SAP's Computing Center Management System CCMS is SAPs central infrastructure for monitoring system landscapes: All landscape components are continuously checked. As a first and most important check, CCMS ensures the availability of all productive components. Moreover, additional checks safeguard the overall system health. If something is wrong, an alert is triggered, and a person in charge can be notified automatically. Then, CCMS offer a central entry point for deeper analysis: Overview data of the faulty component is presented. Analysis tools guide the administrator directly into helpful expert tools for further analysis. Besides CCMS, SAP NetWeaver automatically generates statistics information, which gives you both as aggregates a good overview, and additionally as single statistics detailed insight what has happened. A convenient and fast way to notify in case of problems the person in charge, can be implemented via SAP Alert Management.
The alert monitor also provides the administration methods that you need to monitor the system. These enable you to set threshold values for alerts and add or adapt auto-reaction and analysis methods. Auto-reaction methods react automatically when an alert is triggered; analysis methods enable you to examine the cause of an alert without leaving the alert monitor. The CCMS Monitoring Infrastructure The CCMS is SAPs central infrastructure for monitoring system landscapes. Keep in mind, however, that it is running in maintenance mode. With SAP Solution Manager 7.1, SAP will introduce the new Monitoring and Alerting Infrastructure (MAI)
Figure 174: Alert Monitoring with CCMS - 2/2
SAP's Computing Center Management System CCMS is SAPs central infrastructure for monitoring system landscapes: All landscape components are continuously checked. As a first and most important check, CCMS ensures the availability of all productive components. Moreover, additional checks safeguard the overall system health. If something is wrong, an alert is triggered, and a person in charge can be notified automatically. Then, CCMS offer a central entry point for deeper analysis: Overview data of the faulty component is presented. Analysis tools guide the administrator directly into helpful expert tools for further analysis. Besides CCMS, SAP NetWeaver automatically generates statistics information, which gives you both as aggregates a good overview, and additionally as single statistics detailed insight what has happened. A convenient and fast way to notify in case of problems the person in charge, can be implemented via SAP Alert Management.
The alert monitor also provides the administration methods that you need to monitor the system. These enable you to set threshold values for alerts and add or adapt auto-reaction and analysis methods. Auto-reaction methods react automatically when an alert is triggered; analysis methods enable you to examine the cause of an alert without leaving the alert monitor. The CCMS Monitoring Infrastructure The CCMS is SAPs central infrastructure for monitoring system landscapes. Keep in mind, however, that it is running in maintenance mode. With SAP Solution Manager 7.1, SAP will introduce the new Monitoring and Alerting Infrastructure (MAI)
Unit 4 OData Channel Model Provider Unit Overview In this unit, you will learn how to create a Gateway Service by means of custom ABAP coding. As with the generated Gateway service you created earlier, you will start by creating a read-only Gateway service. This will then be extend to include update functionality.
Unit Objectives After completing this unit, you will be able to: • • • • • • •
Understand the architectural elements needed to build a Gateway Service. Understand how to build a basic Gateway Model Provider Class. Understand how to create a basic Data Provider class. Configure a Gateway Service. Test the partial service in a browser. Display the service’s metadata. Understand how to create complex data types for use in OData entity types.
Unit Contents Lesson: Developing Model Provider Class ..................................138 Exercise 4: Create A Basic Model Provider Class .....................151 Lesson: Creating Gateway Services .........................................159 Exercise 5: Create Empty Data Provider Class ........................173 Exercise 6: Create a Gateway Service from the Model and Data Provider Classes............................................................175 Exercise 7: Create a Service Catalogue Entry .........................179 Lesson: Creating Complex Types ............................................185 Exercise 8: Create Complex Types and Additional Entity Types.....191
The configuration screen asks you to enter the internal service name and then uses this value as the external service name. Be careful to enter the name here that you want the end user to see. There is no need to start the internal service name with a Z character.
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 199: Creating Properties within an Entity Type – 2/2
OData Properties Mapping to Atom Elements
Figure 200: Mapping OData Properties to Atom Elements – 1/4
IMPORTANT! Atom terminology is used in the XML, but OData terminology is used in the ABAP coding
Atom talks about a Collection containing zero or more Entries, but OData talks about an EntitySet containing zero or more Entities. These terms are synonymous.
Figure 201: Mapping OData Properties to Atom Elements – 2/4
Figure 202: Mapping OData Properties to Atom Elements – 3/4
The field “Title” is an Atom field and should be included for conformance to the Atom protocol. This field does not have to be used to for an actual title; instead, it can be used to transport various pieces of information from the server to the client E.G. error messages.
Figure 205: Supplying Properties with ABAP Dictionary Metadata – 2/3
This cryptic error message comes from the fact that when the Gateway Framework tries to initialise your service, the Model Provider class crashes. This leaves the Gateway Framework unable to complete the service initialisation.
Figure 206: Supplying Properties with ABAP Dictionary Metadata – 3/3
Exercise 4: Create A Basic Model Provider Class Exercise Objectives After completing this exercise, you will be able to: • Create the metadata needed to define a basic Gateway service.
Business Example Before starting to code the model provider class, it is first necessary to understand the data model implemented by the model class. As can be seen from the diagram below, the data model consists of the following parts: 1. 2.
Three entity types called Flight, Airport and Booking Two complex data types called Location and GeoCoordinates
The Airport entity type is associated both with itself (i.e. other airports) through a navigation path called AirportsTo, and to the Flights entity type through a navigation path called DepartingFlights. The Flight entity type is associated with the Booking entity type through a navigation path called Bookings This data model will now be implemented as a Gateway Model Provider class in ABAP. The navigation paths described by the entity type associations will be implemented in the Gateway Data Provider class.
After confirming that you want to create a new class, ensure that the Object Type is set to “Object” and press enter.
e)
On the following pop-up screen enter a description for the new ABAP class and press enter. Make sure that the “Class Type” remains set to “Usual ABAP Class”.
Figure 212: Usual ABAP Class
f)
When asked for the package name press “Local Object” or enter ZGW100_nn (where nn is your group number) and press enter.
g)
Once the object has been created, double click on the new object name. This will cause the object’s methods to be displayed (there are none at the moment).
h)
Switch into change mode and select the Properties tab.
i)
Click on the superclass button, enter /IWBEP/CL_MGW_ABS_MODEL as the name of the superclass and press Save (or Ctrl-S).
Before we can implement any methods, we must first define some data types within this class. In this case, we will use the fields found within the data dictionary structure SPFLI to supply metadata for the OData interface properties. Here, we will start with the data type to represent a Booking because this contains no complex types.
b)
c) d)
Select the “Types” tab and enter the following: Type:
BOOKING_S
Visibility:
Public
Description:
Booking structure
Click on the type definition button Replace the line types booking_s. with the following code: types: begin of booking_s, airlineid
type spfli-carrid,
connectionno type spfli-connid, flightdate
type sflight-fldate,
bookingid
type sbook-bookid,
customerno
type sbook-customid,
customername type sbook-passname, price
type sflight-price,
currencycode type sflight-currency, bookingdate
type sbook-order_date,
title
type string,
end of booking_s. types: bookings_t type standard table of booking_s.
We have now defined local data types to describe a single booking (booking_s) and a table of such bookings (booking_t). e) 3.
Save your changes.
Redefine Method DEFINE a)
Right click on the DEFINE method and select Redefine from the context menu.
****************************************************************** "Define Entity Booking lo_entity_type = model->create_entity_type( 'Booking' ). "Define property AirlineId and set it as a key lo_property = lo_entity_type->create_property( iv_property_name
= 'AirlineId'
iv_abap_fieldname = 'AIRLINEID' ). lo_property->set_is_key( ). "Define property ConnectionNo and set it as a key lo_property = lo_entity_type->create_property( iv_property_name
= 'ConnectionNo'
iv_abap_fieldname = 'CONNECTIONNO' ). lo_property->set_is_key( ). "Define property FlightDate and set it as a key lo_property = lo_entity_type->create_property( iv_property_name = 'FlightDate' iv_abap_fieldname = 'FLIGHTDATE' ). lo_property->set_is_key( ). "Define property BookingId and set it as a key lo_property = lo_entity_type->create_property( iv_property_name = 'BookingId' iv_abap_fieldname = 'BOOKINGID' ). lo_property->set_is_key( ). lo_property = lo_entity_type->create_property( iv_property_name = 'CustomerNo' iv_abap_fieldname = 'CUSTOMERNO' ). "Define property CustomerName lo_property = lo_entity_type->create_property( iv_property_name = 'CustomerName' iv_abap_fieldname = 'CUSTOMERNAME' ). "The set_as_author() method assigns the current property to the "ATOM author field. The Boolean parameter defines whether the "property is visible in the content lo_property->set_as_author( iv_keep_in_content = abap_true ). lo_property = lo_entity_type->create_property( iv_property_name
"but do not keep it in the content lo_property = lo_entity_type->create_property( iv_property_name
= 'Title'
iv_abap_fieldname = 'TITLE' ). lo_property->set_as_title( iv_keep_in_content = abap_false ). "Use our previously defined data type to supply the metadata "for the properties in the OData interface.
Fields are matched
"by name. lo_entity_type->bind_structure( 'Z_CL_GW100_MP_nn=>BOOKING_S' ). "Name the EntitySet Bookings. Omitting this statement will "cause an entity set to be created automatically and called "BookingCollection lo_entity_type->create_entity_set( 'Bookings' ). endmethod.
Caution: Do not forget to correct the class reference in the bind_structure() method call! In the area highlighted in yellow, change the nn in ZCL_GW100_MP_nn to your group number. c)
Save and activate class ZCL_GW100_MP_nn. At this point in time, we cannot invoke this model provider class because we have not yet created an associated data provider class. This will be done in the next exercise.
Lesson Summary You should now be able to: • Understand the architectural elements needed to build a Gateway Service. • Understand how to build a basic Gateway Model Provider Class.
How to create a basic Data Provider class Configure a Gateway Service Test the partial service in a browser Display the service’s metadata
Lesson Objectives After completing this lesson, you will be able to: • • • •
Understand how to create a basic Data Provider class. Configure a Gateway Service. Test the partial service in a browser. Display the service’s metadata.
Business Example Gateway Service and Data Provider
Figure 213: Testing the Gateway Service's Model Provider Class
Component IW_SCS is only needed if you create Gateway Services that use screen scraping. It is entirely possible for all the Gateway Add-On Components to be installed in a single server; however, this installation arrangement is only recommended for test and development scenarios. For all productive scenarios, it is recommended that a separate Gateway Hub server is installed.
Figure 227: Create an Entry in the Gateway Service Catalogue - 1/4
Figure 230: Create an Entry in the Gateway Service Catalogue - 4/4
Gateway Service Document
Figure 231: Display the Service Document
The query string parameter sap-client is not necessary as long as the Gateway Service runs in the backend system's default client. The query string parameter $format=xml is necessary when testing a Gateway Service from a browser. This parameter tells the Gateway server to return the HTTP response using the MIME type application/xml. Depending on your browser, various degrees of formatting will be performed on the XML text response before it is displayed.
If the $format=xml parameter is omitted, then the Gateway server will return the response using the MIME type application/atomsvc+xml. The browser will then interpret this as an Atom feed and will format the response accordingly.
Figure 232: Identify the Gateway Service's Base URL
Figure 233: Identify the Collections Provided by the Gateway Service
Exercise 5: Create Empty Data Provider Class Exercise Objectives After completing this exercise, you will be able to: • Create an empty Gateway data provider class and perform the configuration necessary to execute the basic Gateway service. At this point in time, the Gateway service does not yet contain any business functionality, but is able to displays the structure of its interface.
Business Example
Task: 1.
Create an Empty Data Provider Class The coding developed so far should now be tested. In order to do this, we must configure the Gateway system to recognize that this Model Provider class belongs to a Gateway service. However, a Gateway Service is composed from at least two classes – a Model Provider class and one or more Data Provider classes. The next step therefore is to create a Data Provider class.
Solution 5: Create Empty Data Provider Class Task: 1.
Create an Empty Data Provider Class The coding developed so far should now be tested. In order to do this, we must configure the Gateway system to recognize that this Model Provider class belongs to a Gateway service. However, a Gateway Service is composed from at least two classes – a Model Provider class and one or more Data Provider classes. The next step therefore is to create a Data Provider class. a)
Create another ABAP class called ZCL_GW100_DP_nn where nn is your group number.
b)
As with class ZCL_GW100_MP_nn, the object type is “Class”, it should be given a meaningful description.
c)
The Data provider class must have class /IWBEP/CL_MGW_ABS_DATA as it’s superclass.
d)
Save your changes and activate class. At the moment, the data provider class is nothing more than an empty shell; however, it implements the standard interface required by all Gateway Data Provider classes. Therefore, it contains sufficient functionality to allow you to see the results of your ABAP coding in the model provider class.
Exercise 6: Create a Gateway Service from the Model and Data Provider Classes Exercise Objectives After completing this exercise, you will be able to: • Create an empty Gateway data provider class and perform the configuration necessary to execute the basic Gateway service. At this point in time, the Gateway service does not yet contain any business functionality, but is able to displays the structure of its interface.
Business Example Remember that at the ABAP coding level, the Model and Data Provider classes are not required to have any direct reference to each other. The association between these two classes is established using configuration, not coding. The configuration that now needs to be performed will associate your Model Provider class (ZCL_GW100_MP_nn) with the Data Provider class (ZCL_GW100_DP_nn). The configuration process creates two wrapper objects that are then associated with each other. Configuration Summary 1. 2. 3. 4.
The Model Provider class is wrapped in a Technical Model. The Runtime Data Provider class is wrapped in a Service Group. The Technical Model is then assigned to the Service Group. Create an entry in the Service Catalogue.
The first three configuration steps take place in the ABAP system containing the Gateway add-on component IW_BEP. The last configuration step takes place in the ABAP system containing the Gateway add-on component GW_CORE. As is the case with the SAP training environment, it is entirely possible that these two components are installed in the same ABAP system.
Return to the IMG hierarchy and run the “Maintain Service” transaction. This is where a Service Group is used to wrap the Data Provider class. Caution: Whatever name you enter as the Technical Service Name becomes the name that will appear in the URL that runs this service (i.e. the External Service Name). Therefore, you must choose a name that will be meaningful to the end user. Enter Flight_Information_nn as the Technical Service Name and a version number of 1. Press the create button.
b)
On the next screen, enter the Data Provider class name ZCL_GW100_DP_nn and a meaningful description.
Figure 246: Data Provider Class – Description
You must now save your changes otherwise you cannot assign a technical model. c)
Once you have saved the service information, press the “Assign Model” button.
d)
Enter the name of your Technical Model Z_GW100_TM_nn and press the save icon to close the pop-up window.
e)
Press save on the toolbar to save the assignment. Your Model and Data Provider classes are now associated with each other and form an executable Gateway Service.
Exercise 7: Create a Service Catalogue Entry Exercise Objectives After completing this exercise, you will be able to: • Create an empty Gateway data provider class and perform the configuration necessary to execute the basic Gateway service. At this point in time, the Gateway service does not yet contain any business functionality, but is able to displays the structure of its interface.
Business Example Now that the Gateway Service is functional, it needs to be made visible to the outside world. To do this, it is necessary to create an entry in the Service Catalogue. Remember how the following installation scenarios alter the location of these configuration steps: • •
ABAP development of custom Gateway Services takes place in whichever system contains the Gateway add-on component IW_BEP. External users consume Gateway Services by connecting to whichever SAP system contains the Gateway add-on component GW_CORE. This is the system in which the Service Catalogue entry must be made.
In the case of the SAP training environment, IW_BEP and GW_CORE have been installed in the same system. Therefore, there is no need to log on to a different system in order to perform the following configuration. However, when you return to your own system environment, it is entirely possible that IW_BEP and GW_CORE could be installed on separate systems. If that is the case, then you must log on to the system in which GW_CORE has been installed before performing these instructions.
Task: 1.
2012
Create a Service Catalogue Entry and Test the Service
Solution 7: Create a Service Catalogue Entry Task: 1.
Create a Service Catalogue Entry and Test the Service a)
Run transaction /IWFND/MAINT_SERVICE in the system containing the Gateway add-on component GW_CORE.
Figure 247: Component GW_CORE
This transaction shows all the Services currently available from this Gateway Server. At the moment, your Flight_Information_nn service is missing. b)
Click on the “Add Service” button in the tool bar.
c)
Enter the name of the system alias containing your Gateway service. Since the SAP training system has been set up with GW_CORE and IW_BEP in the same system, the System Alias is LOCAL.
Figure 248: Filter
The Technical Service Name is Flight_Information_nn. Press enter and the details of your service are now displayed.
The easiest way to locate your service in the catalogue is to click on the column header for “External Service Name” and then press the sort button to sort the table rows into ascending alphabetical order .
g)
Select the row containing your service FLIGHT_INFORMATION_nn then press the “Call Browser” button.
Figure 252: FLIGHT_INFORMATION_nn
h)
After confirming your logon credentials, you will see the Service Document for this Gateway Service.
Figure 253: Service Document
At the moment, this service contains no functionality; however, we can see our service contains a collection called “Bookings”. It is also possible to look at the metadata that describes the Bookings collection.
In the browser address line, remove the query string parameter ?$format=xml and replace it with $metadata. Note: IMPORTANT! $metadata is an OData command, not a query string parameter; therefore, you must delete the question mark character that denotes the start of the query string.
j)
You will now see the metadata describing the Booking collection.
Figure 254: Metadata Describing
Notice that the XML element and everything it contains, has been generated as a direct result of the ABAP coding in the DEFINE method of your Model Provider class. This is as much testing as can be done with the Gateway Service in its current state; however, this is enough to see the connection between the ABAP coding in the Model Provider’s DEFINE method and the elements.
Lesson Summary You should now be able to: • Understand how to create a basic Data Provider class. • Configure a Gateway Service. • Test the partial service in a browser. • Display the service’s metadata.
Exercise 8: Create Complex Types and Additional Entity Types Exercise Objectives After completing this exercise, you will be able to: • Create the remaining entity types needed for the Flight Information Gateway service.
Business Example
Task: 1.
Create Complex Types
2.
Define the Remaining Entity Types Several more entity types need to be defined. Specifically, these are the Airport and Flight entity types. As with the other entity types we have created, we will reference built-in data types within our model provider class Z_CL_GW100_MP_nn that in turn, derive their metadata from the ABAP dictionary.
Double click on the class name to display the class overview.
d)
Ensure that you are in change mode and select the Types tab.
e)
Enter the name geocoordinates_s, set the visibility to Public and press the type definition button .
f)
Replace the statement types geocoordinates_s. with the following type definitions. types: begin of geocoordinates_s, longitude type sgeocity-longitude, latitude
type sgeocity-latitude,
end of geocoordinates_s. types: begin of location_s, country type string, city
type string,
airport type string, time
type spfli-deptime,
end of location_s .
Since the complex types GeoCoordinates and Location will never be entity sets in their own right, there is no need to define tables based on these types. g) h)
Go back to the redefinition of method DEFINE and double click to edit it. Add an extra declaration for the local object lo_complex_type: method DEFINE. data: lo_entity_type
type ref to /iwbep/if_mgw_odata_entity_typ,
lo_property
type ref to /iwbep/if_mgw_odata_property,
lo_complex_type type ref to /iwbep/if_mgw_odata_cmplx_type.
Then add the following code immediately after the variable declaration section, remembering to change the class reference highlighted in yellow to your own Model Provider class. *************************************************************** *
COMPLEX TYPES
*************************************************************** "Complex type for Location lo_complex_type = model->create_complex_type( 'Location' ). lo_complex_type->create_property( iv_property_name
You can now see that although the complex types for GeoCoordinates and Location have not yet been assigned to an entity, they exist in the metadata definition. (The XML has been formatted for clarity.)
Type="Edm.String" Nullable="true" />
Type="Edm.Time"
Nullable="true"
sap:label="Departure" />
Type="Edm.Double"
sap:label="Latitude" Nullable="true" />
2.
Define the Remaining Entity Types Several more entity types need to be defined. Specifically, these are the Airport and Flight entity types. As with the other entity types we have created, we will reference built-in data types within our model provider class Z_CL_GW100_MP_nn that in turn, derive their metadata from the ABAP dictionary. a)
Go back to the Types tab and enter the name FLIGHT_S of visibility “Public” and press the type definition button.
b)
Replace the statement types flight_s. with the following type definitions types: begin of flight_s, airlineid
type spfli-carrid,
connectionno type spfli-connid, flightdate
type sflight-fldate,
price
type sflight-price,
currencycode type sflight-currency, distance
type spfli-distance,
distanceunit type spfli-distid, flighttime
type spfli-fltime,
planetype
type sflight-planetype,
departure
type location_s,
arrival
type location_s,
title
type string,
end of flight_s. types: flights_t type standard table of flight_s.
end of airport_s. types: airports_t type standard table of airport_s.
c)
Save these changes.
d)
After the coding to create the Booking entity, add the following code, remembering to edit the class names highlighted in yellow: ****************************************************************** "Define Entity Airport lo_entity_type = model->create_entity_type( 'Airport' ). lo_property = lo_entity_type->create_property( iv_property_name
iv_abap_fieldname = 'URL' ). "Set property title as atom title and do not keep the property "in the content lo_property = lo_entity_type->create_property( iv_property_name
iv_complex_type_name = 'Location' ). "Set property title as atom title and do not keep the property "in the content lo_property = lo_entity_type->create_property( iv_property_name
= 'Title'
iv_abap_fieldname = 'TITLE' ). lo_property->set_as_title( iv_keep_in_content = abap_false ). lo_entity_type->bind_structure('Z_CL_GW100_MP_nn=>FLIGHT_S' ). "Name the EntitySet Flights instead of the default "FlightCollection
Unit Summary You should now be able to: • Understand the architectural elements needed to build a Gateway Service. • Understand how to build a basic Gateway Model Provider Class. • Understand how to create a basic Data Provider class. • Configure a Gateway Service. • Test the partial service in a browser. • Display the service’s metadata. • Understand how to create complex data types for use in OData entity types.
Unit 5 OData Channel Data Provider Unit Overview In this unit, you will learn how to implement the business functionality of a Gateway service in an ABAP class known as the Data Provider class.
Unit Objectives After completing this unit, you will be able to: • • • • • • •
Understand architectural principles. Understand the Relationship between HTTP Requests, OData Operations and Methods in the Data Provider Class. Understand how to implement the QUERY and READ operations. Understand how to implement the CREATE operation within a Gateway Data Provider Class. Understand how to implement a custom OData action. Understand how Entity Types in a Data Model are Related Using Associations. Understand how Associations are Implemented at Runtime Using Navigation Paths.
Unit Contents Lesson: Developing Data Provider Class for Read ........................202 Exercise 9: Implement the QUERY Operation .........................207 Exercise 10: Implement the READ Operation ..........................221 Lesson: Developing Data Provider Class for Update ......................233 Exercise 11: Implement the CREATE Operation .......................239 Exercise 12: Implement CancelBooking Custom Action ..............255 Lesson: Using Associations and Navigation Paths.........................263 Exercise 13: Create Associations and Navigation Properties ........269
Lesson: Developing Data Provider Class for Read Lesson Overview This lesson covers the following development aspects of a Gateway Data Provider Class • • •
Architectural principles The Relationship between HTTP Requests, OData Operations and Methods in the Data Provider Class How to implement the QUERY and READ operations
Lesson Objectives After completing this lesson, you will be able to: • • •
Understand architectural principles. Understand the Relationship between HTTP Requests, OData Operations and Methods in the Data Provider Class. Understand how to implement the QUERY and READ operations.
Business Example Data Provider Class
Figure 267: Gateway Service Architecture
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed.
The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 268: Gateway Data Provider Class - General Architecture
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 269: One Data Provider Class per Entity Type
Exercise 9: Implement the QUERY Operation Exercise Objectives After completing this exercise, you will be able to: • Create a Gateway service providing customized flight information
Business Example You wish to provide a Gateway service that displays flight information. In a Gateway Data Provider class, the QUERY operation is implemented by the GET_ENTITYSET method and the READ operation is implemented by the GET_ENTITY method. In our case, we have a total of four Data Provider class; one top level Data Provider, and three subordinate Data Provider classes for each of the entity types in our data model. Therefore, we must implement the GET_ENTITYSET and GET_ENTITY methods in all four classes. So far, we have already created a top level Data Provider class, but it contains no functionality. Also, none of the subordinate data provider classes exist yet.
Create three new ABAP classes: one for each entity type in the data model. The ABAP classes are named: ZCL_GW100_DP_AIRPORT_nn ZCL_GW100_DP_FLIGHT_nn ZCL_GW100_DP_BOOKING_nn Where nn is your group number.
Right click on method GET_ENTITYSET and select Redefine from the context menu.
d)
Replace the contents of method GET_ENTITYSET with the following code. Be careful to replace the class names highlighted in yellow with the correct name of your Data or Model Provider class.
METHOD /iwbep/if_mgw_appl_srv_runtime~get_entityset. data: * Reference the specific data provider class for each entity set lo_airport type ref to zcl_gw100_dp_airport_nn, lo_flight
type ref to zcl_gw100_dp_flight_nn,
lo_booking type ref to zcl_gw100_dp_booking_nn. * What entity set has been requested? * Be careful! The entity set names are case-sensitive! case iv_entity_set_name. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Right click on GET_ENTITYSET and from the context menu, select Change → Implementation.
Figure 281: Change → Implementation
d)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow: method /iwbep/if_mgw_appl_srv_runtime~get_entityset. data: " Structure for one airport ls_airport
type zcl_gw100_mp_nn=>airport_s,
" Table of airports lt_airports type standard table of spfli, " Single values needed in output structure
type zcl_gw100_mp_nn=>airports_t. * Create the output data structure and assign its fields to * the field symbol create data er_entityset type zcl_gw100_mp_nn=>airports_t. assign er_entityset->* to . * Is there a navigation path that needs to be followed? if it_navigation_path is initial. " Nope, so in this case, we are simply obtaining a " list of all available airports select distinct airpfrom cityfrom countryfr into corresponding fields of table lt_airports from spfli up to is_paging-top rows. else. " Yup, so now we need to read only those airports " that can be reached directly from the current airport. " The current airport is supplied in the it_key_tab table read table it_key_tab assigning index 1. select distinct airpto cityto countryto into corresponding fields of table lt_airports from spfli up to is_paging-top rows where airpfrom = -value. endif. " Transfer the list of airports to the output structure loop at lt_airports assigning . " Are we following a navigation path? if it_navigation_path is initial. " Nope, so use the 'from' values lv_airport
= -airpfrom.
lv_country
= -countryfr.
ls_airport-name = -cityfrom. else. " Yup, so use the 'to' values lv_airport
concatenate ls_airport-name '-' lv_airport into ls_airport-title separated by space. ls_airport-geocoordinates-latitude = zcl_gw100_helper=>get_latitude_for_airport( city
= ls_airport-name
country = lv_country ). ls_airport-geocoordinates-longitude = zcl_gw100_helper=>get_longitude_for_airport( city
= ls_airport-name
country = lv_country ). append ls_airport to . endloop. endmethod.
e) 4.
Save and activate your changes.
Implement Method GET_ENTITYSET in the Flight Data Provider Class a)
Edit your Flight Data Provider class ZCL_GW100_DP_FLIGHT_nn.
b)
Create a new private type in this class called FLIGHT_S using the following definition: types: begin of flight_s. include type spfli. types: fldate
type sflight-fldate,
price
type sflight-price,
currency
type sflight-currency,
planetype type sflight-planetype, end of flight_s.
c)
Change the implementation of method GET_ENTITYSET.
d)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow: method /iwbep/if_mgw_appl_srv_runtime~get_entityset. data: lt_flights
type standard table of flight_s,
ls_flight
type zcl_gw100_mp_nn=>flight_s,
ls_filter_airpto type /iwbep/s_mgw_select_option, ls_filter_fldate type /iwbep/s_mgw_select_option.
type zcl_gw100_mp_nn=>flights_t. create data er_entityset type zcl_gw100_mp_nn=>flights_t. assign: ls_filter_airpto to , ls_filter_fldate to , er_entityset->*
to .
" Are we following a navigation path? if it_navigation_path is initial. " Nope, so read all the available flights select * into corresponding fields of table lt_flights up to is_paging-top rows from ( spfli as c inner join sflight as f on f~carrid = c~carrid and f~connid = c~connid ). else. " Yup, so apply key field and select options read: table it_key_tab assigning index 1, table it_filter_select_options assigning with key property = 'AirportTo', table it_filter_select_options assigning with key property = 'FlightDate'. select * into corresponding fields of table lt_flights up to is_paging-top rows from ( spfli as c inner join sflight as f on f~carrid = c~carrid and f~connid = c~connid ) where c~airpfrom = -value and c~airpto in -select_options and f~fldate in -select_options. endif.
" Transfer all the flight information from the SPFLI "structured table, to the output structured table. loop at lt_flights assigning . clear ls_flight. ls_flight-airlineid
Change the implementation of method GET_ENTITYSET.
d)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow: method /iwbep/if_mgw_appl_srv_runtime~get_entityset. data: lt_bookings type standard table of booking_s, ls_booking
type zcl_gw100_mp_nn=>booking_s,
lv_carrid
type sbook-carrid,
lv_connid
type sbook-connid,
lv_fldate
type sbook-fldate,
lv_bookid
type sbook-bookid,
lv_kline
type /iwbep/s_mgw_name_value_pair,
lv_lines
type i.
field-symbols:
type booking_s,
type zcl_gw100_mp_nn=>bookings_t. create data er_entityset type zcl_gw100_mp_nn=>bookings_t. assign er_entityset->* to . " Are we following a navigation path? if it_navigation_path is initial. " Nope, so read all available bookings select * into corresponding fields of table lt_bookings up to is_paging-top rows from sbook. else. " Yup, so read only the booking identified by the key values " Were we passed any key values if it_key_tab is not initial.
" Yup, so see if the key table contains the correct number " of rows describe table it_key_tab lines lv_lines. " Did we find three rows if lv_lines eq 3. " Yup, so search for required key values read table it_key_tab into lv_kline with key name = 'AirlineId'. if sy-subrc = 0. lv_carrid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'ConnectionNo'. if sy-subrc = 0. lv_connid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'FlightDate'. if sy-subrc = 0. lv_fldate = lv_kline-value. endif. endif. endif. " If the required key values are not supplied, then the read " will fail and a null result will be passed back to the client. select * into corresponding fields of table lt_bookings up to is_paging-top rows from sbook where carrid = lv_carrid and connid = lv_connid and fldate = lv_fldate. endif. " Transfer the data from the SBOOK data structure to the export " data structure loop at lt_bookings assigning . clear ls_booking. ls_booking-airlineid
concatenate `Booking for ` ls_booking-customername ` on flight `
ls_booking-airlineid
` on `
ls_booking-flightdate
ls_booking-connectionno into ls_booking-title. append ls_booking to . endloop. endmethod.
e) 6.
Save and activate your changes.
Test the QUERY Operations From A Browser a)
If your browser is still pointing to your Flight_Information_nn service, then re-issue the URL for the Service Document.
b)
If you have closed your browser, then run transaction /IWFND/MAINT_SERVICE. Figure 282: /IWFND/MAINT_SERVICE
c)
Select your service from the list and press the icon Call Browser.
d)
Add each of the collection names in turn to your Gateway Service’s Base URL and test that the correct information is returned. Remember that collection names are case-sensitive. Caution: When testing the Bookings collection, please do not simply issue the URL since to return the entire collection – since there are over 28,000 bookings in the system! Instead add the $top query string parameter to limit the result list to say, the first 100 bookings. E.g. http://:/sap/opu/odata/sap/ FLIGHT_INFORMATION_nn/Bookings?$top=100
Exercise 10: Implement the READ Operation Exercise Objectives After completing this exercise, you will be able to: • Create a Gateway service providing customized flight information
Business Example You wish to provide a Gateway service that displays flight information. We now need to implement the GET_ENTITY methods, first for the top level Data Provider class, and then for each of the entity specific Data Provider classes.
Task:
2012
1.
Implement GET_ENTITY in the Top Level Data Provider Class
2.
Implement GET_ENTITY in the Airport Data Provider Class
3.
Implement GET_ENTITY in the Flight Data Provider Class
4.
Implement GET_ENTITY in the Booking Data Provider Class
Solution 10: Implement the READ Operation Task: 1.
Implement GET_ENTITY in the Top Level Data Provider Class a)
Edit class ZCL_GW100_DP_nn.
b)
Redefine method GET_ENTITY under interface /IWBEP/IF_MGW_APPL_SRV_RUNTIME.
c)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow with your own class name. method /iwbep/if_mgw_appl_srv_runtime~get_entity. data: lo_airport type ref to zcl_gw100_dp_airport_nn, lo_flight
type ref to zcl_gw100_dp_flight_nn,
lo_booking type ref to zcl_gw100_dp_booking_nn. * Implement call-throughs to the specific entity type * data provider classes. * What entity has been requested?
when others. " Add some other entity handler here endcase. endmethod.
d) 2.
Save and activate your changes.
Implement GET_ENTITY in the Airport Data Provider Class a)
Edit class ZCL_GW100_DP_AIRPORT_nn.
b)
Change the implementation of method GET_ENTITY.
c)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow with your own class name. method /iwbep/if_mgw_appl_srv_runtime~get_entity. data: lv_country type spfli-countryto. field-symbols:
type zcl_gw100_mp_nn=>airport_s. * Create the output data structure and assign its fields to * the field symbol create data er_entity type zcl_gw100_mp_nn=>airport_s. assign er_entity->* to . " In which airport are we interested? read table it_key_tab assigning index 1. " Read the details of that particular airport from SPFLI select distinct airpfrom cityfrom countryfr into (-iatacode, -name, lv_country) from spfli where airpfrom = -value. endselect. " Did we find what we're looking for? if sy-subrc = 0. " Yup -url = zcl_gw100_helper=>get_url_for_airport( airport = -iatacode ). concatenate -name '-' -iatacode into -title separated by space. -geocoordinates-latitude = zcl_gw100_helper=>get_latitude_for_airport( city
= -name
country = lv_country ). -geocoordinates-longitude = zcl_gw100_helper=>get_longitude_for_airport( city
= -name
country = lv_country ). endif. endmethod.
d) 3.
Save and activate your changes.
Implement GET_ENTITY in the Flight Data Provider Class a)
Edit class ZCL_GW100_DP_FLIGHT_nn.
b)
Change the implementation of method GET_ENTITY. Continued on next page
Replace the entire method with the following code, remembering to update the class names highlighted in yellow with your own class name. method /iwbep/if_mgw_appl_srv_runtime~get_entity. data: ls_flight type flight_s, lv_carrid type spfli-carrid, lv_connid type spfli-connid, lv_fldate type sflight-fldate, lv_kline
type /iwbep/s_mgw_name_value_pair,
lv_lines
type i.
field-symbols: type zcl_gw100_mp_nn=>flight_s. create data er_entity type zcl_gw100_mp_nn=>flight_s. assign er_entity->* to . " Have we been passed any key values? if it_key_tab is not initial. " Yup, how many key fields do we have? describe table it_key_tab lines lv_lines.
" 3 key fields are needed in order to identify a flight if lv_lines eq 3. read table it_key_tab into lv_kline with key name = 'AirlineId'. if sy-subrc = 0. lv_carrid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'ConnectionNo'. if sy-subrc = 0. lv_connid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'FlightDate'. if sy-subrc = 0. lv_fldate = lv_kline-value. endif. endif. endif.
" Try to find the required flight select single * into corresponding fields of ls_flight from ( spfli as c inner join sflight as f on f~carrid = c~carrid and f~connid = c~connid ) where f~carrid = lv_carrid and f~connid = lv_connid and f~fldate = lv_fldate. " Did we find it? if sy-subrc = 0. " Yup, transfer fields to output structure -airlineid
Replace the entire method with the following code, remembering to update the class names highlighted in yellow with your own class name. method /iwbep/if_mgw_appl_srv_runtime~get_entity. data: ls_booking type booking_s, lv_carrid
type sbook-carrid,
lv_connid
type sbook-connid,
lv_fldate
type sbook-fldate,
lv_bookid
type sbook-bookid,
lv_kline
type /iwbep/s_mgw_name_value_pair,
lv_lines
type i.
field-symbols: type zcl_gw100_mp_nn=>booking_s. create data er_entity type zcl_gw100_mp_nn=>booking_s. assign er_entity->* to . " Have we been passed any key values? if it_key_tab is not initial. " Yup, how many key values are there? describe table it_key_tab lines lv_lines. " 4 key values are needed to locate a booking if lv_lines eq 4. read table it_key_tab into lv_kline with key name = 'AirlineId'. if sy-subrc = 0. lv_carrid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'ConnectionNo'. if sy-subrc = 0. lv_connid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'FlightDate'. if sy-subrc = 0. lv_fldate = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'BookingId'. if sy-subrc = 0.
lv_bookid = lv_kline-value. endif. endif. endif. " Try reading the booking select single * into corresponding fields of ls_booking from sbook where carrid = lv_carrid and connid = lv_connid and fldate = lv_fldate and bookid = lv_bookid. " Did we find the booking if sy-subrc = 0. " Transfer the data from the SBOOK structure " to the output structure -airlineid
Select your service from the list and press the icon Call Browser. To test each of the READ operations, you should first perform the QUERY operation, and then select an entity from the entity set. For instance, if we display the Airports collection, we could choose the entry for Frankfurt airport. method /iwbep/if_mgw_appl_srv_runtime~get_entity. data: ls_booking type booking_s, lv_carrid
type sbook-carrid,
lv_connid
type sbook-connid,
lv_fldate
type sbook-fldate,
lv_bookid
type sbook-bookid,
lv_kline
type /iwbep/s_mgw_name_value_pair,
lv_lines
type i.
field-symbols: type zcl_gw100_mp_nn=>booking_s. create data er_entity type zcl_gw100_mp_nn=>booking_s. assign er_entity->* to . " Have we been passed any key values? if it_key_tab is not initial. " Yup, how many key values are there? describe table it_key_tab lines lv_lines. " 4 key values are needed to locate a booking if lv_lines eq 4. read table it_key_tab into lv_kline with key name = 'AirlineId'. if sy-subrc = 0. lv_carrid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'ConnectionNo'. if sy-subrc = 0. lv_connid = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'FlightDate'.
if sy-subrc = 0. lv_fldate = lv_kline-value. endif. read table it_key_tab into lv_kline with key name = 'BookingId'. if sy-subrc = 0. lv_bookid = lv_kline-value. endif. endif. endif. " Try reading the booking select single * into corresponding fields of ls_booking from sbook where carrid = lv_carrid and connid = lv_connid and fldate = lv_fldate and bookid = lv_bookid. " Did we find the booking if sy-subrc = 0. " Transfer the data from the SBOOK structure " to the output structure -airlineid
For each entity type, choose an entity from the entity set (or collection), locate the tag and issue this URL from your browser address line. This will test the READ operation for each entity type. d)
2012
The key difference between the QUERY and READ operations is this. No matter what filter criteria you define, or whether any entities are found at all, the QUERY operation will always return zero or more entities within an element; whereas, the READ operation will only ever return zero or one entities within an element.
Lesson Summary You should now be able to: • Understand architectural principles. • Understand the Relationship between HTTP Requests, OData Operations and Methods in the Data Provider Class. • Understand how to implement the QUERY and READ operations.
The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 285: CREATE_ENTITY Method in Top Level Data Provider Class
Figure 286: Implement CREATE_ENTITY in the Booking Provider Class
Exercise 11: Implement the CREATE Operation Exercise Objectives After completing this exercise, you will be able to: • Implement and test the Create and CancelBooking operations
Business Example To provide the users of the Flight Information service with the ability to create and cancel flight bookings.
Task 1: The CREATE_ENTITY method is only appropriate for the Booking entity type; therefore, we only need to implement this method in two places: • The top level Data Provider • The Booking Data Provider
Figure 294: Gateway Data Provider
1.
Extend the BOOKING_S Data Type and Booking Entity Type in the Model Provider Class
2.
Implement Method CREATE_ENTITY in the Top Level Data Provider Class
3.
Implement Method CREATE_ENTITY in the Booking Data Provider Class
Task 2: Test the Booking CREATE_ENTITY Method Before starting the actual test procedure, we must first understand what information is required in order to create a flight booking. In order to create a Booking, five values must be supplied to the BAPI: o AirlineId o Connection No o Flight Date o Customer No o Agency In order to determine which values must be supplied to these fields, we need to look inside some tables in the SAP system. But first…
Solution 11: Implement the CREATE Operation Task 1: The CREATE_ENTITY method is only appropriate for the Booking entity type; therefore, we only need to implement this method in two places: • The top level Data Provider • The Booking Data Provider
Figure 295: Gateway Data Provider
1.
Extend the BOOKING_S Data Type and Booking Entity Type in the Model Provider Class a)
Log on to the Gateway Service development system
b)
Run transaction SE80.
c)
Edit your Model Provider class ZCL_GW100_MP_nn
d)
Add two new fields to the booking_s data type: types: begin of booking_s, airlineid
Replace the contents of method CREATE_ENTITY with the following code. Be careful to replace the class names highlighted in yellow with the correct name of your Data or Model Provider class method /iwbep/if_mgw_appl_srv_runtime~create_entity. data: lo_booking type ref to /iwbep/if_mgw_appl_srv_runtime, ex_ref
type ref to /iwbep/cx_mgw_busi_exception.
field-symbols: type zcl_gw100_mp_nn=>booking_s. " Check to which entity type the request belongs " In this case, we will only respond to create requests for " Booking entity types case iv_entity_name. when 'Booking'. " Create the Booking object and the data structure in " which the booking will be returned create: object lo_booking type zcl_gw100_dp_booking_nn, data
er_entity
type zcl_gw100_mp_nn=>booking_s.
" The booking creation will throw an exception if it fails. " This needs to be caught and handled correctly otherwise " the user will get the very unhelpful error message on " their browser 'An exception was thrown' try. " Try to create the booking lo_booking->create_entity( exporting iv_entity_name
catch /iwbep/cx_mgw_busi_exception into ex_ref. " Yup, so hijack the TITLE property to use as a carrier " for the error message assign er_entity->* to . -title = ex_ref->get_msg_container( ) ->get_leading_message_text( ). endtry. endcase. endmethod.
f) 3.
Save and activate your changes.
Implement Method CREATE_ENTITY in the Booking Data Provider Class a)
Edit your Booking Data Provider class ZCL_GW100_DP_BOOKING_nn.
b)
Change the implementation of method CREATE_ENTITY.
c)
Replace the entire method with the following code, remembering to update the class names highlighted in yellow: method /iwbep/if_mgw_appl_srv_runtime~create_entity. data: ls_booking
type z_cl_gw100_mp_nn=>booking_s,
ls_sbook_create
type bapisbonew,
lt_sbook_create_return type bapirettab, lr_sbook_create_return type ref to bapiret2, lx_busi_exc
type ref to /iwbep/cx_mgw_busi_exception.
field-symbols: type zcl_gw100_mp_nn=>booking_s. create data er_entity type zcl_gw100_mp_nn=>booking_s. assign er_entity->* to . " Read the data supplied by the client call method io_data_provider->read_entry_data importing es_data = ls_booking. ls_sbook_create-airlineid
read table lt_sbook_create_return index 1 reference into lr_sbook_create_return. if lr_sbook_create_return->*-type ne 'S'. create object lx_busi_exc. " Transfer the error message(s) into the exception object lx_busi_exc->get_msg_container( )->add_messages_from_bapi( it_bapi_messages = lt_sbook_create_return ). raise exception lx_busi_exc. else. " Its very important that you commit all successfully " applied changes, otherwise the update will be lost call function 'BAPI_TRANSACTION_COMMIT'. = ls_booking. endif. endmethod.
d)
Save and activate your changes
Task 2: Test the Booking CREATE_ENTITY Method Before starting the actual test procedure, we must first understand what information is required in order to create a flight booking. In order to create a Booking, five values must be supplied to the BAPI: o AirlineId o Connection No o Flight Date o Customer No o Agency
In order to determine which values must be supplied to these fields, we need to look inside some tables in the SAP system. But first… 1.
Testing from SAPGUI a)
From the coding shown above in section 12.2.3, it can be seen that method CREATE_ENTITY in the Booking provider class creates a new flight booking by calling BAPI_FLBOOKING_CREATEFROMDATA. Therefore, in order to test that we are using valid data, we can run the same BAPI in test mode from within the SAP system.
b)
In a new SAPGUI session, run transaction SE37. (Type /OSE37 into the OK Code field and press enter).
c)
Enter the name BAPI_FLBOOKING_CREATEFROMDATA and press F8 to execute it.
d)
Enter an “X” into the input parameter labelled TEST_RUN.
e)
We now need to determine what values to use for our new flight booking. In a new SAPGUI session, run transaction SE16. (Type /OSE16 into the OK Code field and press enter).
f)
Look at the contents of table SFLIGHT.
g)
Choose an arbitrary carrier and flight number. For example, you could select Lufthansa flight 0400.
h)
Press F3 to return to the SE16 selection screen and filter the display of table SFLIGHT to display only those rows for your chosen flight.
Choose a flight whose departure date (FLDATE) is in the future and has seats available (where SEATSMAX – SEATSOCC > 0).
j)
Remember the details of your chosen flight – i.e. the contents of fields CARRID, CONNID and FLDATE. We now have 3 of the 5 required fields for creating a flight booking.
k)
Press F3 twice to go back to the SE16 start screen.
l)
Enter the table name SCUSTOM and press enter.
m)
On the selection screen, press F8 to display the table contents. Since there are over 4000 entries in this table, you will only be shown the first 200.
n)
Choose any customer number you like (field ID) and remember it. E.G. 00000001.
o)
The final value we need is an Agency Id. Press F3 twice to return to the SE16 start screen.
p)
Enter the table name STRAVELAG and press enter followed by F8.
q)
Choose any agency number you like (field AGENCYNUM) and remember it. E.G. 00000001.
Now that we have all five required values, switch to the SAPGUI screen in which you are test running the BAPI (transaction SE37).
s)
On the initial screen for running a function module, you will see the names of the input parameters for this function module. Since BOOKING_DATA is not a single field, but a data structure, an icon showing a jigsaw puzzle piece appears to the right of the field name.
Figure 297: Import Parameters
Click on this icon and enter the values we have just derived.
Figure 298: BOOKING_DATA
Once these values have been entered, press F3 to return to the initial screen for testing a function module. t)
Press F8 to execute the function module.
u)
In the “Export parameters” section, you should now see the results of a successful test run.
Figure 299: Export Parameters
Figure 300: Tables
Click on the icon next to the “RETURN Result:” table that has 2 entries. Continued on next page
You will now see the messages created by the BAPI.
Figure 301: Messages
This demonstrates that our test data is suitable for creating a flight booking. The reason we did not try to test the suitability of our data from the RESTClient is that when testing from within SAPGUI, we are testing simply the core functionality of the business process, rather than the business functionality plus the XML sent across OData interface. We can now proceed to test our Gateway service in the RESTClient knowing that our test data is valid. 2.
Testing from the RESTClient in Firefox a)
Open the Firefox browser and start the RESTClient add-on.
b)
In order to perform a CREATE operation; it is necessary to first perform a READ for two reasons: 1. 2.
c)
The READ operation supplies us with a suitable XML document that can be modified for the CREATE operation. The READ operation must be used to obtain an X-CSRF-Token without which, UPDATE, DELETE or CREATE operations cannot be performed.
From within the RESTClient add-on, issue the URL to display the Bookings collection from your flight information service. Caution: Due to the fact that there are over 28,000 bookings in the backend system, do not request the entire Bookings collection. Instead, restrict the number of returned entities by using the $top query string parameter. E.g. .../Flight_Information_nn/Bookings?$top=100
In the “Formatted XML” section of the RESTClient, scroll down the list and locate the element of some booking (the exact booking you choose is not important).
e)
Copy the contents of this element to the RESTClient’s address line.
f)
Add a request header of X-CSRF-Token with a value of Fetch.
g)
Add the query string parameter sap-ds-debug=true to the URL and send it to the server.
h)
In the “Rendered XML” section of the RESTClient, click on the SAP icon in the bottom right corner and then select the Response tab.
i)
Copy the value of the X-CSRF-Token and use this to replace the value “Fetch” in the request header.
j)
Add a second request header called Content-Type with a value of application/atom+xml;type=entry.
k)
Change the HTTP method from GET to POST.
l)
Remove the key predicate and query string from the URL used to perform the READ. The key predicate is the part of the URL immediately after the collection name Bookings enclosed in parentheses. The URL should now contain nothing more than a reference to the Bookings collection.
m)
Copy the XML in the “Rendered HTML” section to the “Request Body”. This XML will need to be edited before it can be sent to the server as a CREATE request.
In the “Request Body” section of the RESTClient, edit the XML to remove the following: 1. 2. 3. 4. 5. 6. 7.
o)
GW100
Any hyphen characters and blank lines (this is caused by copying the XML from a formatted display). The element The element The element The element The element The element
Enter your valid data obtained from testing BAPI_FLBOOKING_CREATEFROMDATA into the XML. Your XML should look something like this, where the required values are highlighted in yellow. LH04002012-06-16T00:00:000000000000000001Harry Hawk0.00EUR2012-02-23T00:00:0000000001
Caution: In addition to the values needed to create the flight booking, look at what is also necessary for the XML to be considered valid: •
In SP3 of Gateway 2.0, OData properties of type Edm.String are not allowed to be empty. (This constraint will be relaxed in SP4 or can be relaxed in SP3 by applying SAP Note 1690310). Therefore, you must always enter an initial value appropriate for the property’s data type. In the case of Edm.String fields that need to be empty, add the parameter m:null=“true”. E.g.
•
The date is always specified as timestamp in the format YYYY-MM-DDTHH:MM:SS where T is a fixed separator between the date and time parts. If you only need to specify a date, then the time part can be set to 00:00:00.
•
If you use the m:null=“true” parameter, then you must terminate the empty XML element with a slash character. See the and elements above.
p)
Once your XML looks correct, press send.
q)
You should receive an HTTP 201 Created message.
Figure 303: Status Code
If you receive an error message, then use transaction /IWFND/ERROR_LOG in the Gateway server to see a detailed error message. After the successful creation of the flight booking, you will see within the Response Header section of the RESTClient, a Location parameter followed by a URL. This is the URL to READ the flight booking that has just been created. Continued on next page
Unfortunately, the RESTClient does not permit you to follow this link by clicking on it. You can’t even copy and paste the value! To demonstrate that the CREATE operation worked correctly, go to the “Formatted XML” section and look for the element. r)
Copy the READ operation’s URL inside this element and paste it into the RESTClient’s address line.
s)
Change the HTTP method from POST to GET and press Send.
t)
You will now see the XML response of a READ operation on the flight booking you have just created. Keep the READ response in the RESTClient, as this is the booking we will cancel when we come to test the CancelBooking action in the next section.
Exercise 12: Implement CancelBooking Custom Action Exercise Objectives After completing this exercise, you will be able to: • Implement and test the Create and CancelBooking operations
Business Example To provide the users of the Flight Information service with the ability to create and cancel flight bookings.
Task: 1.
Adjust the Gateway Service’s Metadata
2.
Implement Method EXECUTE_ACTION in the Top Level Data Provider Class
3.
Implement Method EXECUTE_ACTION in the Booking Data Provider Class
4.
Test the CancelBooking Custom Action The OData specification states that all parameters passed to a Service Operation (or Custom Action) must be passed in the query string. This is true irrespective of whether the GET or POST method is used. Also the data types of certain fields must be declared as part of the query string value.
Replace the coding this method with the following, remembering to adjust the class names highlighted in yellow: method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION. data: lo_booking
type ref to /iwbep/if_mgw_appl_srv_runtime,
ls_rt_booking type zcl_gw100_mp_nn=>booking_s. " The only action that is responded to is CancelBooking case iv_action_name. when 'CancelBooking'. create: object lo_booking type zcl_gw100_dp_booking_nn, data
Implement Method EXECUTE_ACTION in the Booking Data Provider Class a)
Edit your Booking Data Provider class ZCL_GW100_DP_BOOKING_nn.
b)
Change the implementation of method EXECUTE_ACTION.
c)
Replace the coding in this method with the following, remembering to adjust the class names: method /iwbep/if_mgw_appl_srv_runtime~execute_action. data: wa_booking type sbook, lv_carrid
field-symbols: type zcl_gw100_mp_nn=>booking_s. " Check what action is being requested if iv_action_name = 'CancelBooking'. create data er_data type zcl_gw100_mp_nn=>booking_s. assign er_data->* to . " Were we passed any parameters? if it_parameter is not initial. " Yup, how many? describe table it_parameter lines lv_lines. " Must have exactly 4 parameters if lv_lines eq 4. read table it_parameter into lv_kline with key name = 'AirlineId'. if sy-subrc = 0. lv_carrid = lv_kline-value. endif. read table it_parameter into lv_kline with key name = 'ConnectionNo'. if sy-subrc = 0. lv_connid = lv_kline-value. endif. read table it_parameter into lv_kline with key name = 'FlightDate'. if sy-subrc = 0. lv_fldate = lv_kline-value. endif. read table it_parameter into lv_kline with key name = 'BookingId'. if sy-subrc = 0. lv_bookid = lv_kline-value. endif. endif. endif. " Find the booking to be cancelled select single * from sbook into wa_booking where carrid = lv_carrid and connid = lv_connid and fldate = lv_fldate and
bookid = lv_bookid. " Was the booking found if sy-subrc = 0. " Set the cancelled flag and update the database wa_booking-cancelled = 'X'. update sbook from wa_booking. " Return the details of the cancelled booking to the client. -airlineid
concatenate `Booking for ` -customername ` on Flight `
-airlineid
` on `
-flightdate
-connectionno ` has been cancelled.` into -title. else. concatenate `Booking `
lv_bookid
` for flight ` lv_carrid lv_connid ` on `
lv_fldate
` cannot be found.` into -title. endif. endif. endmethod.
d) 4.
Save and activate your changes.
Test the CancelBooking Custom Action The OData specification states that all parameters passed to a Service Operation (or Custom Action) must be passed in the query string. This is true irrespective of whether the GET or POST method is used.
Also the data types of certain fields must be declared as part of the query string value. a)
In the RESTClient, delete the following values: 1. 2.
The Content-Type request header value The entire request body
b)
Ensure the HTTP method is set to POST
c)
Edit the URL so that it contains the following segments concatenated together as a single string: URL Fragment
Description
flight_information_nn/
Gateway Service name
CancelBooking
Custom Action name
?
Start of query string
AirlineId='LH'
Quoted string value
&
Query string separator
ConnectionNo='0400'
Quoted string value
&
Query string separator
FlightDate=datetime'2012-06-16T00:00'
Data type + quoted value
&
Query string separator
BookingId='00009405'
Quoted string value
The format of the FlightDate parameter is what usually catches people out. This is the OData syntax for declaring that the value in the quoted string is of type Edm.DateTime. No white space is permitted between the data type identifier and the quoted value. The URL for invoking the CancelBooking action will look like the one shown below. The values that you will need to edit have been highlighted in yellow. These should be changed to whatever values describe the booking you are cancelling: flight_information_nn/CancelBooking?AirlineId='LH'& ConnectionNo='0400'& FlightDate=datetime'2012-06-16T00:00'& Bookingld='00009405'
Lesson Summary You should now be able to: • Understand how to implement the CREATE operation within a Gateway Data Provider Class. • Understand how to implement a custom OData action.
Lesson: Using Associations and Navigation Paths Lesson Overview This lesson covers the use of OData associations and navigation paths.
Lesson Objectives After completing this lesson, you will be able to: • •
Understand how Entity Types in a Data Model are Related Using Associations. Understand how Associations are Implemented at Runtime Using Navigation Paths.
Business Example
Associations
Figure 305: Turning Data into Information - Using Associations
Figure 306: Defining Associations in the Data Model - 1/
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 307: Defining Associations in the Data Model - 2/
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 308: Defining Associations in the Data Model - 3/
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Figure 309: Defining Associations in the Data Model - 4/
The development of a Gateway Service takes place on whichever system has the IW_BEP component installed. The activation of a Gateway service takes place in whichever SAP system has the GW_CORE component installed. It is entirely possible that these may be different systems.
Exercise 13: Create Associations and Navigation Properties Exercise Objectives After completing this exercise, you will be able to: • Allow users to traverse between the entity types in the Flight Information data model. This is achieved by implementing design-time associations and runtime navigation paths in your Gateway service.
Business Example To provide the users with the ability to obtain information about business objects related to the one currently selected. This allows the users to get answers to practical questions such as, “If I am starting from a particular airport, to which other airports can I fly directly?”
Task: 1.
Create Associations Between Entity Types In order to create the real-life associations that exist between related pieces of information, OData provides a facility to create associations.
2.
Create Navigation Properties Between Associations The Associations we’ve just created declare nothing more than the existence of an association between certain entity types. In order to make use of these associations, we need to provide the user with a means of navigating from one side of an association to the other. This is where Navigation Properties are used.
3.
Modify method GET_ENTITYSET in the Top Level Data Provider Class So far, the coding in method GET_ENTITYSET of the top level Data Provider class takes a simplistic view of the requests it receives. It examines only the name of the entity set (or collection), and then simply calls the associated Data Provider class for that entity type. This coding is not suitable for handling navigation paths for the simple reason that if you want to see a list of flights that depart from a given airport, the URL will refer to the Airports collection, but the returned entity type should be a collection of flights, not airports.
Therefore, we need to extend the coding in the GET_ENTITYSET method to call the Data Provider class associated with the entity type being returned – which is not necessarily the same entity type identified by the collection name. 4.
Test Navigation Paths in the Browser Three navigation paths need to be tested: • AirportsTo: For any given airport, we can list the airport to which we can fly directly. • DepartingFlights: For any given airport, we can list the flights that take from there. • Bookings: For any given flight, we can list its bookings. Navigation paths are tested by constructing a URL that identifies a specific airport or flight, and then appending to it the navigation path name.
Solution 13: Create Associations and Navigation Properties Task: 1.
Create Associations Between Entity Types In order to create the real-life associations that exist between related pieces of information, OData provides a facility to create associations. a)
Start the ABAP Development Workbench (transaction SE80) and edit your Model Provider class ZCL_GW100_MP_nn.
b)
Edit method DEFINE and add a declaration for the local object lo_association: method DEFINE. Data: lo_entity_type
type ref to /iwbep/if_mgw_odata_entity_typ,
lo_property
type ref to /iwbep/if_mgw_odata_property
lo_complex_type type ref to /iwbep/if_mgw_odata_cmplx_type,
c)
lo_action
type ref to /iwbep/if_mgw_odata_action,
lo_parameter
type ref to /iwbep/if_mgw_odata_parameter,
lo_association
type ref to /iwbep/if_mgw_odata_assoc.
Add the following coding to the end the method. ***************************************************************** * ASSOCIATIONS ***************************************************************** "Define Association AirportFrom_AirportsTo between Airport and "Airport lo_association = model->create_association( iv_association_name = 'AirportFrom_AirportsTo' iv_left_type
= 'Airport'
iv_right_type
= 'Airport'
iv_right_card
= cardinality_feed
iv_left_card
= cardinality_entity ).
"Define Association AirportFrom_DepartingFlights between Airport "and Flight lo_association = model->create_association( iv_association_name = 'AirportFrom_DepartingFlights' iv_left_type
"Define Association Flight_Bookings between Flight and Booking lo_association = model->create_association( iv_association_name = 'Flight_Bookings' iv_left_type
= 'Flight'
iv_right_type
= 'Booking'
iv_right_card
= cardinality_feed
iv_left_card
= cardinality_entity ).
Three associations are created here: • • •
2.
An association showing which airports can be reached from any other airport. An association showing which flights are departing from a particular airport. An association showing the bookings for a particular flight.
d)
Save and activate your changes.
e)
Go back to the browser and re-issue the $metadata URL.
f)
You will now see various extra elements in the XML – three elements, and within the element, three new elements.
The Associations we’ve just created declare nothing more than the existence of an association between certain entity types. In order to make use of these associations, we need to provide the user with a means of navigating from one side of an association to the other. This is where Navigation Properties are used. a) b)
Edit method DEFINE. Add the following coding to the end the method. ****************************************************************** *
NAVIGATION PROPERTIES
****************************************************************** "Navigation Properties for entity Airport lo_entity_type = model->get_entity_type( iv_entity_name = 'Airport' ). "Add Navigation Property from role AirportFrom "to role AirportsTo lo_entity_type->create_navigation_property( iv_property_name
= 'AirportsTo'
iv_association_name = 'AirportFrom_AirportsTo' ). "Add Navigation Property from role AirportFrom "to role DepartingFlights lo_entity_type->create_navigation_property( iv_property_name
= 'DepartingFlights'
iv_association_name = 'AirportFrom_DepartingFlights' ). "Navigation Properties for entity Flight lo_entity_type = model->get_entity_type( iv_entity_name = 'Flight' ). "Add Navigation Property from role Flight to role Bookings lo_entity_type->create_navigation_property( iv_property_name
= 'Bookings'
iv_association_name = 'Flight_Bookings' ).
Note: Notice that these statements operate on the entity types for Airport and Booking, not the entity sets Airports and Bookings. A navigation property is identified by the value of the iv_property_name parameter, and then given an association on which to operate. c)
Save and activate your changes.
d)
Go back to the browser and re-issue the $metadata URL.
e)
You will now see some new elements within the elements for Flight and Airport. Continued on next page
Modify method GET_ENTITYSET in the Top Level Data Provider Class So far, the coding in method GET_ENTITYSET of the top level Data Provider class takes a simplistic view of the requests it receives. It examines only the name of the entity set (or collection), and then simply calls the associated Data Provider class for that entity type. This coding is not suitable for handling navigation paths for the simple reason that if you want to see a list of flights that depart from a given airport, the URL will refer to the Airports collection, but the returned entity type should be a collection of flights, not airports. Therefore, we need to extend the coding in the GET_ENTITYSET method to call the Data Provider class associated with the entity type being returned – which is not necessarily the same entity type identified by the collection name. a)
Edit your top level Data Provider class ZCL_GW100_DP_nn. Since there are no navigation paths related to the Booking entity type, we only need to adjust the coding for Airports and Flights.
b)
Just after the data declaration, declare a field symbol: field-symbols:
c)
type /iwbep/s_mgw_navigation_path.
Replace the case branch for Airports with the following, remembering to adjust the class names highlighted in yellow: when 'Airports'. " First check for navigation paths that require a different " entity set to be returned than the one indicated by the " collection name. E.G. Airports('FRA')/DepartingFlights " contains Airports as the entity set but requires a " collection of Flights to be returned read table it_navigation_path assigning index 1. " Instantiate the data provider object for this entity set if sy-subrc = 0 and -nav_prop = 'DepartingFlights'. create: object lo_flight, data er_entityset type z_cl_gw100_mp_nn=>flights_t. lo_flight->/iwbep/if_mgw_appl_srv_runtime~get_entityset( exporting iv_entity_name