You are on page 1of 55

ABAP Objects Intro / Refresher

Preparation for Agile Software Engineering Course


Juergen Heymann, Nena Raab
CPO Software Engineering
Purposes & Format

Purpose: Prepare for AgileSE Course ABAP


 Fast Introduction / Refresher of Object Oriented ABAP (OO ABAP)
 Learn how to develop OO ABAP source code based

Format: Self-study course with set of modules with


 Short video intro to concept
 Programming exercise
 Short video on sample solution
 Modules build on each other

© 2011 SAP AG. All rights reserved. 2


Learning Modules

Module 1 Module 4

 From Functions to Objects  OO Key Concept: Polymorphism


 Object Basics  Interfaces
 OO Key Concept: Encapsulation  Various Uses of Interfaces

Module 2 Module 5

 Local and Global Classes (SE24)  Inheritance/Subclassing


 Class Attributes and Methods
 Design Pattern: Factory Method

Module 3

 Introduction to UML and object modeling

© 2011 SAP AG. All rights reserved. 3


Assumptions / Prerequisites

The course is developed from the perspective of an experienced ABAP


developer. Assumptions:
 You are familiar with ABAP programming (non-OO) and the tools
 You have access to a system for the exercises

Positioning
The course is intended as quick refresher / fast intro to OO programming in ABAP.
For deeper study, read e.g. …

© 2011 SAP AG. All rights reserved. 4


ABAP Objects Refresher
Module 1:

 From Functions to Objects


 Object Basics
 OO Key Concept: Encapsulation
From Functions to Objects 1
Characteristics of the Procedural Programming Model

Separation of data and function


• Data represents state of ‘real world objects’
• Functions implement behavior of 'real world objects function

Usually direct access to data (non-encapsulated)


function function function

Modularization is used to encapsulate functions


function form form form
routine routine routine

Notes:
 You can encapsulate data (access) by functions
 All data is accessible to all functions

data data data

data
data

© 2011 SAP AG. All rights reserved. 6


From Functions to Objects 2
Multiple Instances

When you want 'multiple instances' you use internal- or DB-tables


Row in table holds the data for one instance
 e.g. order  items table
Code works on 'the current instance' = a 'current row of the table'
 address 'current instance' by field-symbol or by taking it into a work-area
 hard to address multiple 'current instances' you work with
 hard to have deeper structures

Cars
code ID name speed

code
Notes:
1 Porsche 911 170  New instance  append to table
code 2 VW Bug 1300 120  Row identified by a 'key'
code

© 2011 SAP AG. All rights reserved. 7


From Functions to Objects 3
Objects – a Real World Object Representation

What changes going to Objects? public private

Putting Code and Data together method


 Instance specific Data and code that 'belongs method data
together' is put together
 Instance specific Data  Instance Attributes
Functions/Forms  Methods Class Car

 Methods work only on their object's data set_name name


(keep their object data consistent)
set_speed speed
 Data is usually hidden ('private') and methods are
public

Each Object Instance is created separately Object 1: Object 2:


 'CREATE OBJECT' instead of 'append line' set_name Porsche 911 set_name VW Bug 1300

Terminology set_speed 170 set_speed 120

 Class: Code + structure to define objects


 Object: Concrete instance of a class

© 2011 SAP AG. All rights reserved. 8


What the Code Looks Like
Definition – Implementation - Client

Definition Definition of a class (here local in program)

Definition of the methods with parameters

Definition of attributes of the class

Implementation
Implementation of the methods

Client code (here: main program)

DATA … TYPE REF TO are reference variables that


can hold references to objects (of a certain type)

the CREATE OBJECT statement creates a


new instance of a class

methods are called on the object to


change the data of this object

© 2011 SAP AG. All rights reserved. 9


From Functions to Objects 4
Instances and References

data car1 type ref to lcl_car.


Instances / Objects data car2 type ref to lcl_car.
data car3 type ref to lcl_car.
 A new object is created by "CREATE OBJECT objref"
(objref = name of reference variable) create object: car1, car2, car3.
 You can have many objects/instances of a class.
(they live in memory)
car1
Object References car2

 Objects are 'accessed' via a reference that 'points to' car3


the object instance
 References are stored in reference variables of
TYPE REF TO …
car3 = car1. "– copy reference
 Reference variables are typed so that only references clear car2. "– clear reference
of objects of that specified type can be stored there
 Reference values can be copied and cleared
 car3 = car1 only copies the reference, not the object! car1
car2 X
Garbage Collection car3
 Objects no longer reachable by any reference are
'reclaimed' (instance discarded, memory reused)

© 2011 SAP AG. All rights reserved. 10


OO Key Concept: Encapsulation
Public and Private

Motivation Definition

 You want to encapsulate/hide internal details


such as data and internal operations
 You want to provide a well-defined, simple and
consumable public interface to the client
 The private object components (data, methods)
can be restructured without the need to change
clients of the object

Some Principles
 Keep your data 'private‘ since private data can
only be modified within the class
 The object itself ensures the consistency of its
data

© 2011 SAP AG. All rights reserved. 11


Special Method: Constructor

A special method of a class is the Definition


CONSTRUCTOR
 This method is called implicitly by the
system when the object is created
 Arguments can be defined that then have to
be passed to the "CREATE OBJECT"
statement
 Constructors are optional
 Constructors are usually used to 'initialize'
an object to a consistent state

© 2011 SAP AG. All rights reserved. 12


Exercise 1: Basic OO Concepts and ABAP OO Syntax

Exercise: Modeling different types of cars with their fuel consumption


 Create a program/report (in $TMP) that you will write your local classes in

Further Instructions
Define a local class for car e.g. lcl_car Create car objects in your main program
 Define attributes of car (private)  Create 3 different cars (instances) with 3 different tank
capacities and gas consumptions.
– name of car (e.g. 'Porsche Carrera 911')
 Call methods on the objects to drive various distances
– capacity of gas tank in liters
 Call methods on the objects to ask for the current tank level
– fuel consumption - liters per 100 km the car consumes and output these values (use WRITE statements)
– current tank level in liters (e.g. 10,2 liters)
 Define methods (public) References
– constructor: sets the attributes
name, capacity and fuel consumption  ABAP Objects syntax reference by sample code
– refuel: fill up the gas tank returning the number of liters used
– drive_distance: reduces the gas in the tank ABAP Workbench Shortcuts
– get_current_tank_level: returns the current tank level CTRL + Space Code Completion
in percentage (e.g. “35% filled”)
SHIFT + F1 Format Source
F2 Check Source
F3 Activate Source
F9 Select all Objects in Activation List

© 2011 SAP AG. All rights reserved. 13


Review of Exercise 1

Content
 Look at the sample solution
 Show objects in debugger

lcl_car

- name
- tank_capacity
- fuel_consumption_per_km
- curr_tank_level
+ constructor( )
+ refuel( )
+ drive_distance( )
+ get_curr_tank_level( )

© 2011 SAP AG. All rights reserved. 14


ABAP Objects Refresher
Module 2:

 Local and Global Classes (SE24)


 Class Attributes and Methods
 Design Pattern: Factory Method
Local and Global Classes

Local Classes Prog1


 Can be defined within any source unit lcl_car Prog2
e.g. report, function, global class … lcl_car
lcl_truck
 Are only visible in that source unit
 same class name can be used in many
source units
 Naming: Usually start with LCL_...

Global Classes
 Are globally visible in the system like any
other function module, DDIC element, …
 Are edited with the Class Builder
transaction (SE24)
 Naming: Usually start with
</namespace/>CL_...
 Using global classes: like local classes

© 2011 SAP AG. All rights reserved. 16


Demo SE24

© 2011 SAP AG. All rights reserved. 17


Static (Class Level) Attributes

CL_CAR
Class vs. Instance Level
 Instance Attributes exist per instance no_of_instances = 6 name = Porsche
911
– defined with "DATA“
 Class attributes exist only once per class,
shared for all instances = 'static'
– defined with "CLASS-DATA"
name = VW Bug
1300

Usage class-data: separate instances and its data


 Suppose you want to know the 'number of
cars created'. Where would you do that?

 Increment where? How guarantee that it is


incremented only once per instance?
  Constructor of 'create method' …

© 2011 SAP AG. All rights reserved. 18


Using Static (Class Level) Attributes

Example: Instance Counter Definition


 Counter exists only once for the class, i.e. is
shared by all instances
 Counter is public read-only
Static attribute
 Constructor increments the count

Access static attributes with "=>"

Access class attributes using static operator "=>“


e.g. class_name=>attribute_name

© 2011 SAP AG. All rights reserved. 19


Using Static (Class Level) Methods

To access non-public class attributes Definition


you need class methods
 Methods exist on class level
 Defined with "CLASS-METHODS"
 Class methods have no access to instance
attributes
 A static method cannot be overwritten by
a subclass

Call static methods using "=>"

access class methods using static operator "=>“


e.g. class_name=>method_name

© 2011 SAP AG. All rights reserved. 20


Example: Factory Method
Using Create Method instead of Constructor

Definition

Motivation
• The class itself wants to control the object
instantiation, not the client
• E.g. ensure that object exists only once
or once per key
• The client wants always the same instance
without holding the instance

factory method
Other Benefits
• Client and class creation are loosely coupled
• You can return the object of a generic type see
interfaces
• You can use where-used-list to find the
object creators

Example: Introduce "factory method“


 If a class method is used to create an
object then you must set 'create private'
(no 'create object' outside class)
© 2011 SAP AG. All rights reserved. 21
Exercise 2: Class Methods and Data
Implement Instance Management

Exercise: Implement a factory method to create an object


 Ensure that an object with a given ID (='key') exists only once

Further Instructions
Copy the code from exercise 1 and change it in the following way:
 Replace the constructor by a static class method, e.g. "get_instance“ (keeping the parameter)
Change class definition to “create private“ to prevent the creation of objects outside the class.
Fix the appearing syntax errors (replace all CREATE OBJECTs with calls to get_instance)
 Remember in the creation method which cars were created (by name key):
use a static internal table with row type [string, type ref to lcl_car]
 If get_instance() is called again with the same key (e.g. 'VW Golf'), return the existing instance.

© 2011 SAP AG. All rights reserved. 22


Review of Exercise 2

Content
 Look at sample solution
 Show objects in debugger

lcl_car

- inst_table
- name
- tank_capacity
- fuel_consumption_per_km
- curr_tank_level
+ get_instance( )
+ refuel( )
+ drive_distance( )
+ get_curr_tank_level( )

© 2011 SAP AG. All rights reserved. 23


ABAP Objects Refresher
Module 3:

 Introduction to UML and object modeling


UML (Unified Modeling Language): Class
Syntax

© 2011 SAP AG. All rights reserved. 25


UML: Class Diagram
Static View of Classes and Their Relationships ('Associations')

Aggregation relation (= 'contains'  'is-part-of')

Generalization

© 2011 SAP AG. All rights reserved. 26


UML: Association
Syntax

© 2011 SAP AG. All rights reserved. 27


UML: Sequence Diagram
Who Calls Who and in What Order

Delegation Principle Visualized

© 2011 SAP AG. All rights reserved. 28


CRC Modeling
Classes – Responsibilities – Collaborations

CRC Modeling Method <Class Name>

Similar to UML classes but more abstract <Responsibilities> <Collaborations>


Use cards with
 class name
 responsibilities of class (bullet points: data
held, methods / operations offered)
 collaborations (names of other classes it Student
collaborates with)
has address professor
knows professors classes
enrolls in class exam scores
CRC cards are usually moved around to drop class
take exam
show relationships by location and arrows

© 2011 SAP AG. All rights reserved. 29


ABAP Objects Refresher
Module 4:

 OO Key Concept: Polymorphism


 Interfaces
 Various uses of interfaces
OO Key Concept: Polymorphism
Depend Upon Abstractions, not on Concrete Implementations

Motivation
• Support Polymorphism = 'having multiple forms‘
• Several implementations for the same abstract interface
examples in the non-OO world: BAdIs or Customizing with callback function modules
• You want to offer (future) extensibility

Some Examples
 Imagine 'generic save' method on each object any_storable_obj->save_your_data_to_db( ).

 Imagine an archive manager that needs data


archive_manager->archive( archivable_obj ).
in a specific format of its objects to be archived
 Imagine a refuel method for all kinds of vehicles any_vehicle>refuel( 45,2 ).

© 2011 SAP AG. All rights reserved. 31


Polymorphism: Interfaces
Definition – Implementation – Client

Interface Definition

… is like the definition of a class


• It contains elements like types, methods, …
• But all elements are public

Interface Implementation

• A class can implement many interfaces

‘full name’ of element: <if_name>~<elem_name>

Client
• Interface references allow access to all interface elements
i.e. regardless of implementing class

Specify class when using interface reference

Object reference can be 'converted' to an


interface reference type that it implements (cast)

© 2011 SAP AG. All rights reserved. 32


Exercise 3: Interfaces for Generic Object Access

Exercise: Access different vehicle types via a common interface

Further Instructions
Copy the code from exercise 2 and change it in the following way:
 Define an interface 'lif_vehicle' with methods
– Copy the methods refuel, drive_distance and get_current_tank_level into the interface (from exercise 1)
 Define and implement a class ‘lcl_truck’ that implements the 'lif_vehicle' interface.
 Let the ‘lcl_car’ class implement the 'lif_vehicle‘ interface
– Remove methods contained in the interface from the class definition
– Rename the method names of the implementation
 In the report:
– Create several trucks in addition to the cars and drive some distances
– Collect references to all vehicles in an internal table using the interface type
– Loop over the table, check that the current tank level is less than 100% and then refuel all of them

© 2011 SAP AG. All rights reserved. 33


Review of Exercise 3

Content lif_vehicle
<<interface>>
 Look at sample solution
 Show objects in debugger get_current_tank_level( )
refuel( )
drive_distance( )

lcl_car lcl_truck

- name
- inst_table
- tank_capacity
- name
- fuel_consumption_per_km
- tank_capacity
- curr_tank_level
- fuel_consumption_per_km
- curr_tank_level …special truck methods

+ get_instance( )
…special car methods

© 2011 SAP AG. All rights reserved. 34


Various Uses of Interfaces
Some Purposes

1. Generic interface / access to objects from frameworks


 Which data is required from the client in which format
 Other interactions with the client e.g. notifications, call backs
 Example: Each class whose objects need to be archived implement the 'archiving interface'.

2. Decouple implementation from interface


• Exchange the implementing class

3. Decoupling during development


• E.g. you need to 'use' / call a class that is built by another developer but is not there yet
• You agree together on the interface. Then the 'caller' can use the interface while the developer has
time to implement the interface.

© 2011 SAP AG. All rights reserved. 35


ABAP Objects Refresher
Module 5:

 Polymorphism: Inheritance
Polymorphism: Inheritance/Subclassing/Derivation
Class Hierarchy

Motivation
• Inheritance is a means to implement conceptual
hierarchies and/or share common code between
classes lcl_vehicle

• A super class implements the characteristics that are


common to all its subclasses + refuel()
+ drive_distance()
• Subclasses are specializations that can do more …

Inheritance
• The subclass inherits the data and behavior
from its superclass: it can access/redefine all
components of its super class

Technical Restriction
 Class/static components cans not be redefined
 A class can only inherit from one class

© 2011 SAP AG. All rights reserved. 37


Polymorphism: Inheritance/Subclassing/Derivation
Parent Class - Subclass

Parent Class

• The parent class must be opened up for derivation:


the final flag has to be removed

• New visibility level protected:


components visible in class and subclasses

Subclass

• Subclass can define further attributes and methods

• Subclass can access all components of its super class


that are protected or public

• Subclass can redefine all methods of its super class


that are protected or public

• Subclass can call the implementation of the parent class

© 2011 SAP AG. All rights reserved. 38


Exercise 4: Use Inheritance

lif_vehicle
Exercise: Move common code to a super-class <<interface>>

Further Instructions get_current_tank_level( )


Copy code from exercise 3 to new program refuel( )
drive_distance( )
 Create class lcl_vehicle that implements the lif_vehicle interface
(which contains the three methods…)
 Move data and implementation of interface methods from lcl_car to
vehicle level and make it protected so that the subclasses can
access them lcl_vehicle
<<abstract>>
 Define lcl_car and lcl_truck as subclasses of vehicle (note: the
- name
existing interface method implementations are no longer needed - tank_capacity
since they are implemented in the super-class vehicle) - fuel_consumption_per_km
 The truck can do more: It has a reserve tank that has its own - curr_tank_level
capacity and must be refueled as well and needs its own get tank
level method
– You can call the refuel() method of the vehicle to get the main tank
refueled
lcl_car lcl_truck
 Create a few vehicles and drive some distances using the vehicle
- inst_table
interface (table) as in exercise 3 reserve_tank_level

+ get_instance( )
+ refuel( ): redefinition
+ get_reserve_tank_level()

© 2011 SAP AG. All rights reserved. 39


Review of Exercise 4

Content
 Look at sample solution
 Show objects in debugger

© 2011 SAP AG. All rights reserved. 40


Polymorphism: Inheritance and Delegation
Additional Notes

• Inheritance entails a very strong coupling between classes and should not be misused just
as a convenient means to share implementation code!

• Key Rule: A subclass must do the same (or more) as its parent / super class
• Liskov Substitution Principle: “Behavior 'promises' by the ‘interface’ of a class C must be satisfied
by all its subtypes S’
• Typical violation: Square class is subclass of Rectangle? NO: Subclass ≠ Subset!
Rectangle client code will expect to set width and height independently

• Therefore it is wise to prefer delegation over inheritance whenever possible,


i.e. have a class beside that implements the common parts

Cparent S¹ Cany¹

S¹ S² S² Cany²
Inheritance Delegation

© 2011 SAP AG. All rights reserved. 41


ABAP Objects Syntax
QT3: ABAP_ASE_OO_INTRO_LANG_REF

ABAP Objects Sample Code as Syntax Reference

Definition Main Program

Implementation

© 2011 SAP AG. All rights reserved. 43


Sample Solutions
Implementation QT3: ABAP_ASE_OO_INTRO_P1_SOL

Exercise 1 (QT3 System)

Definition Implementation

© 2011 SAP AG. All rights reserved. 45


QT3: ABAP_ASE_OO_INTRO_P1_SOL

Exercise 1 (QT3 System) lcl_car

- name
- tank_capacity
Main Program - fuel_consumption_per_km
- curr_tank_level
+ constructor()
+ refuel( )
+ drive_distance( )
+ get_curr_tank_level( )

Back to Exercise
© 2011 SAP AG. All rights reserved. 46
QT3: ABAP_ASE_OO_INTRO_P2_SOL

Exercise 2 (QT3 System)

Definition Implementation

© 2011 SAP AG. All rights reserved. 47


QT3: ABAP_ASE_OO_INTRO_P2_SOL

Exercise 2 (QT3 System)


lcl_car

- inst_table
- name
Main Program - tank_capacity
- fuel_consumption_per_km
- curr_tank_level
+ get_instance( )
+ refuel( )
+ drive_distance( )
+ get_curr_tank_level( )

Back to Exercise
© 2011 SAP AG. All rights reserved. 48
QT3: ABAP_ASE_OO_INTRO_P3_SOL

Exercise 3 (QT3 System)

New Interface New Truck Class – Implementation

New Truck Class – Definition

© 2011 SAP AG. All rights reserved. 49


QT3: ABAP_ASE_OO_INTRO_P3_SOL

Exercise 3 (QT3 System)

Changed Car Class – Definition

Changed Car Class – Implementation

© 2011 SAP AG. All rights reserved. 50


QT3: ABAP_ASE_OO_INTRO_P3_SOL

Exercise 3 (QT3 System)


lif_vehicle
<<interface>>
Main Program
get_current_tank_level( )
refuel( )
drive_distance( )

lcl_car lcl_truck

- name
- inst_table
- tank_capacity
- name
- fuel_consumption_per_km
- tank_capacity
- curr_tank_level
- fuel_consumption_per_km
- curr_tank_level …special truck methods

+ get_instance( )
…special car methods

Back to Exercise
© 2011 SAP AG. All rights reserved. 51
QT3: ABAP_ASE_OO_INTRO_P4_SOL

Exercise 4 (QT3 System)


New Abstract Vehicle Class Changed Car Class

© 2011 SAP AG. All rights reserved. 52


QT3: ABAP_ASE_OO_INTRO_P4_SOL

Exercise 4 (QT3 System)


lif_vehicle
<<interface>>

Changed Truck Class


get_current_tank_level( )
refuel( )
drive_distance( )

lcl_vehicle
<<abstract>>
- name
- tank_capacity
- fuel_consumption_per_km
- curr_tank_level

lcl_car lcl_truck
- inst_table
reserve_tank_level

+ get_instance( )
+ refuel( ): redefinition
+ get_reserve_tank_level()

© 2011 SAP AG. All rights reserved. 53


QT3: ABAP_ASE_OO_INTRO_P4_SOL

Exercise 4 (QT3 System)

Main Program

Back to Exercise

© 2011 SAP AG. All rights reserved. 54


© 201 SAP AG. All rights reserved.

No part of this publication may be reproduced or transmitted in any form or for any purpose Google App Engine, Google Apps, Google Checkout, Google Data API, Google Maps,
without the express permission of SAP AG. The information contained herein may be Google Mobile Ads, Google Mobile Updater, Google Mobile, Google Store, Google Sync,
changed without prior notice. Google Updater, Google Voice, Google Mail, Gmail, YouTube, Dalvik and Android are
trademarks or registered trademarks of Google Inc.
Some software products marketed by SAP AG and its distributors contain proprietary
software components of other software vendors. INTERMEC is a registered trademark of Intermec Technologies Corporation.
Microsoft, Windows, Excel, Outlook, PowerPoint, Silverlight, and Visual Studio are Wi-Fi is a registered trademark of Wi-Fi Alliance.
registered trademarks of Microsoft Corporation.
Bluetooth is a registered trademark of Bluetooth SIG Inc.
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 Motorola is a registered trademark of Motorola Trademark Holdings LLC.
Architecture, Power Systems, POWER7, POWER6+, POWER6, POWER, PowerHA, Computop is a registered trademark of Computop Wirtschaftsinformatik GmbH.
pureScale, PowerPC, BladeCenter, System Storage, Storwize, XIV, GPFS, HACMP,
RETAIN, DB2 Connect, RACF, Redbooks, OS/2, AIX, Intelligent Miner, WebSphere, Tivoli, SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer,
Informix, and Smarter Planet are trademarks or registered trademarks of IBM Corporation. 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
Linux is the registered trademark of Linus Torvalds in the United States and other countries. and other countries.
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are trademarks or registered Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal
trademarks of Adobe Systems Incorporated in the United States and other countries. Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services
Oracle and Java are registered trademarks of Oracle and its affiliates. mentioned herein as well as their respective logos are trademarks or registered trademarks
of Business Objects Software Ltd. Business Objects is an SAP company.
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
Sybase and Adaptive Server, iAnywhere, Sybase 365, SQL Anywhere, and other Sybase
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin products and services mentioned herein as well as their respective logos are trademarks or
are trademarks or registered trademarks of Citrix Systems Inc. registered trademarks of Sybase Inc. Sybase is an SAP company.
HTML, XML, XHTML, and W3C are trademarks or registered trademarks of W3C®, Crossgate, m@gic EDDY, B2B 360°, and B2B 360° Services are registered trademarks
World Wide Web Consortium, Massachusetts Institute of Technology. of Crossgate AG in Germany and other countries. Crossgate is an SAP company.
Apple, App Store, iBooks, iPad, iPhone, iPhoto, iPod, iTunes, Multi-Touch, Objective-C, All other product and service names mentioned are the trademarks of their respective
Retina, Safari, Siri, and Xcode are trademarks or registered trademarks of Apple Inc. companies. Data contained in this document serves informational purposes only. National
product specifications may vary.
IOS is a registered trademark of Cisco Systems Inc.
The information in this document is proprietary to SAP. No part of this document may be
RIM, BlackBerry, BBM, BlackBerry Curve, BlackBerry Bold, BlackBerry Pearl, BlackBerry reproduced, copied, or transmitted in any form or for any purpose without the express prior
Torch, BlackBerry Storm, BlackBerry Storm2, BlackBerry PlayBook, and BlackBerry App written permission of SAP AG.
World are trademarks or registered trademarks of Research in Motion Limited.

© 201 SAP AG. All rights reserved.

You might also like