You are on page 1of 20

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic

by Christian Assig, Aldo Fobbe, and Arno Niemietz


This document is for your personal use only. Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services. For information about SAP Professional Journal and other WIS publications, visit www.WISpubs.com.

Christian Assig Developer, IOT GmbH, Germany

To provide a more detailed representation of production processes than ERP systems typically do, German company IOT GmbH began developing its own manufacturing execution system (MES) in 2003 using custom development based on SAP technology. The system needed to include applications with user interfaces (UIs) to display and edit production data, as well as background applications to communicate with other systems, such as ERP systems or shop-floor control systems. This article explores how we met this challenge and how you might apply our experience to your needs. We began our development using SAP Web Application Server (SAP Web AS) 6.20. By doing so, we deliberately chose to create a new system from scratch based on the mature, highly productive development environment of SAP Web AS ABAP. It enabled us to use all of the possibilities and advantages of object-oriented software development. By using ABAPs Object Services, we also had a powerful library of services at hand to provide the ready-to-use functionalities needed in the development of every system (e.g., to load objects from the database or to save objects to the database). Developing our system using Object Services reduced our costs for the whole software development process. This article covers our experiences in the practical use of ABAPs Object Services: the Persistence Service and the Transaction Service. We also briefly explain the Query Service that SAP NetWeaver 7.0 added to ABAPs Object Services, but its not our primary focus. For us, using Object Services led to both a clean division between database access and application logic, and considerable time-savings in the development and enhancement of large information systems. From our point of view, the fundamental concepts of Object Services (discussed in Object Services on the next page) have proven themselves entirely in practice. We also discuss whether adding a fully integrated lock service to Object Services could lower the inhibition threshold for its use.

Aldo Fobbe Mgr. of Product Dev. & Tech., IOT GmbH, Germany

Arno Niemietz Founder and Managing Dir., IOT GmbH, Germany

(Full bios appear on page 52.)

No portion of this publication may be reproduced without written consent.

33

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

This article is for system architects who want to know how Object Services support the division of object-oriented business logic and database access; software developers who want information on how to use Object Services in ABAP software development; and Chief Information Officers (CIOs) who want a picture of some of the capabilities of programming with ABAP Objects.

Load all objects that match a given criteria from the database (the Query Service) Control which changes to send to the database and when (the Transaction Service)

The Persistence Service


In most object-oriented programming languages, objects initially exist briefly in the systems main memory at runtime. To save data permanently to storage media, such as databases or file systems, you need to program the Save and Load operations. As an alternative, you can introduce a generic service such as the Persistence Service in ABAP. The Persistence Service provides an automated way to save objects to and load objects from a relational database, also referred to as object-relational mapping. Other popular libraries providing object-relational mapping include Hibernate and Enterprise JavaBeans, which are both used in Java applications. The Persistence Service of ABAPs Object Services enables you to map the attributes of persistent objects to fields in database tables. In general, one line in the database table corresponds to one persistent object. To create a persistent class, select the class type Persistent class when creating the class as shown in Figure 1.

Prerequisites
To understand the main ideas of this article, you should have some knowledge of the principles of object-oriented software development: What is a class? What is a method? What is an interface? To get more insight into how to use Object Services in practice, some basic knowledge of ABAP is helpful as well.

This article focuses on explaining some of the capabilities delivered by Object Services and how you can use each component in real-world projects. You can find a more detailed description about how to use these components on the SAP Help Portal (http://help. sap.com).

Object Services
ABAPs Object Services are global services implemented by SAP and delivered with every SAP NetWeaver AS ABAP. They enable programmers of object-oriented software to: Load objects from and save objects to a relational database (the Persistence Service)
For an introduction to Object Services, see Write Smarter ABAP Programs with Less Effort: Manage Persistent Objects and Transactions with Object Services by Stefan Bresch, Christian Fecht, and Christian Stork (SAP Professional Journal, January/February 2002).

Figure 1

Creating a persistent class

34

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Figure 2

The persistence representation dialog

Figure 2 shows the GUI available in every persistent class that enables you to define the mapping between class attributes and database table fields. You can complete the whole process of creating a persistent class, including defining the persistence representation, without manually writing a single line of code. When you create a persistent class, the development environment automatically generates the ABAP source code to manage the objects of the class. The generated code includes methods: to read and change the attributes of an object in the persistent class; to load objects from the database; to save changes of an object already in the database; and to delete objects from the database. To create a persistent class including object-relational mapping, you dont have to write a single line of code manually. Just click a radio button when you create the class (Figure 1). Then, you define the mapping with the UI (Figure 2). You arent supposed to make any changes to the

methods the Persistence Service generates; you just call them from other classes or methods. The application logic can rely completely on the persistent classes you have created to manage the data. That way, its possible to develop objectoriented applications with all of the capabilities of data management in a database without having to write a single SQL statement. Its also possible to save the state of an object (i.e., the values of its attributes) in multiple database tables (e.g., to support inheritance) with the Persistence Service. It supports the object-oriented concept of inheritance (i.e., a way of forming new classes using other, previously defined classes) between persistent classes. So, the persistence representation of a superclass (i.e., a parent class from which you derive other classes) can define a mapping of the general attributes of the superclass to one database table. Then, each subclass (i.e., a child class,

No portion of this publication may be reproduced without written consent.

35

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

which you derive from a superclass from which the subclass inherits some properties) can supplement the persistence representation by mapping its specific attributes to a different database table. Having the Persistence Service manage the persistent objects ensures that only one instance of each persistent object exists in the current work processs main memory. (Work process refers to the running ABAP program.) If a work process asks the Persistence Service to load an object that the same work process has previously loaded from the database, the Persistence Service returns a reference to that objects existing instance without involving the database. In this way, the Persistence Service prevents inconsistencies that might occur by working with multiple instances of the same object in a single work process, and saves the extra costs of unnecessary database accesses. You can use fields of any elementary data type (e.g., text, date, number) to define the attributes of a persistent class. In addition, the Persistence Service can automatically manage references to other persistent objects. For example, if persistent object A has an attribute that references persistent object B, the system stores the reference to persistent object B in the database as a unique key. The next time persistent object A is loaded from the database, the Persistence Service uses this unique key to rebuild the reference to persistent object B. To enhance performance, the Persistence Service doesnt load referenced objects from the database unless you need data from their attributes. Instead, the Persistence Service only loads referenced objects from the database when it is explicitly told to do so or when the system needs to access a specific attribute. Persistent classes have two kinds of attributes: persistent and transient. The content of a persistent attribute is stored automatically in a field in the database. When a persistent object is loaded, the Persistence Service automatically restores the values of the persistent attributes. A transient attribute is not saved to the database automatically. The content of a transient attribute

is set at runtime. After the system loads a persistent object from the database, it sets each transient attribute to its appropriate initial value. Transient attributes are useful for redundantly storing information that the object can determine or calculate from other attributes (e.g., a duration, which can be calculated as the difference between a start date and an end date). In addition to the attributes of a persistent object, the Persistence Service maintains a management state for each persistent object. The management state of a persistent object is used to determine whether the object exists on the database in the same state. For instance, an object in the management state changed was already modified in main memory, but the modifications have not been sent to the database yet. A new object was only created in main memory, but does not exist in the database. Depending on the actions you perform on an object, its management state may change, as shown in Figure 3. The potential management states include: loaded, new, deleted, and changed. You start working with a persistent object either by loading (the management state equals loaded) or creating an object (the management state equals new). By deleting a loaded object, the management state becomes deleted; by changing the objects attributes using a SET method, the management state becomes changed. Additional transitions can occur in conjunction with the Transaction Service; they have been left out of Figure 3 for simplicity. When working with a persistent object that contains transient attributes with the default settings of the Persistence Service, you should note that if you change the value of a transient attribute, the Persistence Service marks the persistent object as changed. In other words, at the end of the transaction, the Persistence Service writes the object to the database even if no persistent attribute has changed. We recommend changing the corresponding setting in the persistence representation (Figure 2) to avoid this behavior (select Goto Generator Settings, and enable the Changes to transient attributes do not cause saving of persistent attributes setting). After this setting is changed, the Persistence Service will only write data to the database when persistent attributes

36

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

CREATE_PERSISTENT

NEW

GET_PERSISTENT REFRESH_PERSISTENT GET_PERSISTENT LOADED GET_attribute

DELETE_PERSISTENT

NOT LOADED

SET_attribute

CREATE_PERSISTENT CHANGED SET_attribute

CREATE_PERSISTENT DELETE_PERSISTENT

DELETE_PERSISTENT DELETE_PERSISTENT

DELETED

RELEASE

RELEASE

Figure 3

Unified Modeling Language (UML) state diagram of the management states of persistent objects

have changed (i.e., when data in the database actually needs to be modified). While using Object Services at IOT GmbH, some situations displayed the need for reusable components to perform the Object Services tasks that occur frequently. For instance, SAP UI elements, such as SAP List Viewer (ALV) grids, show the data from structured internal tables. We developed a generic component that encapsulates the access to an ALV grid and deals with persistent objects. This component automatically converts data from the attributes of any persistent object supplied to it into the fields of an internal table. Thus, it shows data from persistent

attributes in SAP UI elements. The component also works in the opposite direction (i.e., the user can change data in an SAP UI element and the compo-nent will automatically apply the changes to the persistent objects). In contrast to an object from a usual ABAP class, the garbage collector doesnt remove a persistent object from memory when there are no references to it. In this way, the system can make sure that it only loads an object from the database once in each work process (avoiding unnecessary database traffic), even if you ask the Persistence Service to supply a reference to the same object more than once. If you need

No portion of this publication may be reproduced without written consent.

37

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

to reduce the amount of main memory used because a work process has loaded too many persistent objects, you can manually release specific persistent objects from the management of the Persistence Service. After you release a persistent object, you can no longer access it with existing references. When there are no more references to a released persistent object, the garbage collector reclaims the memory that the object used. If all of the applications in a system use the Persistence Service, they will deal with many persistent objects from different persistent classes. So, you should implement methods that work with multiple objects. With some infrequently used functionalities for managing persistent objects, the Persistence Service offers methods that it can execute for a single object, but these methods can be too laborious to handle a multitude of persistent objects. Therefore, IOT GmbH implemented a custom component that allows us to refresh the state of numerous persistent objects by loading them from the database again or by releasing multiple objects from the main memory. With our custom component, we can both refresh and release all persistent objects from all persistent classes or, in a more targeted way, from a specified persistent class. You need the refresh mechanism when you update, for example, the data displayed in a UI. When youre about to execute a new selection of objects from the database, you should release all previously loaded persistent objects. That way, the new selection loads the current state of the persistent object from the database, and the amount of memory used doesnt increase with each selection you execute. In persistent classes, the system automatically generates the methods that read and change the attributes values. An implementation contains neither plausibility checks nor any kind of application logic. To integrate application logic or lazy load2 mechanisms into persistent classes, only a few laborious or error-prone alternatives were available for a long time. You could manually implement a method for every
2

attribute you want to access, but you cant use method names that start with GET or SET since the system automatically generates these methods in persistent classes. Thus, the system doesnt allow you to manually implement any methods with a name starting with GET or SET in persistent classes. As an alternative, you could limit the use of a persistent class to an object-relational mapper, which means that youd have to implement application logic outside the persistent classes. Since the release of SAP NetWeaver Application Server (SAP NetWeaver AS) 7.0, however, the Enhancement Framework has provided a new way of integrating application logic into persistent classes. The Enhancement Framework enables you to modify any kind of program code in SAP NetWeaver AS ABAP without changing the original code. Instead, SAP NetWeaver AS ABAP checks during runtime to see if any enhancements are available for the original code it is about to execute and whether these enhancements are switched on. This approach is the new, unified way for customers to make changes to SAP code in their systems; previously, you could make changes by using the Modification Assistant, Customer Exits, and Business Add-Ins. At this time, we dont know whether the Enhancement Framework will be the best option for integrating application logic into persistent classes. However, its approach enabling the integration of custom code into the GET and SET methods of persistent classes seems promising.

The Query Service


To load an object from the database using only the Persistence Service, you need to know the objects key. With the introduction of Query Service with SAP NetWeaver 7.0, however, you can use Object Services to instantiate objects that meet certain selection criteria without knowing their keys. You no longer need to manually implement any kind of SQL statement to determine the keys of the objects. For example, you might want to select all flights departing on a given date. Figure 4 shows how you had to do this before the introduction of the Query Service. You had to manually implement an Open SQL statement to identify the keys of all objects

A lazy load is a design pattern used to avoid loading objects unnecessarily. Instead of loading all of the objects that another object references immediately, this pattern loads them when you need them.

38

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

DATA: ta_keys_sflight TYPE STANDARD TABLE OF scol_flights_key. DATA: rf_agent_sflight TYPE REF TO zca_sflight. DATA: ta_ro_flights TYPE osreftab. * Get reference to agent of persistent class (singleton pattern) rf_agent_sflight = zca_sflight=>agent. * 1st SQL statement: Read keys of objects from the database SELECT carrid connid fldate INTO CORRESPONDING FIELDS OF TABLE ta_keys_sflight FROM sflight WHERE fldate = '20071031'. IF LINES( ta_keys_sflight ) > 0. * Load objects from database CALL METHOD rf_agent_sflight->if_os_ca_persistency~get_persistent_by_key_tab EXPORTING i_key_tab = ta_keys_sflight RECEIVING result = ta_ro_flights. ENDIF. -------------------------------------------------------------------------------------* 2nd SQL statement: Load objects from the database * (generated by the Persistence Service) select * from SFLIGHT into table DB_DATA_LOCAL_TAB for all entries in I_BUSINESS_KEY_TAB where SFLIGHT~CARRID = I_BUSINESS_KEY_TAB-CARRID and SFLIGHT~CONNID = I_BUSINESS_KEY_TAB-CONNID and SFLIGHT~FLDATE = I_BUSINESS_KEY_TAB-FLDATE.

Figure 4

Selecting and loading objects without the Query Service

matching the criteria. The Persistence Services method get_persistent_by_key_tab() loaded those objects that corresponded to the keys from the database. This included using a second SQL statement, which the Persistence Service generated automatically. Instead of using these two database queries, as shown in Figure 4, you only execute one database query when you use the Query Service. It loads all of the objects that match the selection criteria, as

shown in Figure 5 on the next page. So, the Query Service replaces any kind of manually implemented SQL statements with an object-oriented interface to simplify the use of the Persistence Service. It also reduces the database load, since it combines multiple database queries that were previously executed separately into one query. Now that weve covered the link between objects in the main memory and their relational representa-

No portion of this publication may be reproduced without written consent.

39

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

DATA: ri_query_manager TYPE REF TO if_os_query_manager. DATA: ri_query TYPE REF TO if_os_query. * Create query ri_query_manager = cl_os_system=>get_query_manager( ). ri_query = ri_query_manager->create_query( i_filter = 'FLDATE = ''20071031'''). * Execute query: Load objects matching the query filter from the database CALL METHOD rf_agent_sflight->if_os_ca_persistency~get_persistent_by_query EXPORTING i_query = ri_query RECEIVING result = ta_ro_flights. -------------------------------------------------------------------------------------* Only 1 SQL statement generated by the Query Service: * All objects matching the query filter are loaded * from the database select * from SFLIGHT up to I_UPTO rows into table DB_DATA_LOCAL_TAB where (I_WHERE_CLAUSE) order by (I_ORDER_BY_CLAUSE). * In this case, the value of I_WHERE_CLAUSE is: * SFLIGHT~FLDATE = '20071031'

Figure 5

Selecting and loading objects with the Query Service

tions in databases, lets look at how to manage object changes, which the Transaction Service provides.

The Transaction Service


With the help of the Transaction Service, an application can decide whether and when to write any object changes to the database or discard them. The term transaction describes a logical unit that consists of multiple changes. The system must execute either all of the changes from a transaction or none of them; otherwise, the changes would leave the system in an inconsistent state. For example, after you transport some amount of material from one location to another, you have to update the inventory data for

both the source location and the target location. If the amount of material at the target location increases and the corresponding amount of material at the source location doesnt decrease, an inconsistent state results. The material you transported is now attributed to both the source location and the target location. By combining the inventory changes into one transaction, you can ensure that no such inconsistency occurs. Within the SAP environment, the term transaction has different meanings. It can refer to an ABAP program executed using a transaction code. However, within the environment of the object-oriented Transaction Service and this article, the term transaction has a general meaning, as in the inventory example we just discussed.

40

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Before the introduction of the Transaction Service, there were two ways to group changes to database data into transactions. Both of these are referred to as logical units of work (LUWs): An LUW on the database layer (database LUW) ensures, independent of the application server, that all of the changes in one LUW either are saved together or are not saved persistently at all. You can also define a transaction by using an LUW on the application server layer (SAP LUW). You apply any changes from an SAP LUW persistently with the ABAP statement COMMIT WORK, and you discard them with the ABAP statement ROLLBACK WORK.

cally closes the database LUWs. This makes it hard for an application developer to create transactions in a controlled way with database LUWs, which leaves SAP LUWs as the only real option for transactions. Without Object Services, changes made by executing a SQL statement went to the database immediately. To access the database and make the changes event-based at the end of the transaction, you had to implement a new update module manually for each kind of data change, as shown in Figure 6. The Transaction Service also uses the concept of SAP LUWs internally, yet it offers a multitude of additional possibilities. From a developers point of view, you only need to work with the transaction objects of the Transaction Service. You dont have to consider the underlying technical details such as database LUWs and SAP LUWs. Both Figure 6 and Figure 7 (on page 43) show a simple example

SAP LUWs can embrace multiple database LUWs. In applications that include UIs or calls to remote systems, the runtime environment automati-

DATA: st_flight * Load SELECT INTO FROM WHERE AND AND

TYPE sflight.

flight data from the database into a structure SINGLE * CORRESPONDING FIELDS OF st_flight sflight carrid = 'AA' connid = '0064' fldate = '20071228'.

* Change the flight data in the structure st_flight-planetype = '747-400'. * Register update function module to change data in the database CALL FUNCTION 'Z_UPDATE_SFLIGHT' IN UPDATE TASK EXPORTING im_sflight = st_flight. * Finish classical SAP logical unit of work, * invoking the execution of the update module COMMIT WORK. -------------------------------------------------------------------------------------Continues on next page

Figure 6

Changing a flight without Object Services

No portion of this publication may be reproduced without written consent.

41

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

FUNCTION z_update_sflight. *"---------------------------------------------------------------------*"*"Update Function Module: *" *"*"Local Interface: *" IMPORTING *" VALUE(IM_SFLIGHT) TYPE SFLIGHT *"---------------------------------------------------------------------UPDATE sflight FROM im_sflight. ENDFUNCTION.

Figure 6 (continued)

of a change made to an object within the scope of a transaction. This example loads a flight object from the database, which changes the type of plane used for the flight and writes the modified object back to the database. The example in Figure 6 performs these actions without using Object Services. An Open SQL statement loads the data from the database. To save the changes to the database at the end of the SAP LUW, the application registers an update function module. The system executes the update function module when the COMMIT WORK statement is performed. Figure 7 does the same thing, but using Object Services. After the application starts a transaction, the Persistence Service loads the flight object rf_flight from the database. The plane type attribute planetype is changed in the persistent object. Finishing the transaction writes the modified object to the database. In addition to changing data in the database, transactions record all changes to persistent objects. When you finish a transaction by calling its end() method, the system retains all of the changes that it performed in the transaction. In contrast, when a transaction calls the undo() method, the system discards all of the changes that it performed in the transaction. When you use the Persistence Service and the Transaction

Service, the system wont transfer changes to the database until the system is certain that the database will apply the changes persistently. If you make changes to persistent objects on the application server and the system discards them later, your changes wont get to the database. This approach reduces the database load and avoids any additional implementation effort for specific update modules. In contrast to the ROLLBACK WORK statement for an SAP LUW, the impact of the Transaction Services undo() method isnt limited to the database. It also affects persistent objects in the running work processs main memory. When you execute a transactions undo() method, a persistent object returns to its initial state at the time the transaction started. The Transaction Service discards all changes to the persistent objects attributes, as well as the creation or deletion of any persistent objects. Therefore, an application might continue working after executing the undo() method without needing to reload data from the database to manually restore its previous state. Unlike SAP LUWs, you can nest Transaction Service transactions as arbitrarily deep as you want. The first transaction you open is considered to be on the highest level and is referred to as the top-level transaction. When you close the top-level transaction,

42

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

DATA: DATA: DATA: DATA:

rf_flight rf_agent_flights ri_transaction_manager ri_transaction

TYPE TYPE TYPE TYPE

REF REF REF REF

TO TO TO TO

zcl_sflight. zca_sflight. if_os_transaction_manager. if_os_transaction.

* Get reference to transaction manager ri_transaction_manager = cl_os_system=>get_transaction_manager( ). * Get reference to class agent of flight class rf_agent_flights = zca_sflight=>agent. * Create and start a transaction ri_transaction = ri_transaction_manager->create_transaction( ). ri_transaction->start( ). * Load a flight from the database rf_flight = rf_agent_flights->get_persistent( i_carrid = 'AA' i_connid = '0064' i_fldate = '20071228' ). * Change an attribute of the flight rf_flight->set_planetype( '747-400' ). * Write the transaction to the database by finishing the transaction ri_transaction->end( ).

Figure 7

Changing a flight with Object Services

the Transaction Service writes all changes performed in the scope of this transaction to the database. If you open a new transaction while another transaction is still running, the new transaction becomes a sub-transaction of the transaction already running. This way, you can selectively discard changes made to persistent objects in the scope of a sub-transaction while you retain changes made before the subtransaction began. For example, when an exception occurs in the middle of a business process, you can use sub-transactions to revoke changes made to persistent objects by returning to a consistent state that existed before the business process began. You simply execute the undo() method of the sub-transaction and all persistent objects will return to the state they were in when the sub-transaction began.

Afterward, the application might continue to execute further process steps or wait for user input where appropriate. To implement the same behavior without the Transaction Service, you would have to manually copy all of the data that might change to enable the restoration of the previous dataset. You can use the Transaction Service in two different transaction modes: object-oriented and compatibility. To obtain the most benefits from the Transaction Service, you should use the objectoriented mode, in which you only have to use transaction objects. You dont need to execute the statements COMMIT WORK and ROLLBACK WORK in your code; in fact, the Transaction Service forbids you from using them in the object-oriented mode. If an application still contains processing

No portion of this publication may be reproduced without written consent.

43

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

create_transaction (implicitly) Application start (implicitly) Transaction

COMMIT WORK end (implicitly) {OR} ROLLBACK WORK undo (implicitly)

Figure 8

UML sequence diagram of compatibility mode

blocks that use COMMIT WORK or ROLLBACK WORK, you can use the compatibility mode. In compatibility mode, you can use many of the features of the Transaction Service, but at the end of the transaction, you have to treat top-level transactions and sub-transactions differently. While you can still finish sub-transactions with the methods of a transaction object, you use the statements COMMIT WORK and ROLLBACK WORK to finish a top-level transaction. If an application doesnt call any processing blocks that contain COMMIT WORK or ROLLBACK WORK, you should use the object-oriented mode so that you dont need to differentiate between top-level transactions and sub-transactions. Moreover, these transaction objects include additional techniques for consistency-checking and error-handling that are not available with the COMMIT WORK and ROLLBACK WORK statements.

Figure 8 shows how the system internally handles the different statements for finishing transactions in compatibility mode.3 At the beginning of the application, the runtime environment implicitly creates and starts an object-oriented transaction. When the runtime executes a COMMIT WORK or a ROLLBACK WORK statement, the object-oriented transaction is implicitly finished. Figure 9 shows the same information for objectoriented mode. Here, the application itself creates and starts an object-oriented transaction. When the application finishes a transaction, either by calling its
3

Similar to the syntax conventions for ABAP on the SAP Help Portal (http://help.sap.com), the figures used in this article use uppercase letters for keywords and options belonging to the ABAP language itself, while names of variables, methods, classes, and so on are written in lowercase letters.

44

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Application

create_transaction Transaction

start

end COMMIT WORK

{OR}

undo ROLLBACK WORK

Figure 9

UML sequence diagram of object-oriented mode

or undo() method, the transaction, among other things, executes the COMMIT WORK statement or the ROLLBACK WORK statement, respectively. The application doesnt use either COMMIT WORK or ROLLBACK WORK directly.
end()

attempt to finish a transaction by calling its end() method, it automatically calls all checking agents, one after another. If even one checking agent reports an inconsistent state, the transaction wont finish; the Transaction Service will throw an exception. You can register every object from a class that implements the interface IF_OS_CHECK as a checking agent. When this interface is implemented, it may include arbitrary checks adapted to a systems specific requirements. The interface is most often implemented directly in a persistent class. That way, the persistent object itself can check the consistency of its own attributes; it becomes its own checking agent. Typically, you only register a checking agent if one or more of the objects attributes changes. If the

To transition a system from one consistent state to another, its not enough to guarantee that all of the changes you have executed have been saved persistently. Before you save the changes, you need to verify that they left the system in a semantically consistent state. If the new state is not consistent, you need to abort the transaction. The Transaction Service offers the capability of registering so-called checking agents with a running transaction to perform consistency checks at the end of the transaction. When you

No portion of this publication may be reproduced without written consent.

45

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

data doesnt change, you havent introduced any new inconsistencies. When you use Object Services, be sure that you perform every write access to the database with persistent objects. In theory, you can perform write accesses to the database by directly executing SQL statements even though youre using Object Services. However, in practice, when a sub-transaction executes an undo(), it doesnt reverse these direct changes. In other words, direct SQL write access to the database in a sub-transaction leaves the system in an inconsistent state if you then execute an undo() on the sub-transaction.

object-oriented mode. If you use legacy code that contains COMMIT WORK statements in your application, you set this parameter to oscon_true to tell the Transaction Service to run in compatibility mode. If you dont need compatibility to the COMMIT WORK statements, you set the parameter to oscon_false to run in object-oriented mode. i_update_mode: This parameter sets the update mode and defines how the transaction will write changes to the database: synchronously (i.e., the application continues to run after the changes are written to the database) or asynchronously (the application continues to run while the changes have been written to the database). In addition, the applications work process can perform the changes or you can use a different work process called the update work process. The different update modes existed in ABAP in conjunction with SAP LUWs long before SAP introduced Object Services.

Important!
You need to open the first top-level transaction as soon as possible in an application that changes persistent objects, because a transaction must run before you load or create the first persistent object. Its not enough to open a transaction just before you make the first change to a persistent object. If you access persistent objects when no transaction is running, the Transaction Service works unreliably, even if you open a transaction later. In addition, unnecessary, extra, database read accesses may occur if the system loads a persistent object without having a transaction running and then accesses the object after it starts to run a transaction.

To keep a transaction running all the time, you should close the top-level transaction by calling its end_and_chain() (or undo_and_chain()) method if the application continues to work with persistent objects after you close it. Both methods automatically create and start a new transaction that each of them passes back as its RETURNING parameter, which saves you the trouble of opening a new transaction manually. Compared to working with classical SAP LUWs, you can gain many benefits by using the Transaction Service. You can make changes to objects in a work processs main memory on the application server layer, and the system wont send the changes to the database until the transaction finishes. Subtransactions enable you to revoke a specified set of changes, return to a consistent state, and continue processing after an exception has occurred. You can conveniently implement all of the functionalities described in this article by using object-oriented technology and concepts. With the help of checking agents and events, you can perform other actions in relevant situations. To get maximum benefit from Object Services, you should use both the Persistence Service and the Transaction Service consistently. You

It is advisable that you set the transaction mode and start a transaction immediately after you start an application, before you do anything else. To set the transaction mode, you call the static method init_and_set_modes() in the class cl_os_system. This method has two parameters that you can use to fine-tune the Transaction Service: i_external_commit: This parameter sets the transaction mode to either compatibility mode or

46

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

should also avoid compatibility mode and Open SQL statements that write directly to the database, such as UPDATE, INSERT, MODIFY, and DELETE. The capabilities above are already part of Object Services as currently shipped by SAP and, thus, are available in SAP NetWeaver AS ABAP. In each system that multiple users employ, its indispensable to have a means of managing concurrent write accesses to the same object. Its common to have hundreds of users working at the same time, particularly in SAP systems; its very rare to find SAP systems with only one user. Now, lets look at the integration of concurrency control mechanisms with ABAPs Object Services.

interfaces that Object Services provide to implement a generic service usable in any number of classes and applications without adaptation. For our solution, we didnt have to develop a new lock concept from scratch; instead, we based our solution on the SAP Lock Concept, which we integrated into the existing functionalities of Object Services. When using our lock service, an application doesnt have to deal with locks explicitly in any way (e.g., by setting locks or checking their existence). The application uses Object Services in exactly the same way it would without the lock service. The SAP Lock Concept was originally designed to implement pessimistic locking. For example, if an application is about to change data with pessimistic locking, it sets an exclusive lock before it loads that data from the database. Then, after the application writes those changes to the database, it releases the exclusive lock. When a work process locks an object exclusively, other work processes cannot set a lock of any kind for the same object. This ensures that only one work process can modify an object at a time. Figure 10 on the next page illustrates this approach. In this example, two sessions of an application are about to modify the same object. Before a session starts to work with the object, it tries to set an exclusive lock. In this case, Aldos session comes first and successfully sets the lock. It modifies the object and writes it to the database, while it still holds an exclusive lock. Christians session asks for the lock when the object is already locked. Therefore, Christians request is denied, and he is not allowed to begin modifying the object. SAP added another lock mode to the SAP Lock Concept to support optimistic locking, in which you set an optimistic lock for each object before loading it from the database. Multiple work processes can hold optimistic locks for the same object at the same time. If you make changes to an object, you have to convert the lock from an optimistic lock to an exclusive lock before you write the changes to the database. A successful request to convert an optimistic lock to an exclusive lock causes all other work processes to lose any optimistic locks for the same object. The conversion to an exclusive lock is only possible if the work

Integrating the SAP Lock Concept


To ensure that the system remains in a consistent state when many users work on it, SAP NetWeaver AS ABAP offers the SAP Lock Concept. The SAP Lock Concept is based on classical function modules that you can call to set locks in different modes. Every SAP NetWeaver AS ABAP comes with an Enqueue Server that manages all the locks set through the SAP Lock Concept. However, setting a lock doesnt ensure that concurrent write accesses will never happen. You have to implement the SAP Lock Concept in every concurrent process to enable the mechanism to work. Therefore, its important for every application in the system that changes data to use the SAP Lock Concept. In a complex system consisting of many applications, its quite labor-intensive and error-prone to manually implement the integration of the SAP Lock Concept in each application. When IOT GmbH began using Object Services, we hoped that they would incorporate locks automatically and transparently. That way, we would have been spared dealing with all of the details of implementing a concurrency control mechanism. At first, we were disappointed to find that Object Services dont come with a mechanism to synchronize concurrent write accesses. Fortunately, you can use the

No portion of this publication may be reproduced without written consent.

47

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Aldos Session

Enqueue Server

Christians Session

Set exclusive lock success

Set exclusive lock failure

Modify object

Error-handling or retry

Write changes to database

Figure 10

UML sequence diagram of pessimistic locking

process trying to convert the lock still holds the corresponding optimistic lock. For instance, two sessions of an application can set an optimistic lock and start to modify the same object simultaneously. Before they write their changes to the database, however, both sessions try to convert their optimistic lock to an exclusive lock. Only the first session to ask for the conversion will be successful. In the example in Figure 11, Christians session successfully converts its optimistic lock to an exclusive lock, which causes Aldos session to lose its optimistic lock. Thus, Aldos session cant convert its lock later. Christians session can continue by writing the changes it made to the database, whereas Aldos session has to do some kind of error-handling (e.g.,

discarding the changes, telling the user about the error, or starting again). You should only set optimistic locks in applications that can change objects. You shouldnt set optimistic locks in applications that dont allow changes to the objects, especially if those applications display a multitude of objects. This approach helps to prevent setting a lot of locks unnecessarily. Setting optimistic locks unnecessarily without converting them to exclusive locks doesnt restrict parallel work directly, but the Enqueue Server can only handle a certain number of locks simultaneously. If required, your SAP system administrator can increase that number by changing the systems profile parameter enque/table_size (the default value is 4096KB).

48

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Aldos Session

Enqueue Server

Christians Session

Set optimistic lock

Modify object Set optimistic lock

Modify object

Convert optimistic into exclusive lock success

Convert optimistic into exclusive lock failure

Write changes to database

Discarding changes, error-handling or retry

Figure 11

UML sequence diagram of optimistic locking

With pessimistic locking, a collision of locks is part of the expected program flow; with optimistic locking, however, it is an exception. When you use optimistic locks, a collision can only occur in one place at the end of the transaction. Therefore, you can handle the collision at one central position by implementing exception-handling. With pessimistic locks, whenever you set a lock, you have to deal with the possibility that another work process might already hold an exclusive lock. Thus, a transaction may have to implement appropriate exceptionhandling for the collision in more than one place. Pessimistic locking and optimistic locking coexist legitimately; the type of application youre developing

determines which technique you should use. You should always choose optimistic locking if youre loading many objects and youre unclear about whether the application will modify or display them. This is often the case in interactive applications. Many modern business applications dont just open one object for modification; rather, they display a large number of objects and let the user choose which objects to change. Locking all objects exclusively when the system changes very few, if any, of them severely restricts parallel work. Optimistic locking also prevents you from setting exclusive locks for an unnecessarily long time as exclusive locks are only set while the system writes the changes to the database. In contrast, with pessimistic locking the application

No portion of this publication may be reproduced without written consent.

49

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

How to choose between pessimistic and optimistic locking


You should use pessimistic locks in your application if Your application runs in the background Users must put a lot of effort into entering data before they can save it Your application shows many objects, but typically changes few or none of them You dont know which objects will change when you load them from the database Many users work with the same objects and you dont want one user to lock an object for an unnecessarily long time

Optimistic locking is more appropriate if

Its possible that scenarios exist in which both pessimistic and optimistic locking could lead to a convenient solution; there may also be scenarios in which you have to choose between the two when neither is exactly what you want.

already holds the exclusive locks while it waits for the user to enter data. The worst case of pessimistic locking occurs when a user decides to take a lunch break while working with a change dialog and no one else can work with the objects displayed until the user returns from his break. You can avoid these situations by using optimistic locking. If its already clear when you load an object that it will change and the transaction will finish promptly, you should use pessimistic locking. This is usually the case for background processing. Different applications can work with the same objects by using either pessimistic or optimistic locking. Even if some applications use the SAP Lock Concept optimistically while others use it pessimistically, the SAP Lock Concept still provides protection from inconsistencies caused by concurrency. (For more information about when to use optimistic locking and when to use pessimistic locking, see the sidebar on this page.) In a large information system, it is both more efficient and less error-prone to implement locking in a central component instead of putting the locks manually into every single application in the system. The approach we used at IOT GmbH allowed us to auto-

mate locking. Most of our applications dont have to consider locking directly, although they make changes to persistent objects. To implement optimistic locking in an automated way, we extended the method that the Persistence Service created to instantiate objects to set an optimistic lock before the method loads the object from the database. If you set the lock after you load the object, another process could change the object in the meantime. We also had to be careful not to set an optimistic lock if the application had previously loaded the object, because the Persistence Service would return the reference to an existing instance without loading the object again from the database. In addition, an optimistic lock is automatically set when an application creates a new persistent object. To convert optimistic locks to exclusive ones, we used the checking agents, which we implemented in the persistent classes. Whenever an application modifies a persistent object, it registers the object for the running transaction as a checking agent. Within the scope of every persistent objects consistency check, we try to convert the optimistic lock to an exclusive one when the transaction is about to finish. If the

50

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

Use ABAPs Object Services to build object-oriented enterprise applications and divide database access from application logic Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

checking agent cannot convert the lock, the consistency check fails, leading to an exception thrown by the Transaction Service. The application only has to handle the exception that occurs when it tries to finish the transaction. The whole process of setting and converting optimistic locks runs automatically without any direct involvement from our applications. In background processes with pessimistic locking, you must set each exclusive lock before you load the corresponding object from the database. We set exclusive locks as soon as possible and one after another for all objects that would change within the scope of the current transaction. That way, we created a place where we could implement all lock-specific errorhandling for applications with pessimistic locking, too. However, its more complicated to implement pessimistic locking than optimistic locking, because you need to know in advance which persistent objects will change. In pessimistic locking, we havent yet completely automated lock setting; the application still has the sole responsibility for setting exclusive locks.

development steps, the system benefits from the robustness that ABAPs mature Object Services bring. Figure 12 on the next page summarizes the influence of Object Services on the software development process at IOT GmbH. The amount of effort needed for the whole software development process is less when you use Object Services. The application structure that Object Services suggest simplifies software design. The code can rely on the Persistence Service to load objects from and save objects to the database. Object Services save the effort required to implement the load and save functions manually. Finally, you need less effort to maintain the software, because software based on Object Services is more robust and is structured better than software that manually implements what Object Services provide.

Conclusion
There are many advantages to using Object Services when developing software in ABAP. In conjunction with Object Services, SAP NetWeaver AS ABAP becomes one of the most powerful platforms for modern, object-oriented software development. After having benefited from Object Services under real-world conditions for years, we at IOT GmbH think that Object Services make your applications more robust and their structure more homogenous and intuitive. You need the functionalities of Object Services to develop any kind of system. In addition to its many possibilities for customization to meet specific requirements, you can also extend Object Services systematically. Compared to customer development or third-party libraries offering similar functionalities, using ABAPs Object Services leads to faster software development. While others rack their brains about which persistence service to use, SAP NetWeaver AS ABAP comes equipped with its own, powerful, readyto-use Persistence Service. In subsequent software

The benefits gained by using Object Services increase with the size of the software product developed. While you shouldnt necessarily use Object Services for simple SAP R/3 enhancements, you should use it consistently for customer development of more complex modules and entire systems. This rule applies to the development of all kinds of applications, including: services within an enterprise service-oriented architecture (enterprise SOA) environment; applications with UIs based on Web Dynpro ABAP, SAP GUI, or SAP Business Server Pages; and applications for background processing. The following questions about Object Services remain unanswered: Why do many companies not use Object Services to develop software? Even when companies are developing new systems in ABAP from scratch, either they dont use ABAPs object-oriented features or they develop custom persistency layers instead. Could the inhibition threshold for using ABAP Objects be lowered further by adding a fully integrated lock service to Object Services? We think it would enable software developers to use ABAP Objects and Object Services more frequently.

No portion of this publication may be reproduced without written consent.

51

SAP Professional Journal November/December 2008 Reproduction or distribution in any form is strictly prohibited without the permission of the publisher, Wellesley Information Services.

Additional effort for the software development process without Object Services

Effort

Effort for the software development process with consistent use of Object Services

Specification

Design

Coding

Testing

Maintenance

Figure 12

The effect of Object Services on the software development process

We hope this article has given you some idea of the power of Object Services and how you can use them in your system.
Christian Assig studied Computer Science at the University of Applied Sciences in Gelsenkirchen, Germany, and at the University of Western Australia in Perth. Since 2004, he has developed object-oriented frameworks in ABAP Objects for IOT GmbH. He contributes to the enterprise-wide establishment of object-oriented models and language constructs in the development of information systems in ABAP. You may reach him at assig@iot-online.de. Aldo Hermann Fobbe studied Computer Science at the University of Applied Sciences in Gelsenkirchen, Germany. He has been working for IOT GmbH for the past eight years as the manager of product development and

technology in the SAP NetWeaver environment. He shaped the development of an MES based on ABAP Objects by initiating the use of a service-oriented software architecture based on SAP NetWeaver AS ABAP. You may reach him at fobbe@iot-online.de. Arno Niemietz studied Physics and Mathematics at the University of Mnster, Germany. After receiving his doctorate, he worked in software development for several companies. Since 1987, he has been particularly engaged in business information systems. In 1990, he was appointed professor by the University of Applied Sciences in Gelsenkirchen, Germany. He teaches and researches in the field of business information systems in the Department of Computer Science. In 1998, he founded IOT Institute for Organization and Technology Design GmbH, which develops business solutions based on SAP technology. You may reach him at niemietz@iot-online.de.

52

www.SAPpro.com

2008 SAP Professional Journal. All rights reserved.

You might also like