You are on page 1of 87

HOW TO DEVELOP IN ABAP

How to Develop in ABAP


Applies to:

SAP NetWeaver 7.0. For more information, visit the ABAP homepage.

Summary

This is the PDF version of the development blog series on SDN published in 2007 that gave an introduction
to ABAP newbies who want to learn how to develop simple programs in ABAP.
This PDF file does not contain the few blogs of the original series that explained how to install and
administrate the ABAP demo version and how to import and export programs. This PDF document solely
focuses on the many blogs that focused on development in ABAP. This is why the PDF file starts with blog 3
and has some gaps in the numbering.
The main author of this blogs is Thomas Weiss but some blogs were written by other authors (Manfred Lutz,
Hans Tillinger, Dirk Feeken). For more information read the original blogs.
If you are interested in the comments and answers to the comments on the blogs you should read the
original blogs on SDN. Otherwise this PDF file gives you an easy opportunity to work your way through the
whole series.

Author Bio

Thomas Weiss has a Ph.D. in analytic philosophy. He worked as a professional writer before joining, in 2001,
the SAP NetWeaver product management training team where his responsibilities included the e-Learning
strategy for ABAP. After becoming more involved in writing ABAP material himself, he is now a member of
the SAP NetWeaver Application Server Solution Management. One of his main interests lies in rolling out
ABAP topics both for experts and for beginners by writing blogs in SDN.

1
Table of Contents
WHY AND HOW THE SERVER MATTERS TO YOU AS A DEVELOPER: SERVER ARCHITECTURE AND
WORK PROCESSES .................................................................................................................................. 4
ABAP Application Server for Newbies – Why and How the Server Matters to You as a Developer ....... 4
Developing on the Server .......................................................................................................................... 4
The Three-Layer Architecture ................................................................................................................... 5
Work Processes in Some Detail ................................................................................................................ 5
The Three Layer Architecture Continued.................................................................................................. 7
Summary .................................................................................................................................................... 8
MANY DEVELOPERS ON ONE CENTRAL SERVER - HOW DOES IT WORK? ......................................... 8
Many Developers on One Server – How Does It Work? ........................................................................... 8
Developing on a Central Server – The Way to Keep Your Sources in Sync ............................................ 9
Summary ...................................................................................................................................................10
NAVIGATION IN THE APPLICATION SERVER .........................................................................................10
A FIRST ‘HELLO-WORLD’ PROGRAM .....................................................................................................13
The Repository Browser – The Central Place in the ABAP IDE ..............................................................13
Packages ...................................................................................................................................................14
A Package for Local Objects ....................................................................................................................14
‘Hello World’ as a Local Program .............................................................................................................14
Summary ...................................................................................................................................................18
CREATING A PROGRAM AND A PACKAGE - AN INTRODUCTION TO THE SAP CHANGE AND
TRANSPORT SYSTEM ..............................................................................................................................18
Some Words of Motivation: Why Your Programs Deserve Better than Package $tmp..........................19
Creating a Package - the Chance to Get in Touch With the CTS ............................................................19
Creating a Package - the Details ..............................................................................................................19
The Concept of a Transport Layer ...........................................................................................................21
Some More Basic Concepts of the SAP Change and Transport System ...............................................22
Package Building Continued ....................................................................................................................25
Creating a Program Within a Package .....................................................................................................26
Outlook ......................................................................................................................................................27
A FIRST LITTLE BUSINESS PROGRAM ...................................................................................................28
The Aim: Our First Little Business Program............................................................................................28
How to Use the ABAP Documentation .....................................................................................................28
How to Get an Internal Table with the Line Type of a Database Table ...................................................29
Open SQL in ABAP ...................................................................................................................................30
Test Output of an Internal Table 1: A Loop and a Write-Statement ........................................................30
How to Get to Know the Properties of a Database Table ........................................................................31
What the List Output with the Write Statement Looks like .....................................................................31
Test Output of an Internal Table 2: A Dynamic Way to Output Any Internal Table ................................32
Test Output of an Internal Table 3: The Object Oriented Way ................................................................33
The Whole Code of the Three Alternatives – An Overview .....................................................................34
Summary ...................................................................................................................................................35
GETTING MORE FAMILIAR WITH THE ABAP DICTIONARY ...................................................................35
PARAMETERS and the Selection Screen ................................................................................................36
From the ABAP Dictionary to the Data Browser......................................................................................37
Data Element, Domain, and the Way They Interact .................................................................................39
At Last: The Source of Our Search Help ..................................................................................................40
Summary ...................................................................................................................................................41
DEBUGGING IN ABAP ..............................................................................................................................41
Defining a Custom Structure in a Program..............................................................................................41
A Useful Addition to the SELECT Statement ...........................................................................................42
What Is Wrong With Our Program – We Start to Debug ..........................................................................43
The New ABAP Debugger – A Short Overview ........................................................................................43
Debugging Our Program ..........................................................................................................................44
Some Words on Efficient SQL Programming ..........................................................................................45
How to Use the ABAP Language Documentation Efficiently ..................................................................46
Summary ...................................................................................................................................................48
GET YOUR PROGRAM UP TO SPEED - OVERVIEW & INTRODUCTION ................................................48
The Programs to be Analysed ..................................................................................................................48
ABAP Runtime Analysis: Tool & Procedure ............................................................................................49
THE FOUNDATION OF AN APPLICATION - CREATING THE DATABASE TABLES ...............................53
The Contents of this Blog in Some Detail ................................................................................................54
The Concept of a Client: A Key-Player in the SAP World of Business Programming ...........................55
Defining the Data Elements ......................................................................................................................56
Creating Database Table YACCOUNT ......................................................................................................58
Providing Some More Check Tables ........................................................................................................61
Summary ...................................................................................................................................................62
HOW TO DYNAMICALLY CREATE TEST DATA FOR OUR DATABASE TABLE .....................................63
The Basic Principle of How to Create the Entries Randomly..................................................................63
How to Fill Database Tables in the Data Browser ...................................................................................64
Looking at the Program Itself ...................................................................................................................65
Running the Program ...............................................................................................................................68
Summary ...................................................................................................................................................69
The Complete Program Code ...................................................................................................................69
YOUR FIRST ABAP OBJECTS..................................................................................................................70
STARTING WITH WEB DYNPRO FOR ABAP ...........................................................................................75
Create your first Web Dynpro Component ..............................................................................................75
Model View Controller and the Context ...................................................................................................76
Data in the View ........................................................................................................................................79
Defining the View Layout..........................................................................................................................80
A First Test ................................................................................................................................................82
Bringing Life into the Component ............................................................................................................84
Conclusion ................................................................................................................................................86
WHY AND HOW THE SERVER MATTERS TO YOU AS A DEVELOPER: SERVER ARCHITECTURE AND
WORK PROCESSES

In general, you develop on a central server in ABAP. That is why the server matters to ABAP developers
from the very outset. In this weblog I explain the three layer architecture of the SAP NW Application Server
ABAP and the basics of how users are distributed on work processes. The result of this architecture is a
highly scalable and robust server.

ABAP Application Server for Newbies – Why and How the Server Matters to You as a Developer

Usually as a developer in a language like C or C++ you need not care so much about the server. It might
only matter to you if your program should run on a server in the end. When you are developing in ABAP
things are different in this regard. In this weblog I will explain why the server concerns you from the very
outset and why, consequently, you need to have some knowledge about the SAP NetWeaver Application
Server ABAP. And this is what I want to provide you with in this blog: some basic information on the SAP NW
Application Server ABAP.

Developing on the Server

For those experienced with other programming languages like C, Java, or Visual Basic working with ABAP
offers some features they might not be accustomed to. The structure of the development environment for
ABAP is different from probably everything that you might have encountered so far: In ABAP, you program
on the server from the outset. You do not develop the programs locally on your PC, nor do you store the
sources in a versioning system or deploy the programs on the server at a later stage.

In order to program with ABAP, you therefore require access to and developer authorization for the SAP NW
Application Server ABAP. You write your programs using the ABAP Editor of the ABAP Workbench and the
tools integrated there, which are also part of the server.

However, the SAP NW Application Server ABAP not only contains the programming environment with its
tools and utilities for supporting the software lifecycle. Developing with ABAP is closely connected to the
server in another respect: Once you activate your source code, platform-independent byte code is
generated, which the runtime environment interprets for the program execution. And this byte code
generated from your ABAP program runs on the SAP NW AS ABAP. Usually many developers are working
on the same server.

This way, a problem known to all developers in large projects does not even arise: No quality manager
needs to care about providing a system on which to deploy the programs from different developers and
where to test the interaction of the programs from different developers in a project. Everything to accomplish
this, is already done, and you as a developer already have your programs in the right place: As soon as your
source code is activated the respective development object is visible on the central system. So the principle
in ABAP is: Development on a central server.

You need also not care about checking in and out your sources in a content management system. The whole
persistence and administration of different versions of your sources also happens transparently to the users.
Pushing the Save-button in the ABAP Workbench stores your program in the database. You retrieve it by the
program name: There is no fumbling with program files in ABAP. Again the server does it all for you.
By the way, this is a typical experience when working with the SAP NW AS ABAP: Many things you need for
business programming are provided by the system. The ABAP server does a lot of services for you in the
background that developers or quality manager usually have to care about.

The explanation for these conveniences is the fact that the organization and structure of and the technology
behind the development process in ABAP is different. Some these features need getting used to, but after a
while you will like them because thanks to them you can concentrate on what your job really is about:
developing business logic.
It is for this reason that you must take into account the architecture of the environment in which ABAP
programs run when designing and developing these programs. For this purpose, you first require some
information about this architecture.
The Three-Layer Architecture

The SAP NW Application Server ABAP consists of three layers: presentation, application, and database. The
database layer of a system is made up of a central database with a database management system and the
database tables. It not only contains the user data, but also the entire program code of the SAP NW AS and
application programs, all administrative data, and Customizing settings. The programs you develop are
stored in the database of the system.

The application layer lies between the database layer and the presentation layer. It consists of one or more
application servers (more than 100 servers possible) and a single message server, which is responsible for
communication and load distribution within this layer. The programs that process the business logic of an
application and all the development tools, such as the ABAP Workbench, run in this layer.

Work Processes in Some Detail

Technically, the actual processing takes place in work processes, which represent processes of the
operating system. A fixed database connection is assigned to each work process. For you as a developer
this means: You always have a database connection at hand. No need to get a database manager, to open,
handle and close the database connection. The whole database handling is done for you in the background
by the server.

There is no fixed assignment of users to work processes. A lengthy user session can utilize different work
processes sequentially, and one work process is used by different users consecutively. Still the state of your
program is kept. The context of your work process is rolled in as soon as your program is processed and
once the work process returns a result, your context is rolled out. It is this so-called roll area that contains all
the data and programs that are currently processed by a user.

This architecture makes for robustness and scalability. It is robust because every user has a work process of
his own, for the time his program is processed. All that can happen in the worst case only concerns the work
process your program currently occupies. There is no such thing like crashing the whole engine in ABAP by
a severe syntax error in your program.

The way user requests are distributed to work processes combines the advantages of stateful and stateless
communication. On the one hand, a user does not occupy a process for a long period while he might not be
doing anything. On the other hand, the Dispatcher (within the server) knows and remembers the identity of a
user over time: This way each time a user session gets processed its context is known.

To give you a better understanding of this mechanism I will present you an example of how a user of a
particular application is assigned to different work processes at different points in time when performing
different steps in an application. To avoid one possible misunderstanding from the outset: In general, one
request is processed within a single work process though it is possible to write programs in ABAP that
distribute different costly tasks on several work processes (such as, for example, several large selects on the
database if they do not depend on each other).

Let us suppose a loan officer, let us call him Jones works with an application in the office: First retrieves the
table of debtors in a particular region. His request is processed by work process 1 (picture 1). But, of course,
he might get any other work process that is currently free.
If the request is processed the result is sent back to the user. The roll area that keeps the state and data of
user 1 is rolled out and the work process is freed for requests of other users (picture 2). As long as user
Jones does not interact with the application he does not occupy any work process. By the way, the other
users in our pictures are assigned to other free work processes in the same way as user Jones is. But this is
not shown in the picture, as I want to keep the focus on the way user Jones is assigned to work processes.

Next our loan officers want to get the details of a particular customer. He gets assigned to work process 3
and his roll area in the state he has left it is rolled into this work process (if there is not much traffic on a
server, you will in general stay into the same work process, because the server tries to minimize the cost for
rolling-in and –out, but this are optimization details, and I am interested here in the general mechanism).

Again the work process is freed after the request is processed (picture 2).

Next the loan officer sets a new credit limit for Smith and saves it. Again he gets another work process. His
roll area is rolled in, the request is processed and the data is saved on the database.
This way a user does only occupy a work process when the application he uses actually sends a request.
Due to this mechanism it is possible to have far more users than work processes on an AS ABAP. So a
typical SAP ERP System running on an AS ABAP server might have 50 work processes and 500 users
currently logged on (This is, of course, only an example to show the ratio, the actual number of work
processes on a server depends on many technical details such as the CPU power of the servers, the RAM
that is available, what kind of applications the users typically are running, how many users are logged on
simultaneously etc.. The number of work processes for a system is determined in the profile by the system
administrator).

The Three Layer Architecture Continued

The kernel and the Basis services make up the part of the application layer that is specific to both the
operating system and the database. They are responsible for user and process management, database
access, communication with other systems, as well as system monitoring and administration. The software
processes or virtual machines, that interpret the platform-independent byte code as operating system-
specific machine language commands, run in the kernel.

The presentation layer represents the interface with the user and is responsible for the screen display. This
layer receives user entries – that is, mouse-clicks and keyboard input – and passes them on to the
application layer. Furthermore, it receives data from the application layer and displays it to the user.
When writing a business application you should use Web Dynpro ABAP as a state-of-the-art user interface.
A Web Dynpro ABAP component may run on the same server as the underlying business logic. An ABAP
Web Dynpro application is displayed in the Browser or the Business Client.

The ABAP workbench and all the other tools you need for developing use the Dynpro technology (Dynpros
are the classical user interfaces of most ABAP-based SAP programs and run in the SAP GUI). In our demo
programs in this series, we will sometimes use classical Dynpros to input and output data as a handy device
just as you use the output to the console in Java Tutorial. It saves you time if you want to test a backend
program and the real user interface written in Web Dynpro ABAP is not yet available or you want to test the
business logic apart from the presentation logic. The real user interface of your programs should always be
developed with Web Dynpro ABAP.
The purpose of this division in three layers is high performance and scalability. The layer division is purely
logical. It does not imply over how many machines the system is distributed. In fact, all three layers can
actually run on a single computer. For demonstration purposes, such as you have just done it in the case of
this demo system, it is possible to install all three layers on a single PC. However, in the case of large,
production applications of customers, this is more of a theoretical possibility, since it would counteract the
scalability of the three-level architecture.

Summary

Now you should have understood that you always work on the server when developing in ABAP. It is for this
reason that I have explained to you the basics of the three-level architecture of the server and the way users
are assigned to work processes. In the next blog I will explain the impact of development on a central server
on the developing process. Again I will focus on an example that is intended to illustrate a basic mechanism.
This time you will lean some details about what happens when you activate your program.

MANY DEVELOPERS ON ONE CENTRAL SERVER - HOW DOES IT WORK?

In this blog I show you one big advantage of central development in an example: You will always use the
latest sources as soon as they are activated instead of developing against proprietary source versions that
you have on your PC and not updated for weeks. This is ensured by the technology underlying the
development process in ABAP. A simple example illustrate how this works.

Many Developers on One Server – How Does It Work?

In the last blog I have explained some basics about the ABAP server: Let us now combine what I have
explained about the three-layer architecture of the server and the fact that developers always develop on the
central ABAP server in real-world projects. As in the last blog I will provide a little example to illustrate what
happens when you activate your program.

As I have told you, there are many developers developing on the same server. Each developer has his own
“instance” of the development environment on the server within his roll area. You can compare this to many
clients working with different instances of a class.

Technically the development environment comprises a set of programs such as the ABAP Editor, the ABAP
Workbench or the Class Builder plus a lot of other tools to support the development process. An ABAP
developer works on the client and has the classical SAP GUI that presents the user interface of the
respective development tools. The programs under development are stored on the central database.
The program a developer writes within development client 1 is only visible to this developer as long as the
program is not activated.
As soon as the developer activates a program it is visible on the whole server. This means, of course, that
other programs can access it.

Developing on a Central Server – The Way to Keep Your Sources in Sync

One great advantage of this organization lies in the fact that incompatibilities will become visible very early.
Let us refine our small sketch a bit to show you how this works in detail: Let us assume that program 1 uses
class 3 (developed by development client 3). Remember: It is the active version of class 3 that is used.
Inactive versions are not visible to other users (in fact they are not visible to any other development objects).
Meanwhile there is a new inactive version of class 3 under development.

As developer 3 is not very experienced he changes the interface of the method that is called by program 1.
Let us assume he renames the parameters of the method. Unaware of the consequences of this
incompatible change developer 3 activates his class. What happens? The old inactive version becomes the
new active one and … there is a syntax error as soon as program 1 (the client of class 3) is recompiled:
So you see: As I have already explained, there is no need to maintain a dedicated test system if the
developers belonging to a project develop on the same server. So one typical problem of local development
does not occur when you develop in ABAP. Instead of developing against proprietary source versions that
you have on your PC and not updated for weeks, you will always use the latest sources as soon as they are
activated. This way, incompatibilities will be realized in a very early state.

Summary

I hope, by now you have understood what is so good about many developers working on one central system.
Once you activate your program it is visible to everybody else on the system, and possible conflicts are
detected in a very early state.

NAVIGATION IN THE APPLICATION SERVER

In Part 2 of this blog series, you logged onto the Application Server as 'BCUSER'. From this starting point,
this blog explains how to find the functionality you need.

Item No.1 is a Command field for the 'Transaction Code'. This is a shortcut to the transaction (functionality)
you want to execute. Position the cursor in the field and press 'F1' to display the documentation.

This is a general feature of the Application Server for online help on input fields.
In Part 2 of this blog series you were asked to enter 'SE80' in this Command field, which takes you directly to
the ABAP workbench. This works only in the logon screen, in all other screens you have to add '/' as the first
character and a letter as described in the documentation. For example, if you add an 'o' (as in 'other') before
the Transaction Code, a new window will be opened for that transaction.

To the right of the Command field, there is an icon to display a history of commands used. Just click the icon
and a pull down menu appears with all the transaction codes you entered so far.

Item No.2 are two buttons in the toolbar. The left button opens a new window, which is the same as '/o' in the
Command field. The right button is for creating a shortcut on your desktop that will start the transaction you
are currently in. You also can create a shortcut to any other transaction.

Item No. 3 is a folder for your favorite transactions. Since it is not easy to remember all the transaction codes
you can collect the ones you'd like to use more often in that folder. To make it more convenient for you, the
folder displays the title of the transaction instead of the transaction code. Click the folder icon to open the
context menu. 'Insert transaction' adds a new item to your favorites. You can do the same thing by clicking
'Favorites' in the menu bar.

If you are in a screen and you don't know the transaction code, just click the 'System' button in the menu bar
and select 'Status'. A new dialog box will appear.

This dialog box shows all the system information for your session. The transaction code used in the
Favorites folder can be found under 'Transaction'.

One useful hint: In the Favorites folder and in the SAP Menu you can display the transaction code in the
beginning of each line (see screenshot below). For that, click on 'Extras' in the menu bar and select 'Settings'
and check for 'Display technical names'.

Item No. 4 is a navigation tree to the different transactions. Just open up the SAP menu, click 'Tools', open
the 'ABAP Workbench' folder, open 'Overview' folder, and then you'll find the 'Object Navigator' item.
Double-click that item, and the 'SE80' transaction is started.

Since the ABAP Trial Version is only the Application Server, there are no business-oriented transactions in
the navigation tree.

There are three buttons in the middle of the toolbar, all for navigation purposes. They are highlighted when
active.

The green button is the 'Back' button, which goes back to the previous screen.

The yellow button is the 'Exit' button that interrupts the transaction and takes you straight back to the entry
screen.

The red button is the 'Cancel' button that stops the transaction, but will not always return you to the entry
screen.

To close the session, just enter '/nex' in the Command field and press 'Enter' or the green 'OK' icon to the left
of the toolbar. All open sessions will then be terminated without any dialog.
A FIRST ‘HELLO-WORLD’ PROGRAM

After you have learned how to get the ABAP Object Navigator (transaction SE80) in the last blog it is now
time to do it. And we will do it here and now in this blog. We will write a "Hello World" program.

Again, you will recognize a principle that I have explained in my blogs on the server. The ABAP development
environment offers you a lot of benefits for free that take quite some extra work when developing in other
languages. When developing in ABAP, your program becomes part of a large mechanism that helps to
manage and organize development objects in a system landscape from the very outset. Let my elucidate this
by an analogy. Creating a development object with C or Java is in a way like writing a text with a word
processor: You write it, save it where you want and that's it. In contrast, developing a program in ABAP is
like writing a text with a content management system where you are forced to create a document as part of a
larger context with a number of default attributes, which help to pigeonhole your document within this
system.

The main structure is pretty simple: Every development object in ABAP belongs to a package. In general,
every package has a property that determines to which other systems the package plus its content is
transported if the package plus its elements are assigned to a transport request. The only exception to this
rule is the package $tmp which is made for local developments. The content of this package is not
transported to any other systems. In this blog we will create a program in this package for local
developments, while in a later blog we will create a package that we will use as a container for all elements
we will create in other blogs.

The Repository Browser – The Central Place in the ABAP IDE

First we navigate to the transaction SE80 and have a short look at what we see there:

The Object Navigator is the development environment for the central editing of all development objects. We
call these objects repository objects. This includes all ABAP programs of AS ABAP and all their components.
However, there are many other repository objects, such as global data definitions in the ABAP Dictionary,
global classes, or XSLT programs. Together, these development objects in the ABAP Workbench form a so-
called repository. This repository is a special part of central database, which, instead of customer data,
comprises the programs of AS ABAP itself.

The buttons in the upper part of the navigation area allow the selection of a browser. You can configure in
Utilities - Settings which browsers are presented for selection with buttons. The browser we will generally be
using is the Repository Browser (1). It is the default setting of the Object Navigator and also the most
generic browser, which provides an overview of all important repository objects sorted by different criteria.
You access the repository objects through the Repository Browser by using so-called object lists. You must
select such an object list in the dropdown list box, which is displayed in the navigation area under the
buttons. In our screenshot you see the local objects (2) of user bcuser. As we have not created any local
objects by now, the area that shows these local objects is still empty (3). By choosing another entry in the
dropdown list you can see other objects such as package, programs, function groups etc.

Packages

As already mentioned above, every development object must belong to a package. Packages organize
development objects and handle their connection to the AS ABAP software logistics. That is a package is like
a folder in a way. As for the software logistics, in ABAP your objects have to be assigned to a specific
"software transport track" and a particular transport request. As soon as you release the relevant transport
request, your object will be transported to the next system on that track. I will explain in another blog more
technical terms what these tracks and transport requests look like in detail.

You can view a package plus all its elements also in the SE80. Just choose the entry Package in the object
list of the Repository Browser, enter the name of the relevant package in the input field below and press
"Enter". Then all the objects of that package are displayed.

A Package for Local Objects

We will make do with the default package for local development for our first program. In this case we do not
need to create a package and need no transport request. As already told, every AS ABAP contains a
predefined package named $TMP, in which you can create local practice and test programs, that need not
be transported to other systems. Each user has a local package of his own in a system. If the SE80 does not
already show the space for your local objects, select "Local Objects" in the Repository Browser, enter
"BCUSER" in the input field under the dropdown list box, and press "Enter". As result the Repository Browser
displays all the development objects in this special package, which were created under your user name.

‘Hello World’ as a Local Program

To create a local program we select "Program" in the Repository Browser and enter the name
z_hello_word_local in the input field below and press "Enter" or select the glasses icon.

Here you see a very helpful feature of the ABAP development environment. If you want to edit an object that
does not exist, in general the system asks you if you want to create the respective object. We confirm and
get to the next dialogue window.

By the way, you should note and always remember as from now that repository objects created for
customers in customer systems have different naming conventions than those that apply to Sap's own
programs: A customer must use "Y" or "Z" for the first letter, or the abbreviations reserved by SAP for
the customer’s company. Our Trial Version is set up as a customer system in which the user BCUSER is
registered as a customer. Therefore the names of the objects we create must start with a "y" or "z".

In the next dialog window we deselect the item "Create with TOP Include", confirm, and get to the next dialog
window.
In here you can define the properties of the new program. This is important, since the program properties
determine the execution of the program in the ABAP runtime environment. One of the most important
program properties of an ABAP program is its type. From the list provided, we want to select the type
"Executable program" for our simple Hello-World- program, and change or add no other properties. In
particular, ensure that the properties "Unicode checks active" and "Fixed point arithmetic" should always be
checked.

In the next dialog window we select "Local Object" and, thus, do not need to input a package name. And
there we are. Now we have done everything we need to input the code of our first program.

Note that in our blogs we will be using the new frontend editor available as of SAP NetWeaver 2004s, which
like all modern editors supports syntax highlighting and so on. To configure this editor, select Utilities -
Settings - Frontend Editor (new). To configure the editor for your own preferences, you can select the icon in
the lower right-hand corner. Up to and including Release 6.40 (SAP NetWeaver 04), you will still need to use
the old frontend, which provides a lot less support for programming.

To go on, we double-click the program name in the object list of the SE80.

On the right the editor opens. In it you see the framework predefined by the ABAP Workbench. This syntax
consists of a few lines of comments, and also contains an initial statement named Report.

*&----------------------------------------------------*
*& Report Z_CREATE_EXAMPLE_DATA *
*& *
*&----------------------------------------------------*
*& *
*& *
*&----------------------------------------------------*
REPORT Z_CREATE_EXAMPLE_DATA.
The first seven lines are comment lines, and the eighth line is a statement.

Comment lines are introduced by an asterisk * in the first position. The rest of the line is arbitrary and is
shown in a different color by the editor. To mark only the final portion of a line as a comment, you can use
the character ".

As we want to input some code, we have to change the program. In order to do this we have to go to the
change mode by pressing the respective button:

Below the report-statement we enter:

REPORT Z_HELLO_WORLD_LOCAL.

data output_text type string.


output_text = 'Hello World'.

write output_text. "obsolete statement

Admittedly, this listing needs some beautifying. The tool to do this is the Pretty printer. We configure the
Pretty Printer at Utilities-Settings-ABAP Editor-Pretty Printer and select Convert Uppercase/Lowercase and
below Keyword Uppercase. Next we press the Button Pretty Printer and our program now looks a bit nicer as
all the keywords are now in capitals.
To run the program we press the icon:

Now let us spend some words on the syntax of this little program. Though this program is as simple as it
could be, I still want to add some comments on the general way ABAP programs are structured.

Every standalone ABAP program, that is, all types of programs except for so-called include programs, start
with an introductory statement. In our first program, the introductory statement is REPORT. This designation
is historical and expresses the fact that an executable program was once exclusively used for reporting.
Here, however, it suffices to know that our first statement introduces the program z_hello_world_local.

After the introductory statement, every ABAP program follows a fixed program structure that divides it into
two parts:

 a global declaration part

 a procedural part

In the global declaration part, which directly follows the introductory statement, declarative statements can be
used for definitions and declarations, which will be visible and applicable throughout the entire ABAP
program. Examples of objects that can be declared or defined here are data types, classes, and data
objects. For larger programs, these declarations are generally made in a special include program, the "top
include," which is supported by the ABAP Workbench and inserted at this position. After the global
declaration part comes the implementation part, in which the actual processing logic of the ABAP program is
implemented.
The keywords and statements used in this program do not need many explanations. We declare a field of
type string, assign a value to, and output it.

Note some important information on the write-statement. The write statement outputs a list and it is driven by
the classic SAP Dynpro technology which should not be used to write applications with a state-of-the-art user
interface. You should use Dynpro-based UIs only in test-programs if you want to output (or input) some
values in a quick and dirty way.

You can compare the write-statement to the output to the console in Java. Just the same way you should not
use the write-statement to output something in an application proper. The right way to do this is to use a Web
Dynpro ABAP application as a user interface and to encapsulate all the logic of your programs in function
modules or classes. Still, we will use the write-statement sometimes in our blog series in order to output
some results or to input some values a program needs. And this is the way, you should use this classic, but
by now obsolete UI technology yourself: Use it (only) to test your business logic separately from the
presentation logic.

In order to show you, how the syntax check works in ABAP, let us change the Keyword DATA to DTA and
press the Check Icon.

At the bottom of the editor we get the information:

This check gives you precise information as to in which line the error is. In case of a slip of pen like this, the
system can make a reasonable guess as to what you wanted to type in, and proposes a semi-automatic
correction.

Next we save our program by pressing the Save button:

The real storage of the program in the database is done by the system. You need not worry about it. All you
need to retrieve the program is the name. So there is no fumbling with files on the Web AS ABAP.

If you remember the blog about the activation of programs, you probably know that this program is still not
visible to other users. Why? There is no active version of this program. A version of a program that is not
activated is only visible to the developer of this program.

In order to make our program visible in the whole system, we activate it by pressing the Activate button:
Now our program is visible to every user in the system.

Summary

Now you have learned all you need to develop a simple program in ABAP.

 You know that you need a package for every development object. If your object does not need to be
transported to another system the package $tmp for local development will do.

 You have seen how to find your way in the Repository browser of the SE80 and how easy you can
create a new program. Just input the name of a new object and the system asks you if you want to
create it.

 You are able to save, activate, run, or check a program for syntactical correctness

In other words, now you know the basics, and we can go on with something more complex in the next blog.

Special thanks to Horst Keller and the Galileo Press. By courtesy of the author and the publishing house
I could reuse some explanations of ABAP concepts from the lately published book: ABAP Objects. ABAP-
Programming in SAP NetWeaver in this blog. And I will also do this in the following blogs of this series, as it
is faster sometimes to reuse an explanation of some ABAB basics to some extent if it fits in the structure of
the blog.
In case, you want to know anything about ABAP in more detail than we can present here in our blog series,
just consult the book. On 950 pages it covers, I feel temped to say, almost every conceivable detail of the
ABAP language.

CREATING A PROGRAM AND A PACKAGE - AN INTRODUCTION TO THE SAP CHANGE AND


TRANSPORT SYSTEM

This blog is about how to create a transportable package, how to create a program within this package, and
how to get the connection to the integrated software logistics of the server, the SAP Change and Transport
System (CTS) right from the beginning. Doing this you will get a grasp of what a multi layer system
landscape for development is for and what the concepts of a transport layer and a transport requests mean
in this context. This will provide you with a basic understanding of the complex world of software logistics in
the ABAP world.

Unfortunately, I must confess it, you need a lot of dialog windows to define the relevant properties of a
package and a program. And clicking through these windows is a bit of a bore. No kidding. And the worst is:
It will take so much time to show you what attributes the package and the program need and to explain why
they need these attributes with which value that I have decided to postpone any program code to the next
blog.

But still I believe that you need the information I present in this blog. And I will try to make the long walk
through many dialog windows more interesting by adding some more basic information to the CTS. But do
not expect too much from it. The world of SAP CTS is complex, and I can only scratch its surface. But let me
first spend some thoughts on why we are not content with our demo programs in the package $tmp for local
developments.
Some Words of Motivation: Why Your Programs Deserve Better than Package $tmp

Development is not only about devising cool patterns, algorithms and coming up with a hip design. This is
the bright side of developing. What I show in this blog is, in a way, the monotonous housekeeping of the
developer. It is not cool, but it has to be done, if you will not end up in a mess with your cool programs. And
you will get rewarded for it. By assigning your development objects to a package and a transport request with
the right properties, you will keep your developments tidy, from the very outset.

This proper structuring of development objects becomes particularly important if you work in a team on a
development project. When just developing on your own at home, this assignment of your objects to the
software logistics is not strictly necessary and means some overhead expense for you. Nevertheless, you
might also profit from it when just working on your own. To return to our analogy of housekeeping: Avoiding
producing a mess is more important if you share an apartment, but it is not wrong if you live on your own
either. The same applies in analogy to developing on your own with our demo version at home. There is only
one default package $tmp for local development for each user. And you need more packages to manage a
lot of different developments. Just imagine you had all files on you PC in one folder. In the same way, it does
no good to have all your development objects in your package $tmp.

But there is an even more compelling reason to use a transportable package as a container for your
programs right from the beginning: You cannot even export local objects to a file. (In fact this unconditionally
true only for objects in package $tmp. They can never be transported. Objects in a local package can be
transported in a special type of transport request: a request for the transport of copies. But this type of
request can only be created in the Transport Organizer, SE09 and not from the dialog windows provided by
the ABAP Editor in the SE80. As I do not want to introduce the SE09 in this blog we have to make do with a
normal transportable package).

As ABAP development objects are stored in the database of the system you cannot just copy a program file
if you need it elsewhere. You need to export it to transport files first, and then you can import these files into
any other application server ABAP if you have access to the file system of the underlying physical server.
This is the motivation and an explanation as to why even solitary developers at home should not be content
with developing in package $tmp. Your programs deserve better. They should live in a transportable
package.

Creating a Package - the Chance to Get in Touch With the CTS

This walk through a lot of dialog windows, cumbersome as it is, might still be interesting to those who have
some experience in handling these things. In a way, this cascade of dialog windows resembles a wizard
driven activity. You may get along in these windows, and still not really know what you are doing. This is the
way I got through some wizards. I was happy to be out of it, and hoped that I had fed the wizard the info it
needs and that the wizard would not take revenge on me: Maybe due to my limited knowledge I had
provided some syntactically correct data that nevertheless did not lead to a semantically meaningful
outcome.

Since the input in these dialog windows connects your development objects to the SAP Change and
Transport System and this powerful system is really complex, the odds are good that you do not really know
what you are doing there, though you get along quite successfully in these windows. In any case, if you are
one of those you will probably profit from this blog.

Creating a Package - the Details

By creating a package we are laying a cornerstone for all subsequent developments in later blogs, as we will
use it throughout all parts of our little demo application. Moreover you learn the little steps you have to take
before you can start typing in the code, whenever you need a new development object. After this blog we will
simply presuppose that you know how to perform these steps, and if we create other development objects
such as a global class, a function group and a function module, a database table or a data element in the
ABAP Dictionary, we will only explain what is different from the procedure explained in this blog.
As packages themselves are also repository objects, which can be edited using the ABAP Workbench, we
use this tool to create our package. To do this, we select the package object list in the Repository Browser,
and enter the name y_abap_demo into the input field below.

Again you see this very helpful feature of the ABAP development environment: If you want to edit an object
that does not exist, in general the system asks you if you want to create the respective object. We confirm
and get a dialogue window:

In addition to a short description you must specify the Application Component, the Software Component, and
the Transport Layer. In order to input the software component, we select suitable entries from the selection
list, which is displayed after pressing the input help key (F4). As already mentioned, this value help is an
important and extremely helpful feature, and you find it throughout the SAP AS ABAP and all ABAP-based
applications if their developer has provided it. So let me show you in the next figure how this value help
works. You select the field with the label Software Component, enter (F4) and you get the value help if it is
provided:
In our case the values you see are created by the system administration when the system was set up: It is a
list of the software components that are available in the system. The software component HOME is meant by
SAP for customer development and equipped with all the tools available for this. We select it and confirm by
selecting the check mark (1). In case a list in a value help is very long, select the telescope icon (2) and start
a search.

The Concept of a Transport Layer

The transport layer is an important concept. It refers to the transport path a package should take in a system
landscape. The usual landscape has a least three layers:

The basic idea behind this layered system structure is simple: You develop an object in the development
system and test it in the consolidation system. When all tests are successful you transport your tested
development objects to the productive system. The SAP CTS enables you to define this path as an attribute
of a package. Due to this feature there is no fiddling about with the destinations of development objects. You
just define them in the properties of the respective package in the beginning.

How useful the concept of a transport layer is, becomes in particular evident if you have, for example, one
development system for different productive systems.
In the landscape shown in this figure it makes sense to define two transport layers, one for a path from the
development system over consolidation system 1 to productive system 1 and the other layer that leads from
the same development system to consolidation system 2 and productive system 2.

Due to this organizational structure development objects destined for productive System1 are from the very
outset in a different pigeonhole than those for productive System 2.

The arrows in these figures only show the direction and the destination of the relevant transports. The
transport layer by itself does not transport anything. You need a transport request to get something
transported. Maybe an analogy can help to expose the way the concepts of a package, a transport layer, its
respective destination system, and the export from and import into a system are interrelated:

The transport layer is like a subway line and the transport request is like the tram. Assigning some object to a
transport line is like buying a ticket for this line, while assigning an object to a transport request is like
actually putting it on the train. Exporting the transport request is like the train leaving the station, and the
import is the reverse.

Some More Basic Concepts of the SAP Change and Transport System

Let me show you an example to help you understand how a program BB in a package z_my_package
assigned to transport layer DeCoPro and transport request 1 is transported through a system landscape with
three layers (the names of the transport request and the transport layer are simply chosen for didactic
reasons and irrespective of existing conventions and technical constraints). The figures just concentrate on
the entities mentioned: The program, its package, the transport request and the transport layer.
1. Our Program is assigned properly to the package, this in turn is assigned to a transport layer, both are
assigned to the same transport request, that is a transport request that has the same destination as the first
destination defined in the transport layer. So far nothing has been transported. The transport is not released
and you can still change it, that is, you can, for example, assign other objects to it or change programs in the
request.

2. The transport request has been released from the development system and been imported into the
consolidation system. As you see, there are copies of program BB and its package in the relevant
destination system after the transport. And this makes sense: If the transport moved the program, many
transports would empty a system, and above all, you could no longer change a program after it has been
transported out of a system. The released transport request is in the consolidation system too, and it also still
exists in the development system. In fact, this is only the logical perspective. Physically the objects in a
released transport request are written to a file, and this file exists only once. When it is imported into another
system, this system gets a reference to this file.

3. Next after the tests in the test system are completed successfully we import the transport request into the
productive system.

Again, physically the productive system just gets a reference to the exported transport request in the file. So
the arrow between the systems only expresses a temporal and logical sequence. I still decided to use these
arrow as this is the typical way to sketch the structure of the transports through a SAP system landscape.
The physical structure (see figure below) is like this: When importing the Transport Request 1 into the
consolidation and the productive system these systems just get a reference to the export files of the relevant
transport request:
At this stage of the explanation, you might ask yourself what happens if you have to change program BB for
some reason. Well, let us suppose in the productive system a branch of your program is executed that has
not been tested so far, and the program does not behave as expected. So we have to change it, and we do
this in the development system. This is what the division in the three layers is for. As the name suggests, in
general, you only develop in the development system. Of course, there are some situations when you better
correct errors in the consolidation system (for example if this system gets programs from different
development systems and the error does not appear in the development systems, but only when the sources
from the relevant development systems are activated and run on one system), but then you should change
the relevant development objects in the consolidation and the development system. Otherwise you will easily
get inconsistencies between these two systems. But in our example we can stick to the general rule to
develop in the development system.

In order to change the program, we need to assign it to a new unreleased transport request:

There we are. We have assigned the program to a new unreleased transport request, which can still be
changed. A package is usually only transported once, except for the case that the package properties have
changed. For this reason we only assign the program to a new transport request and not the package. But
what happened to the previous assignment of the program to transport request 1? Nothing. The point is
simple: A development object can be assigned to one unreleased changeable transport request only, but,
in addition to many released transport requests.
But why is it that the assignments to the old, released requests do still exist, if they are not changeable?
What are they good for? Probably you guess the answers: This is for matters of versioning. Whenever a
transport request is released an actual version of the program state at this time is stored. You can both
return to this old version in case you need to or simply use it to track when which version of a program was
released. Before leaving this short introduction to the transport system, let me mention that, of course in our
example we need to transport our bug fix to the productive system, before our problem is corrected there.

But this should suffice by now to give you a basic understanding of the SAP Change and Transport System.
As I told you before, the CTS offers a complex set of features, and in this intro blog I can do no more than
give you a clue as to what you are doing when you fill out the relevant fields during the creation of package
and a program.

Package Building Continued

So let us go on with our example. For our demo system you should use the transport layer znsp throughout
(as already told, you also need a transport layer if you want to export a development object to a file. In a later
blog we show how you export and import development objects to or from a file).

If you have input all values as shown on the last figure you press the Create button.
In the next dialog window you have to assign your package to a transport request. As we do not have a
transport request of our own so far we create one by pressing the Create button in this dialog window and
the next dialog window appears. We input some short description as shown:
Just note in this context: In a real-world development project you will always use a transport request that is
created in the transaction SE09 and paste this into the window with the header Prompt for transportable
Workbench Request, that is the window we have just shown, and not create the transport request by using
the Create button in this window. By using the SE09, you have more control on the transport request you get.
If you just need a transport request without any particular properties, you can do it the way we do it here.

Pressing the Save button opens another dialog window:

There it comes: Our first transport request. We finish the creation of our package by pressing the Create
button. And now we have done it. We have created a package of our own.

The package we have just created is shown in the list below the input field of the Repository Browser where
the $tmp package of our BCUSER was shown before.

In case you feel a bit dizzy by now because of the bunch of dialog windows, do not hesitate. Let us do
something similar again and pass a similar cascade of dialog windows in order to create a program in our
package.

Creating a Program Within a Package

So we create a program within this package, or to put it another way, create a program and assign it to this
package. If you have completed this task you will see that these dialog windows always appear in a defined
order, and once you have understood this order, you will feel no more confused by clicking your way through
the dialog windows than by walking through a long floor with several doors.

So let us start. We right-click on the package Y_ABAP_Demo and choose Create - Program.

Again we are lead to a dialogue window, where we input the name of the program we want to create
y_select_f_flight. We deselect "Top Include" because we still do not need a top include, and we
confirm. As in the case of our last program z_hello_word_local we get the dialog window that defines
the program properties. We confirm again and in the dialog window we see that the system already proposes
y_abap_demo as the package for our program. We press the Save button.
The next dialog window also offers little work for us. The transport request our package belongs to is already
in the relevant field.

Again we confirm and we have done it: We have created a new program within a package.

The procedures I have just described might look like a lot of work, but let me repeat it: After a short while it
will cause no more trouble than getting the car key, opening the car, sitting down, fastening the seat belt, and
turning the ignition key. In real life, you hardly pay any attention to these actions. In the same way you will
create programs in ABAP. The steps are always the same:

 Give the program a name,


 Define the properties of the programs (in general, you just accept the values proposed by the
system),
 Assign your program to a package,
 Assign your program to a transport request.

Outlook

Instead of a summary I want to finish this blog by giving an outlook on what we will do in the next blog. By
now the ABAP Editor has opened in the change mode and below the usual comments at the beginning of a
report you have the first line: report y_select_f_sflight. You know this already from the last blog.

From here we will start in one of the next blogs and write a program that performs the task of a typical
business program: It selects some lines from a database table that fulfill a given condition, stores them in a
container in the program, an internal table, and shows this internal table in a quick and dirty way on the
screen. We will use a Dynpro-based list and an object-oriented alternative to do this. As already mentioned,
you should use this technology for test purposes only: It facilitates a fast and easy output to the screen, but
does not support the model-view-controller paradigm.

In some later blog we will show you how to output a table like this in a real world program: You encapsulate
your business logic that contains the SELECT statement in a global class or a function module and offer the
relevant data in a getter method. The presentation in the UI is done in a Web Dynpro ABAP application that
accesses the relevant modularization unit that offers the data.
A FIRST LITTLE BUSINESS PROGRAM

Now it is time to write a program that does something more than just output "Hello World". In blog 7 of our
series we have done the necessary preparatory work, that is, we have created a transportable package for
all our programs and a program within this package. With some more experience you will handle this prep-
work very fast with hardly paying any attention to it, though it might look time consuming at first sight. The
other reason why I spent some more time on this is that it will pay if you know what your are doing when
clicking your way through these dialog windows: The SAP CTS (Change and Transport System) does not
exist for its own sake, but it has proven to be highly useful in large development projects and that is why SAP
created the CTS.

In any case, the result of the last blog will be the starting point at which be begin to write our program. You
will only be able to reproduce what we are doing in this blog, if you have the results of this blog or are able to
create an empty report, that is a program of the type report. If you have trouble doing this, just look in blog 7.

The Aim: Our First Little Business Program

So much for the preliminaries. So let us resume the work we have begun in the last blog. Our aim is to write
a typical business program: It selects some lines from a database table that fulfill a given condition, stores
them in a container in the program, and shows this data in a quick and dirty way on the screen. As to the
presentation of the result in the user interface I will show three alternatives that are easy to realize, straight
forward to understand and require a minimum of coding effort. You will probably be surprised at how simple it
is to output a result table on the screen in ABAP.

All three alternatives are based on classic Dynpro technology. That means you should use them for test
purposes only, if you need to output some result fast. Each alternative has an advantage of its own and
contains new ABAP commands for you: The first one is straight forward in that you see all the different
components that you output. You can use the second alternative to output any result table of a SELECT on
the screen no matter what its components are. Understanding this you get to know two important means for
dynamic programming: the field-symbol, which is a sort of a pointer and the dynamic assign. The third
alternative is based on a service class that needs hardly more than the name of the table you want to output.
The code of this gives you an impression of how object orientation is realized in ABAP.

Nevertheless, useful and fast-to-realize as these alternatives are, they are all more or less comfortable ways
to output results for test purposes. In a real-world program you use Web Dynpro ABAP, encapsulate your
business logic in a global class or a function module and hand over the data needed in the user interface as
parameters. But I think it is perfectly legitimate to use this classic technology at this stage of our blog series.
Just compare it to the output to console so widely used in Java tutorials though nobody would bother a real
end user with such a user interface.

How to Use the ABAP Documentation

Our example is based on the SAP flight model: This model gives a simple description of seat bookings in
passenger airplanes by flight customers and is realized in a set of database tables such as SCARR for air
carriers, SPFLI for flight connections, SFLIGHT for flights and SBOOK for bookings. You find more
information on this model in the SAP Help Portal under this link. The SAP Help Portal contains the SAP
documentation in different tree structures. The key node of the ABAP documentation in this portal is here.
The topics we touch in our weblogs are mainly covered under these three subnodes.
The documents under the node ABAP Programming and Runtime Environment describe language-related
topics. Under the header ABAP Workbench you find documentation on the tools to edit objects like reports,
function modules, and global classes, on the Transport Organizer, on test tools like the ABAP Debugger and
the Performance Trace and all the other tools of the ABAP Workbench. The Web Dynpro ABAP
documentation provides a description of the complete architecture of Web Dynpro ABAP and its main
concepts. You should consult the Help Portal for ABAP topics when you have questions that are related to
tools, the architecture or the relation of concepts. For information on the keywords and syntax of the
language itself there is the system documentation. One way to access the system documentation is by
marking the relevant command in the editor and pressing the F1 button.

How to Get an Internal Table with the Line Type of a Database Table

This was a short digression to the ABAP documentation and how to access it. Let us go on and select some
flights from the database table sflight, in particular the flights that fulfill two conditions: The airline is
Alitalia and the seat capacity of the airplane is smaller than 250 seats. We want to output the result set of this
select condition on the screen. We begin our program by declaring the data we need:

DATA: itab_flight TYPE STANDARD TABLE OF sflight,


wa_flight TYPE sflight.

In the first statement we define an internal table with the line type of the database table sflight. The way
this works in general is simple:

DATA: sometable TYPE STANDARD TABLE OF [any database table].

This declaration defines the internal table with the line type of the database table given in the square
brackets at the end. An internal table is the ABAP data type that is tailor made for business programming. It
is a dynamic data field that can contain a practically infinite number of lines. You can use centrally defined
line types or define a line type within your program.
The figure shows a linetype for contacts (1). It consists of first name, last name and city. The internal table
itab_contacts (2) can contain a practically infinite number of lines, the technical size limit for an internal table
is 2 GB.

Open SQL in ABAP

Next we select from the database table sflights all flights of the carrier Lufthansa with airplanes that have
less than 250 seats:

SELECT * FROM sflight INTO TABLE itab_flight


WHERE carrid = 'LH' AND seatsmax < 250.

As you can see a subset of SQL is part of ABAP. This so-called Open SQL has a big advantage for you: It is
a database independent subset an SQL, so that your SQL statements are valid for the database of every
vendor that is supported by the SAP NetWeaver Application Server ABAP. As the application server always
has a database connection at hand, you need not care about opening, administrating and closing such a
connection. By using the keywords INTO TABLE you perform an array fetch, the whole result set is
transported into the internal table. The only precondition is that the database table and the internal table
have the same line type.

Next we want to see the content of the internal table. One way to see the content of this internal table at
runtime is to switch to the debugger and to have a look at the content of it. We will show in a later blog how
easy this is in ABAP. You can just set a breakpoint at a particular statement and the debugger opens as
soon as this statement is processed.

Test Output of an Internal Table 1: A Loop and a Write-Statement

Here we will output the content of the internal table on the screen by using a classical list. ABAP has a
particular control statement to loop over all lines of an internal table. Let us use it:

LOOP AT itab_flight INTO wa_flight.


WRITE: wa_flight-mandt,
wa_flight-carrid,
wa_flight-connid,
wa_flight-fldate,
wa_flight-price,
wa_flight-currency,
wa_flight-planetype,
wa_flight-seatsmax,
wa_flight-seatsocc,
wa_flight-paymentsum,
wa_flight-seatsmax_b,
wa_flight-seatsocc_b,
wa_flight-seatsmax_f,
wa_flight-seatsocc_f.
SKIP.
ENDLOOP.

Every line of the internal table is put into the work area consecutively. Inside the loop the different
components of the work area wa_flight are written to the list output. In ABAP the hyphen is the component
selector for a structure.

How to Get to Know the Properties of a Database Table

You may ask, how could I know the components of this structure? Answering this question is a good
opportunity to show another useful feature of ABAP. Obviously, the work area is a structure of the line type of
the database table sflight. So we double click the name of this database table in the declaration at the top
of our report. We are asked to save the program, and we confirm. There we are:

The system has led us to the location where the table is defined. This is the ABAP Dictionary (Transaction
SE11). By using the Back button we return to our program. So this is the way you get to know the
components of the line type of a database table.

What the List Output with the Write Statement Looks like

The way the output to a list works is simple: As soon as the whole list is filled it is output to the screen. So let
us save and run our program, and the upper part of the result on the screen looks like this:
Obviously this way to write the lines of the internal table while looping over it presupposes the knowledge of
what the components of this table are.

Test Output of an Internal Table 2: A Dynamic Way to Output Any Internal Table

Next I will show you a way to write the lines of a table without knowing the different components of its line
type. First of all you can reuse these lines of code to output any result of a SELECT that is stored in an
internal table. And secondly, you encounter two important means to realize dynamic programming in ABAP:
the field-symbol and the dynamic assign.

First we have to declare such a field-symbol, this is a particular field type in ABAP. Without going into the
details of it, you should know that a field symbol works like a pointer without pointer arithmetics, but has a
value semantics. You can assign it to different data fields and when accessing their content there is no need
for dereferentiation.

FIELD-SYMBOLS: <wa_comp> TYPE ANY.

The typing ANY is necessary because the field symbol should be able to refer to data of any type. And this is
what our loop looks like now using a dynamic assignment to the different components of the work area:

LOOP AT itab_flight INTO wa_flight.


DO.
ASSIGN COMPONENT sy-index OF STRUCTURE wa_flight TO <wa_comp>.
IF sy-subrc <> 0.
SKIP.
EXIT.
ENDIF.
WRITE <wa_comp>.
ENDDO.
ENDLOOP.

The most complex activity is contained in the third line. The rest is simple and straight forward: The system
variable sy-index contains the loop counter that is counted up with every processing of the loop. The n-th
component of the structure is assigned to the field symbol. If this is successful (if sy-subrc =0) the content
of the field symbol is output to the list using the write-statement. If there is no more component to be
assigned to the field symbol, the assign is not successful (sy-subrc <>0) and then we leave the DO-loop
(the inner loop) and go on with the outer loop.
To check if our new lines yield the same result we comment out the original loop. You mark the relevant lines
and press CRT and "<" simultaneously. We run the program and the result is almost the same. There is one
difference: This table has some more columns because this time we output all columns, while in the first
alternative we have not shown the columns SEATSMAX_B, SEATSOCC_B, SEATSMAX_F, SEATSOCC_F.
If you doubt this just double click on sflight in the program and look in the declaration of the table in the
ABAP Dictionary.

Test Output of an Internal Table 3: The Object Oriented Way

A more comfortable way to output the internal table is by using a service class that outputs the whole table
plus the header information provided in the ABAP Dictionary. First, we need to declare a field that can keep a
reference to the service class.

DATA alv TYPE REF TO cl_salv_table.

The whole output is contained in two statements:

cl_salv_table=>factory( IMPORTING r_salv_table = alv


CHANGING t_table = itab_flight ).
alv->display( ).

The class method factory of the class cl_salv_table needs the internal table it should show, creates
an instance of this very class, and exports a reference to this instance. In the second statement the method
display of this instance outputs the table to the screen. Before we run the program, we should, of course,
comment out, the dynamic assign plus the loop:
The Whole Code of the Three Alternatives – An Overview

Now let us have a look at the whole code of our program in one listing. I have commented out alternative two
and three to output the internal table on the screen. So if you use this code as it is, you run alternative one.
To change this just comment out other parts of the code (press Shift + CRT + ">" to uncomment and CRT +
">" to comment out some lines):

REPORT read_table_flights.
DATA: itab_flight TYPE STANDARD TABLE OF sflight,
wa_flight TYPE sflight,
alv TYPE REF TO cl_salv_table.
FIELD-SYMBOLS: <wa_comp> TYPE any.

SELECT *
FROM sflight INTO TABLE itab_flight
WHERE carrid = 'LH' AND connid = '402'.

* Alternative one: Loop at table and write the different components of work area
LOOP AT itab_flight INTO wa_flight.
WRITE: wa_flight-carrid,
wa_flight-connid,
wa_flight-fldate,
wa_flight-price,
wa_flight-currency,
wa_flight-planetype,
wa_flight-seatsmax,
wa_flight-seatsocc,
wa_flight-paymentsum.
skip.
endloop.

**Alternative two: Loop at table with dynamic assign of component


*LOOP AT itab_flight INTO wa_flight.
* DO.
* ASSIGN COMPONENT sy-index OF STRUCTURE wa_flight TO <wa_comp>.
* IF sy-subrc <> 0.
* SKIP.
* EXIT.
* ENDIF.
* WRITE <wa_comp>.
* ENDDO.
*ENDLOOP.

** object oriented way


*cl_salv_table=>factory( IMPORTING r_salv_table = alv
* CHANGING t_table = itab_flight ).
*alv->display( ).
Summary

Now you have learned:

 What an internal table is good for and how easily you can declare an internal table of the same line
type as a given database table
 How you write a SELECT statement in ABAP and put its result into an internal table.
 A simple way to output an internal table on the screen by looping over it and outputting each line
component-wise.
 A dynamic way to output any internal table using a field symbol and a dynamic assign.
 An object oriented way to output the whole table without any looping.

GETTING MORE FAMILIAR WITH THE ABAP DICTIONARY

In this blog of our series we will improve the program from the last blog and show you some other useful
features of ABAP and the development environment provided by the NetWeaver Application Server ABAP.
You find an overview of all the blogs in the series here.

Quite obviously our program is not very flexible. In fact, what the program does appears more hard-wired
than really program driven insofar as you always get the same result. In this blog we will adapt the program
so that you can choose the carrier on a so-called selection screen. Using this selection screen you can very
easily create a UI to input the relevant parameter, but you should use this also (just as the list output) for test
purposes only, as it is based on old technology. Still, with this limitation, the selection is the perfect means to
create a user interface for input of test data in a quick hack. So we will create one to input the carrier.

Astonishingly enough, we will find that there is a value help for the input of the carrier, when we call this
selection screen from the program. Apparently this is quite useful, as the user cannot be expected to know
the carriers available, let alone the abbreviations of the carriers that are needed by the program. At this
stage, we will take the existence of this value help for granted, but keep the question in mind: Where does
the value help come from, if we have prepared nothing of this kind in the program code?

Moreover there lurks the problem that we do not know in advance for which searches we will get a non-
empty result set. We cannot be sure if there are any flights in the result set for a particular carrier. To make
matters worse, we also will not know, why the program does not show any flights, if this happens. You might
suppose that there might be something wrong with the program presenting the values in the user interface if
it does not show any flights.

We will tackle all the question addressed in the course of this blog:

 First we show you how to navigate from the definition of a database table in the ABAP Dictionary
(transaction SE11) to the Data Browser (transaction SE16) that enables you to look at the records in
the respective table. This way, you can check beforehand whether the data you input will produce a
non-empty result set.

 Having a closer look at the ABAP Dictionary and the way data types are defined there we will get a
better understanding of how and why technical and semantic properties of a data type can be
defined separately from each other: Semantic properties are defined in the Data Elements, while
syntactic properties can be defined in the Domain.
 It is the data element that contains a reference to a Search Help. The so-called Search Help is also
defined in the ABAP Dictionary and provides the value help we use when inputting our carrier as a
parameter.

 In some of the next blogs I will present you the standard solution to problems like this: Quite
obviously, the standard approach to a problem like this, is to use the debugger. This is true for ABAP
as for any other programming language. But with the SAP AS ABAP it is particularly easy to start the
debugger. You can diverge into the debugger from the normal state of the system. There is no need
to start the system in a particular debugging mode in ABAP. Moreover you will find, that the ABAP
debugger offers all the functionality you expect from a state-of-the-art debugger. But this is
something that should only raise your interest in the blogs to come. Explaining the ABAP debugger
will not be part of this blog.

PARAMETERS and the Selection Screen

We start by copying the program from blog 10 to another program. To do this, we navigate to the program in
the object tree of the SE80, right click it and choose Copy. A dialog window opens:

We enter the name of the target program as shown and press the Copy button. Next we switch to the
Change mode (by selecting the respective button).

So what do we want to achieve? We are not content with the SELECT statement as it is:

SELECT FROM sflight INTO TABLE itab_flight


WHERE carrid = 'LH' AND seatsmax < 250.

Instead of always choosing the carrier Lufthansa, we want to enable the user to input other carriers and look
what flights they offer.

In ABAP this is quite easy to achieve. We declare a variable of the relevant type as an input parameter of the
program:

parameters: p_carrid type s_carr_id.

This simple line of code serves two purposes:

 First, it is the declaration of the variable as we need it. (Later in the blog you will understand why we
use the data type s_carr_id).

 Secondly the parameters-command in ABAP creates a so-called selection screen at run time, which
is a screen to input the respective variable(s) declared in this command.

In order to make our parameter do some work we adapt the select statement:

SELECT FROM sflight INTO TABLE itab_flight


WHERE carrid = p_carrid AND seatsmax < 250.

We save, activate and run the program. As I have told you, we get to a so-called selection-screen.
Since we are not familiar with the carriers in the database we need a value help and press the F4 Button.
Surely, you remember: This is the button to trigger the value help in ABAP, if there is a value help supplied.
Obviously, there is a value help though we have not done anything to provide one:

We choose BA for British Airways, confirm and press the Copy button (with the checkmark icon). Nothing
happens.

And this is the situation I have mentioned at the beginning of this blog. Obviously, we do not really know, if
there is something wrong with our program or if there are no flights of British Airways with the specified
capacity.

From the ABAP Dictionary to the Data Browser

As a first approach to solve this problem we try to find some other way to check if there are any flights in the
table that match our SELECT criteria: We double click the name of the database table sflight in the data
declaration of the program. The ABAP Dictionary opens. The Fields tab shows the name of each column
plus its data type, as we have already shown in blog 10. At the moment we use the ABAP Dictionary only to
pass through to another transaction that provides us a view on the content of the database table. To get
there, we choose the menu Utilities – Table Contents – Display. We reach the selection screen of the Data
Browser (SE16):
First we enter BA in the field CARRID. A message in the status line tells us: "No table entry found for
specified key".

In order to get an overview of all the entries in the table, we delete the input BA, select the Execute button,
and get a list with the entries:

A view at the relevant section of the table shows that there are no entries for BA at all. So we have one part
of the answer to the question of why our program showed no result list. Still you might wonder why the
program does not even show an empty list. Let me add a particular feature of the report-logic to answer the
question completely: If there is no list output the program returns to the selection screen. (But be careful: In
case you ever want to use this feature in test programs, you should know that the selection screen is opened
in a new internal mode. That means the global variables of the program are reset to their initial values.)

Now it is time to have a look at the question where the value help came from. You surely remember that in
blog 10 I told you that the flight model is part of all delivered SAP systems. This means the respective tables
and the relevant data elements are available in the system. That was why we could use the table sflight with
all its components though we have not stirred a finger to create it. The same is true for the value help as I will
show in the next section.
Data Element, Domain, and the Way They Interact

We navigate back to the ABAP Dictionary, where we see the definition of the database table sflight. We want
to have a closer look at the type of the component CARRID since we have a value help for a parameter of
this type. So we double click the data type S_CARR_ID.

We get to the data element S_CARR_ID:

Still we find that the syntactic properties of the type are not defined in here, but defined in a Domain. So we
drill down to the domain by double clicking its name:

To make a long story short, the ABAP Dictionary provides two levels to define a data type: The data element
determines the semantic properties of a type, while you can assign a domain to the data element, and it is
this domain that defines the syntactic of technical properties. What is this two-level-structure good for?
Apparently it is a good idea to reuse the technical properties of a data type. For instance, a character field of
length three, can be used for all kinds of IDs, not only for carriers. They all share the syntactic properties, but
need, for example, different labels.

Probably you remember the last blog: When we output the internal table with the display method of the class
cl_salv_table all the columns had header information on the screen. You might have asked yourself: Where
did this information about the header text come from? It is now that we are in the right position to answer this
question: The text used for headers is defined in the Data Element under the tab Field Label:
On the level of the Data Elements (1) you define the semantic properties, and, the syntactic properties are
defined in the Domain (2).

Of course, this two-level-structure is optional: If you want you can define also the syntactic properties in the
Data Element.

At Last: The Source of Our Search Help

The Data Element is also the place where search help for a data element is defined. Under the tab Further
Characteristics you see the name of a search help: S_CARRIER_ID:

By double clicking the name of the search help we could go into the details of the search help. I do not want
to do this here, but it should suffice to state: A search help is a particular kind of object that is created and
edited with the ABAP Dictionary. It provides a value help with the list of possible input data by drawing the
data from a table that serves as the data source.

The fact that the search help is a property of the data type has a big advantage: A search help defined in the
ABAP Dictionary, is also available in Web Dynpro ABAP applications if the fields on the screen are typed
with the right Dictionary types that supply such a help. We navigate back to our program by using the Back
button and take some breath and sum up what we have learned so far about the ABAP Dictionary and the
Parameters command.
Summary

 The ABAP Dictionary (SE11) defines the technical properties of a database table such as the name
and the data type of each column. It is possible to define the syntactic and the semantic properties of
a data type separately from each other, the semantic properties in the Data Element, and the
syntactic properties in the Domain.

 Typical semantic properties are the field labels and the reference to a Search Help. So we know by
now where the value help that seemed to appear by magic is defined: In the Data Element of
S_CARR_ID. A Search Help defined there can also be used in a Web Dynpro ABAP application.

 The Data Browser (SE16) is the place where we can get an overview of all the entries of a database
table. We can navigate there via the ABAP Dictionary as we have seen, but we might, of course,
also open another session, input SE16 as an ok code and enter the name of the relevant database
table there.

 The Parameters command is very simple to use and still a powerful means to create a UI for user
input. But nowadays you should use it for test purposes only because it is based on classic
technology.

With the knowledge we have acquired, we can now check if the WHERE-condition of our SELECT should
lead to a list output. In order to make sure that nothing else goes wrong, you should be able to use the
debugger. As I have already mentioned in the introduction of this blog, I will soon introduce this powerful tool.
You will find it particularly useful, since you can just jump into the debugger without making any time
consuming preparations.

DEBUGGING IN ABAP

In this blog (blog 12 of our blog series) you get to know one of the most important tools for an ABAP
developer, the debugger, and an important source of information that every developer needs: the ABAP
keyword documentation. I will give you a short overview on the ABAP debugger and use it to find a particular
bug. You will probably be pleased to learn that in the SAP AS ABAP it is very easy to start the debugger.
You can diverge into the debugger from the normal state of the system. There is no need to start the system
in a particular debugging mode in ABAP.

Moreover I will show you how to benefit from some really useful features of the ABAP keyword
documentation. All these explanations are embedded in a practical example: We will change the program
from blog 11 in order to present fewer columns in the UI, to order the entries and to minimize the result set.
In the course of doing this, you will learn:

 How to define a structure

 How to narrow the result set of a SELECT by reading less fields from the database

 A particular addition to the SELECT statement that enables you to restrict the number of fields
transported into the target field of the SELECT.

Defining a Custom Structure in a Program

As a preliminary we copy the program from blog 11 to the program y_select_f_flight_ad_2. If you
have any trouble doing this refer to blog 11 where I describe how to copy a program
y_select_f_flight_ad_1. Let us start by defining a narrower structure than the one we had in our
program. You remember that by defining wa_flight TYPE sflight we got a structure that was as broad
as the table sflight with all of its fields. We assume, we need only some of its fields, namely: carrid,
connid, fldate, price, currency, and planetype. So we add a new data definition:
DATA: itab_flight TYPE STANDARD TABLE OF sflight,
wa_flight TYPE sflight,
alv TYPE REF TO cl_salv_table,
BEGIN OF str_flight_s,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
price TYPE sflight-price,
currency TYPE sflight-currency,
planetype TYPE sflight-planetype,
END OF str_flight_s.

If you have read the blog in which I introduced the Data Element, you know what additional benefit we get by
using those Dictionary data types: They all have defined field texts. Since I intend to use the object-oriented
way to output an internal table (look at blog 10) we will profit from these texts by getting headers for all the
table columns we output.

You may think that by now we do not even have an internal table that has the same line type of our new
structure. And you are right. So let us create one:

DATA: itab_flight_s LIKE STANDARD TABLE OF str_flight_s. does the job for us. We use the
keyword LIKE because we do not give a type for the table line, but a structure. Next we adapt the select
statement:

SELECT *
FROM sflight INTO TABLE itab_flight_s
WHERE carrid = p_carrid AND seatsmax < 250.

Again we have an array fetch, because we select the whole result at once, and we have … yes, we have a
syntax error. Press CRT + F2, this is the keyboard short cut for the syntax check to see this.

A Useful Addition to the SELECT Statement

At second thought it is easy to understand what is wrong with our SELECT. By using the asterisk we read all
columns of table sflight, and this does not completely match with structure str_flights_s. Of course,
there is a partial match, because the structure str_flights_s contains only fields that are typed with the
respective types of the columns of sflight, but it does not contain all the fields of this database table, only a
subset. Wouldn't it be nice if we could tell the program: “Move only the fields from the result set to the target
structure that have a counterpart in this structure”? And indeed, there are some keywords in ABAP that do
this job. We adapt the SELECT statement again:

SELECT *
FROM sflight INTO CORRESPONDING FIELDS OF TABLE itab_flight_s
WHERE carrid = p_carrid AND seatsmax < 250.

But be careful with the keywords INTO CORRESPONDING FIELDS. They can do no magic, but use the
identity of the names for the assignment: That is the value of the selected entries from database table
column A are moved to the fields in column A of the internal table. And this is all. In our case, the fields with
an identical name also are of the same type, but if this would not be case this is not checked by the system.

Next we use the object-oriented way to output our internal table. In order to get some additional information
in case the internal table itab_flight_s is empty we add a condition. So our code looks like this:
IF itab_flight_s IS INITIAL.
WRITE: 'nothing in table.'.
ELSE.
cl_salv_table=>factory( IMPORTING r_salv_table = alv
CHANGING t_table = itab_flight ).
alv->display( ).
ENDIF.

We comment out the two alternative ways to output the table (mark the relevant code and press CRT +
SHIFT + "<"), save, activate the program, and run it.

What Is Wrong With Our Program – We Start to Debug

We know from blog 11 that there is a result set with some entries in it if we choose Lufthansa in the selection
screen as the value of the parameter p_carrid and so we provide the same value for this parameter.
Unfortunately the result is not satisfying:

It might seem hard to understand why we do neither get the output "nothing in table" nor an output showing
some table entries. So this is the time to resort to the debugger. To see what our SELECT statement does at
runtime we set a breakpoint at this line. We do this by double clicking the leftmost column in the editor as
shown and a small icon appears that stands for a breakpoint:

Before starting to debug we check if we have really chosen the new debugger. In fact your system should
already be configured accordingly. If not we open the menu: Utilities – Settings – ABAP Editor –
DEBUGGER and select "New Debugger". And now let us go. We run the program, choose the input
parameter Lufthansa and select Execute or press F8:

A new external mode opens and we see the new debugger. Let me use this opportunity to give you some
general information on the debugger before we go into the details of how to find our bug.

The New ABAP Debugger – A Short Overview

You know, you live in good times, at least as far as the ABAP debugger is concerned. Since NetWeaver
2004 there is a completely new debugger that runs in another work process than the program that is
debugged, the debuggee. This is why the new debugger always starts in a new external mode.

To put it in a nutshell: This debugger is a state-of-the-art tool that offers the features you expect from any
debugger, even some features more (for example a tool to compare the contents of any two internal tables).
The navigation within the debugger is straight forward, and you can easily configure the different tools in it as
you like. As for the general layout of the debugger, it is divided in different tabs. Each tab stands for a
desktop of its own, that can contain different tools, which, for example, show the source code, the call stack,
or the value of variables etc. You can customize each desktop by inserting the tools you like in the position
you want. To give you a general impression of what such a desktop in the debugger looks like let me show
you a screenshot of the standard desktop with its three tools:
Below the menus that are not shown in this screenshot (experienced bloggers on SDN know: the size of
pictures in SDN blogs is limited) there are some buttons to control how to step through the debugged code
(5). In the panes below you see the standard desktop (1) with the source code tool (2), the call stack (3) and
the variables and their values (4). So much for the overview of the debugger. But to really show you how to
work with it we go on searching our bug.

Debugging Our Program

As the debugger has opened with desktop 1 we first choose the standard desktop tab to see the tools as
shown in the figure above. We double click the name of the internal table itab_flight_s in the code view.
That has the effect that the debugger shows the value of this variable in the pane on the right (4 in the figure
above):

If you were more experienced with the ABAP debugger, this display would already tell you that we have an
internal table with six columns and no line. So you can just guess it or must believe me. To make sure that
this is the right way to understand what we see we double click the name of the internal table in this pane:
We get to the tab rider that shows the content of the internal table so that we can check, if there were any
lines to be displayed:
There are none. We navigate back to the standard desktop by using the Back button. Next we want to
execute the SELECT statement and then look again at the content of the internal table. So we need a single
step, and quite obviously the icons to control the debugging steps look as in most other debuggers, and
anybody familiar with debugging will have no problems to choose the right debugging steps in the ABAP
debugger:

We select the single step mode as shown, look again at the content of the internal table in the right pane
below. Obviously our internal table is now populated with 33 entries.

So we can feel relieved: There was no mystic loss of data in the system since the blog 11 when we had quite
a number of entries for the carrid of Lufthansa. We go on in the single step mode, and see that the first
branch of the if-statement is not taken. This is because the internal table is not empty. While we are stepping
forward we have an eye on the content of the internal table in the pane on the right. It does not change until
we reach the display method. So how could it be that there are no lines output, if the value of the internal
table it not empty and this table is output?

Obviously we have so far explicitly verified only the first part of the condition. So do we really output the
internal table, which has 33 lines as the debugger tells us? We have a closer look at the relevant statement:

cl_salv_table=>factory( IMPORTING r_salv_table = alv


CHANGING t_table = itab_flight ).
alv->display( ).

And there is the culprit. We have passed the wrong table to the factory method. We double click itab_flight to
view it in the variables tool. The table is empty, and this takes little wonder. It is the table we used in blog 11.
Since we have not deleted its definition it does still exist in the program, but no line was added to it.

Remember: We meant to replace its name by the name of the table itab_flight_s in all statements. But
it seems, we have forgotten one statement, namely the one in which an internal table is passed to the factory
method. So the table itab_flight is still empty, and it is this empty table that we pass to the factory
method. This is also the explanation of why our output showed many more headers for columns than our
new narrow table s_flight_s. We showed the old table s_flight with all columns of the database table
sflight and no content, because the result of the SELECT statement was moved to the new internal table
s_flight_s.

So we correct the statement accordingly, activate, save the program, and by double-clicking our breakpoint
we remove it: For the time being we do not need the debugger, we are fully confident that we have corrected
the mistake, and we are right.

Let me use the last sections of this blog to tell you a bit about good SQL programming style and something
more about the ABAP language documentation as I have announced at the beginning of this blog.

Some Words on Efficient SQL Programming

First of all, you probably know already that it is bad programming style to select more data from the database
than needed or used. Why is this so? In general, in a real-life system accessing the database is expensive.
You have the network latency and you have to access the hard disk if the table is not cached. In general,
both activities are far more time consuming than the execution of simple statements on the application server
that do only affect the memory of the work area of the process the program runs in. Selecting all fields from a
dataset on the database if in fact you move only a few fields to the target structure is as efficient as carrying
ten buckets of water to the tenth floor and then pour five of them away. Of course, it does not really matter in
our little example, but if you have result sets with some hundred thousands of datasets, you are well-advised
to select only the fields you really use:
So we adapt our select statement to:

SELECT carrid fldate planetype currency price connid


FROM sflight INTO CORRESPONDING FIELDS OF TABLE itab_flight_s
WHERE carrid = p_carrid AND seatsmax < 250.

I have chosen a sort of random order for the columns just to show you that this order does not matter
because the fields of the result set are moved according to their name. The order is irrelevant.

How to Use the ABAP Language Documentation Efficiently

Being economical we want to order the flights in the result by the price and the date. Most probably we need
an addition to the SELECT statement. If you are not sure what the relevant addition you need looks like in
detail, just position the cursor on the keyword SELECT and double click. A dialog window opens:
We double click the first alternative and get to a window with a tree in the pane on the left.
It shows the nodes and leaves under the node SELECT. Each node and leave corresponds to a page that is
shown in the pane on the right. You can navigate to the respective page by double clicking a node or leave
in the tree. The navigation within in the tree is quite as you expect it. We see that the SELECT node is
marked and the corresponding page is shown. The entry for the SELECT node starts with an overview of the
syntax of this statement:

We click sort key and get to the page that informs us in more detail:

So this should suffice to give you an impression of how you can drill down on the topic you need in the ABAP
language documentation.

You can use the arrow heads on top of the page to navigate back and forth to pages you have already
opened. The button bar offers some other useful functions you might need:

I guess the tool tips require no further explanation.

So much for the explanation of the ABAP keyword documentation. To learn more about the ABAP keyword
documentation have a look at a blog in which this source of information is introduced by its author.
Let us now go on with our example and enhance our SELECT statement by the keywords we have just
found:

SELECT *
FROM sflight INTO CORRESPONDING FIELDS OF TABLE itab_flight_s
WHERE carrid = p_carrid AND seatsmax < 250
ORDER BY price fldate.

We save, activate and run the program. Fortunately, this time it behaves as we have expected.

Summary

By now you should be able to use the debugger and to find your way in the ABAP keyword documentation.
In a sense, you can now stand on your own feet in ABAP. You know how and where to find information on
the details of the ABAP semantic and syntax. And you are able to track down the source of misbehavior if
your program seems to lead a live of its own and does not what it is expected to.

So in the next blogs I will explain not every new keyword we use as extensively as I used to. But as there is
far more to developing in a language than knowing the details of its keywords there still remains a lot of work
to be done in this series. In particular we will show you in the next blogs how to create database tables in the
ABAP Dictionary and relate them by a foreign key relationship. We will fill these tables with entries from a
text file we put in a directory of the server. And this is only the beginning. Some blogs later we will
encapsulate our program logic so that we can call it from a state-of-the-art UI: an ABAP Web Dynpro View.
At this stage you will learn the basics of Web Dynpro ABAP and how it interacts with the backend logic. So
we hope this short sketch of what else is going to come will heighten your interest in this series.

GET YOUR PROGRAM UP TO SPEED - OVERVIEW & INTRODUCTION

The runtime analysis tool allows you to examine the performance of any ABAP programs, such as reports,
subroutines, function modules or classes that you create in the ABAP Workbench. It saves its results in
performance data files, which you can display as lists. You can use these results to identify runtime-intensive
statements, to combine table accesses, and show the hierarchy of program calls.

Normally you use the runtime analysis tool to measure the runtime of complex program segments or
complete transactions (if you want to measure the runtime of smaller program segments or individual ABAP
statements you can use the ABAP statement GET RUN TIME FIELD).

However, we use only simple examples in this blog, in order to make the understanding easier.

The Programs to be Analysed

Let's assume I am a very newbie in ABAP and I have written a tiny little program which is doing the following:

 reading data from a database table

 storing that data in an internal table

 display that data on a list (at the start of the program you have to specify certain key values; only
matching data should be displayed later on).

So here it comes (and it seems to work as designed ...):

REPORT y_wlog_atra_1.
PARAMETERS: p_carrid TYPE sbook-carrid DEFAULT 'LH',
p_connid TYPE sbook-connid DEFAULT '0400'.
DATA: wa_sbook TYPE sbook,
itab_sbook TYPE STANDARD TABLE OF sbook.
SELECT * FROM sbook INTO wa_sbook.
CHECK: wa_sbook-carrid = 'LH' AND
wa_sbook-connid = '0400'.
APPEND wa_sbook TO itab_sbook.
ENDSELECT.

LOOP AT itab_sbook INTO wa_sbook.


WRITE: /,
wa_sbook-carrid,
wa_sbook-connid,
wa_sbook-fldate,
wa_sbook-bookid,
wa_sbook-customid,
wa_sbook-custtype.
ENDLOOP.

A nice colleague has thrown a glance at my source code. He has given the hint to use a WHERE clause with
the SELECT statement instead of the CHECK statement for reasons of better performance.

So I have written another program ...

REPORT y_wlog_atra_2.
...
SELECT * FROM sbook INTO wa_sbook
WHERE carrid = 'LH' AND
connid = '0400'.

APPEND wa_sbook TO itab_sbook.


ENDSELECT.
...

I am curious about the performance now. Let's compare the 2 variants with the ABAP Runtime Analysis tool.

ABAP Runtime Analysis: Tool & Procedure

To start it, choose Test --> Runtime Analysis in the SAP Menu, or use transaction SE30.

The runtime analysis procedure consists of two parts:

 Recording performance data (upper part of the screen)

 Analyzing the performance data (lower part of the screen; this part only appears if there are
performance data files in place)

The procedure for the first part (Recording performance data):

We go to the initial screen of the runtime analysis (transaction code SE30) and specify the name of the first
program (Y_WLOG_ATRA_1) in the relevant input field. After that we press the button Execute.
The selection-screen of the program Y_WLOG_ATRA_1 (including the 2 input fields) is displayed. At the
bottom of the screen we are informed that the measurement has been started. We continue by clicking the
Execute button.

Later on we will see that a file (containing performance data) has been created in parallel.

Now we repeat that procedure for our second program (Y_WLOG_ATRA_2).

The second step is the analysis of the generated performance data.

To do that we have to go to the initial screen of the Runtime Analysis tool again. On the bottom part of the
screen you can specify those performance data files you want to analyse.

You can see some information related to the last measurement run (in our case that was program
(Y_WLOG_ATRA_2). By pressing the button Other File we are able to select those performance data files
we like to analyse.
I want to see all the files I have created (user BCUSER).

I get the relevant list with 2 lines (related to the performance data files of the programs Y_WLOG_ATRA_1
and Y_WLOG_ATRA_2).

Based on that list you can display the distinct performance data per line. You have to click in the column
Object Type of the relevant line.
As a start the tool displays the evaluation overview (showing the cumulated execution times for the ABAP,
database and system-level).
Here comes the evaluation overview for program Y_WLOG_ATRA_1.

We can do the same for the other program Y_WLOG_ATRA_2.

By comparing the performance data of the 2 programs we clearly see that I have done well with listening to
the advice of my colleague. The performance of the second program is dramatically better.

In the next step you can forward to a more detailed display of the performance data (hit lists). That listing
shows the different granular execution steps (according to your filter adjustments). Here you can easily
identify the most time-consuming program units.
And it will also be a good idea to glance at the Tips & Tricks corner. You will find many valuable
suggestions about good performance definitely.

THE FOUNDATION OF AN APPLICATION - CREATING THE DATABASE TABLES

This blog of our series (find the other blogs of the series here) is about building and managing the foundation
of any business application: The database table(s). With the ABAP declarative approach of the Data
Dictionary these things are so easy that you can concentrate on your data model and leave all database
vendor specific details to the system. From a technical point of view what I will explain is easier to
understand than the SAP Change and Transport Management. Still this blog is hard stuff because it contains
a lot of details and it is has become longer than I planned. But I saw no good way to cut the material into
different parts. In addition to the technical information I will explain the concept of a client in the SAP world to
some degree since we will build a client-specific table.

When creating a table on the Application Server ABAP all you have to do is to define the metadata of a table,
including foreign key relationships and check tables, search helps and fixed values. Just activate the relevant
object (s) in the Data Dictionary (transaction SE11) and the table is created on the underlying database of
the system. No need for any code as far as the data definition on the database is concerned. No need either
to care about vendor specific technical details. Your database tables will be created on any database that is
supported by the Application Server ABAP if this is the database of your system.
We will implement a simple data model almost from scratch in this blog. You will learn in some depth the
basics of

 How to define a database table

 How to define a foreign key relationship and thereby

 How to provide a check table for the relevant column in the foreign key table

 How to create Data Elements and Domains

 How to create Fixed Values in the Domain

You perform all these things in different screens of the Data Dictionary. This way you will get to know how to
manage database tables in a metadata-driven approach that is typical of developing on the Application
Server ABAP. Our central table will be a table of accounts that is related to some other auxiliary or check
tables. So I will give some substance to the claim of how easy database table handling is on the AS ABAP.
Another blog will show you how to fill this account table with data very easily by inputting some data into
auxiliary tables in the Data Browser (SE16) and then using these data in a program to create random entries
for the account table.

The Contents of this Blog in Some Detail

We want to create a table YACCOUNT that contains accounts and we want to use this table plus its auxiliary
tables for queries later in other blogs. The account table is related to a customer table by a n:1 relationship:
One customer can have many accounts, but an account is uniquely assigned to a customer. As for the
customer data we can profit from the fact that there is already a table with customer names and some
relevant attributes: The table SCUSTOM is part of the flight model that is delivered with every ABAP system
and this table should contain about 1500 customers in the Demo System you use. So we need not define a
customer table of our own and fill it with data, but we can simply re-use the table SCUSTOM and relate our
account table YACCOUNT to it by a foreign key relationship.

In another blog we will fill the database table YACCOUNT with some test data. This step is very important for
every business application. You have to test an application to see if it works. And you only can test it, when
you have some test data: We will first manually provide a small set of test data for the check tables in the
Data Browser (SE16). Using these entries in the check table a program of some 70 lines will create random
entries for the table YACCOUNT. This way we will get the test data that enable us to run Web the Dynpro
ABAP based applications we write in later blogs in the environment these applications need.

Let us now consider the structure of our central table in some detail: The account table should provide
columns for

 The client

 The account number

 The bank

 The city of the bank

 A customer ID that is related to the customer table

 The balance

 The currency

 A category that specifies the height of the income that is transferred to the account every month
Since the identity of an account is defined by client, account number, bank and the city of the bank, we
define a composite key with these four columns. This means there cannot be an account with the same
account number for the same client with the same bank in the same town.

Further we will assume that the number of banks, towns, currencies and income categories is limited in our
example. So we will provide check tables: For example the currencies permitted in our table, the foreign-key
table, are controlled by a table for currencies, the check table. These tables have to be related by a foreign
key relationship that is can also defined in the ABAP Dictionary.

This way we will also create these check tables and the relevant foreign-key relationships when defining the
table YACCOUNT. Though we can profit from the existence of the table SCUSTOM we still need some other
tables: For the bank and the city of the bank we will provide check tables to delimit the banks and cities
allowed, but we will keep these tables very lean indeed. As for the category, we do not need a check table,
but can use so-called fixed values in the domain of the relevant data element to control the number of entries
in the category column of the account table.

Defining all these things plus the data elements required might seem a bit tiring if not intimidating at first, but
you will soon realize that you do not need a lot of practice to create data elements and database tables really
fast in the Data Dictionary. It will be the same experience as the one you had when defining a package LINK:
When you have done it a few times with the relevant tools and have got accustomed to the procedure, you
will find it as easy as pie. So do not let yourself be put off when having a look at the all the stuff we are
defining in this blog.

I will spend less time on explaining details than in the last blogs. Having worked your way through the blogs
of our series you are sort of an advanced Newbie to ABAP. When I show you how to create data elements
and domains, how to define tables and how to relate them by a foreign key relationship I presuppose that
you are able to find your way in the ABAP Dictionary. In other words: I presuppose that you are familiar with
the blog on the Data Dictionary in our series. In particular you should know what a data element is, what the
respective definitions of field labels for data elements the definitions of fields for a table look like, not in great
detail, but to the degree that I have explained this in the blog mentioned

The Concept of a Client: A Key-Player in the SAP World of Business Programming

When defining the fields of the table YACCOUNT you see that the first field is the client. Probably you do not
know what a client is. At least to me "The Client" was no more than a suspense movie before I joined SAP.
Within the context of SAP ERP systems the client is an important concept that deserves some words of
explanation. Though the main focus of this blog series is on ABAP, its development environment and the
way you develop with this powerful language for business programming, it is nevertheless for some of you
also a first step into the SAP world. And within this world you simply should not only know the definition of
what a client is, but have some basic understanding of this concept. Those of you who are more interested in
ABAP development in a narrower sense or are already familiar with the client concept should simply skim or
skip the rest of this section.

A Client is in commercial, organizational, and technical terms, a self-contained unit in an SAP system with
separate master records and its own set of tables. This definition of a client in the SAP Help Portal is, of
course, comprehensive and true, but you may still ask yourself how one concept can have a commercial, an
organizational and a technical aspect at the same time. Let me start by sketching the commercial aspect of
the client concept. Then I explain how this creates technical requirements and how they are fulfilled.
From one point of view an ERP system holds

 A large bunch of business data and

 The applications that work with this data. These applications represent the business processes of a
company.
Obviously it is a good idea to organize these data according to organizational units and the business needs
of a company. The same holds true for the technical fine tuning of the business applications: For example,
the different international subsidiaries of a global company may need to implement the same business
processes differently in their systems. What I have loosely called the technical fine tuning is done by means
of customizing in an ERP system: You adapt an application to the specific structure of your business
processes. And maybe you want to adapt it in different ways for different subsidiaries. In other words: The
data need to be structured by organizational and business-related criteria, and the processes may require
different customizing for different subsidiaries of a company.

It is the concept of a client and the way it is implemented in a SAP ERP system that helps to fulfill all these
requirements.

The client is the highest organizational unit in an ERP system and a self-contained unit with its own master
data. From a commercial point of view a client can represent a corporate group of legally independent
companies. And you can customize the same process differently in different clients.

How is this separation technically achieved with the client concept?

 The client is the first key field in most relevant tables of an SAP ERP system.

 A user in an ERP system is always logged on to a particular client of a system.

 A SELECT in a program always selects only the data from the client the programs runs (system field
sy-mandt). There is no need to specify the client in the WHERE-condition. The client-specific data
are automatically selected.

It is because of this structure that you can keep the data of different clients in one table and still keep them
apart as if they were stored in different tables. And this is why our table is designed the way it is with the
client as the first key field. By the way, the client-specific customizing is also, to a large degree, realized by
tables that are designed the way I have just described.

But now let us return from this abstract explanation of a key concept of the SAP ERP world to the mundane
task of creating our table.

Defining the Data Elements

It is common practice to use data elements for all columns of a table and there are good reasons for this
practice:

1. All foreign keys must be typed with a data element.

2. So check tables to control the values of columns that require a data element.

3. The field labels defined in a data element will automatically provide translatable column headers and
labels when the respective data element is shown in the User Interface. This applies for Dynpro-
driven test UIs and Web Dynpro based user interfaces.

We need Data Elements for the account number, the bank, the city, the customer ID, the balance the
currency, the date of the last entry, and the category of the account. The first column for tables in common
business applications is the field MANDT which represents the client. We name the other columns
ACC_NUM, BANK, CITY, CUSTOM’ER, BALANCE, CURRENCY, LAST_ENTRY, and CATEGORY. The
Field CUSTOMER contains an ID that is related to the customer table SCUSTOM by a foreign key
relationship. For the columns MANDT, CUSTOMER and CURRENCY we can reuse Data Elements that
already exist. This re-use of existing data elements is also common programming style when developing in
ABAP.
Data Element for the Account Number: Y_ACC_ NUM

First we create the Data Element Y_ACC_ NUM. We navigate to the transaction SE11, select Data Type and
press the button Create. In the dialog window we choose Data Element and continue. We enter the short
description Account Number, select the radio button Predefined Type on the tab rider Data Type, and input
NUMC, a numerical character type and a length of 8. On the tab rider FIELD LABEL we have to input labels
of different length for our field:

We input Acc.Num. as a short label and Account Number in the other lines. We need not provide enough
space for some translation of the labels, and so we need not input the length for the Field Labels, but the
system calculates it by the actual length of the field labels we have just input.

When activating the data element we choose y_abap_demo as the package as in the other examples. The
next dialog window proposes us the same transport request as in the last example programs. We continue
and activate the data element (we will use this package and this transport request throughout this whole
example without mentioning this fact any more in this blog).

Data Element for the Bank: Y_BANK

Next we create a data element for the name of the bank. The procedure will be the same:

1. Input the name in transaction SE11: Y_BANK

2. Enter a short description: Bank.

3. Input the appropriate format: CHAR of length 30.

4. Go to the tab rider Field Label and enter Bank for the labels of all lengths.

5. Activate and Save.

Data Element for the City: Y_CITY

The data element Y_City has City as a short description and as the text for all field labels. Its format is CHAR
and length 30. For the column CUSTOMER we can reuse an existing data element from the table
SCUSTOM, as I have already told you.

Data Element for the Balance: Y_BALANCE

So we go on and create a Data Element for the column BALANCE: Y_BALANCE. We proceed in the same
way, but this time we will use a Domain instead of defining the data format by ourselves: We input the short
description Balance, select Domain as Elementary Type, input the Domain name S_PRICE, and press Enter:
The data format of the domain is shown below: CURR 15, decimal places 2. To complete the definition of
this data element Y_BALANCE we have to provide field labels in the way shown before: We input Balance
for all lengths. We save and activate the data element. Since you need to save and activate all objects that
you create this procedure will only be mentioned time and then. I just presuppose that you know by now
when and how to do this.

Data Element for the Last Entry: Y_LAST_ENTRY

For the field LAST_ENTRY we create the Data Element Y_LAST_ENTRY with the domain S_BDATE and
LastEntry as the text for all field labels and Last Entry as a short description.
Data Element for the Category: Y_CAT

Last we define the DATA Element Y_CAT with the short description: Account Category and the field labels:
Category (short) and Account Category (all other labels). By forward navigation we define the domain:
Y_CAT, format: NUMC and length 1. We switch to the tab rider Value Range and input the fixed values: 1
with the short description low income, 2 and medium income, 3 and high income.

Creating Database Table YACCOUNT

Now we have all the Data Elements we need at hand and we can create the database table YACCOUNT. By
the way: It is also possible to create the data elements you need by forward navigation when defining a
table, but I have decided to separate the definition of the data elements from the definition of the database
table in this blog for didactic reasons.

We return to the start screen of the Data Dictionary, select Database Table, enter YACCOUNT, and press
the button Create.

In the next window we input the short description: Account. Under the tab rider Delivery and Maintenance we
input A as the Delivery Class and Display/Maintenance allowed with Restrictions.
We change to the tab rider Fields and enter the name of the fields and their data elements as shown in the
figure below:
Next we mark the line CUSTOMER and press the Key icon to define a check table for this line and a foreign
key relationship. We refuse the proposal in the first dialog window as this suggests the check table from the
domain and this table is not suitable for our purposes. In the next dialog window we input the short text:
Check table for account ID and the check table SCUSTOM. Next we press the button Generate Proposal
and get to the next dialog window. There is no magic, but the system draws the proposal from the identity of
the data elements.

We enter 1: CN as the cardinality, and then we check the definition of the table for consistency by pressing
the Syntax Check icon. If this check is successful we press the Copy button.

As you need to define other check tables on your own later in this blog, let us repeat the steps necessary to
define a foreign key relationship with a check table that determines which values can be input into a
particular field:

1. Mark the line with the relevant field/column.

2. Press the button with the Key symbol.

3. Input some explaining text and the name of the check table.

4. Press the button Generate Proposal. (If the relevant data element has a value table defined in its
domain this table is proposed by the system after step 2.)

5. If the proposal is ok, just enter the relevant cardinality and press Copy to close the dialog window
and keep what you have input there.

We need another check table for the currency. Again we mark the line and press the Key symbol. This time
we confirm the proposal:

We only have to enter a suitable text and there we are. We select the Copy icon and have another check
table. The tab rider Entry help/check shows us the check tables for the table YACCOUNT.
Next we define a reference field for the column of the type CURR as shown in the figure below:

A reference field is needed for all currency and quantity fields as the figures in this field need a currency or
unit. If you have no reference field and table for fields of this kind you will get a syntax error. This syntactic
constraint reflects a semantic fact: A figure in a field does not tell you a lot if you do not know to which
quantities or currencies the figure is related: It does not suffice to know that you have, for example, five
items, but you need to know if you have five meters, five Euros, five pound etc. And this information is
provided the reference field and table.

There still remains some work to be done. We select the menu Extras – Enhancement Category. Here we
determine if and if so to which degree the table can be enhanced: We choose Can be enhanced (character-
type or numeric) and press Copy.

After saving again we press the button Technical Settings and choose the data class APPL0 and the size
category 0.
We save and activate, return to the view of the table we have been working with before. Next we save and
activate the table.

Let us pause for a second and reconsider the steps necessary to create a database table in the Data
Dictionary:

1. Go to the start screen of the Data Dictionary.

2. Type in the name of the table and select the Create button.

3. Enter a Short Description

4. Choose the Delivery and Maintenance tab rider and input a delivery class and determine if and how
the table can be maintained and displayed.

5. Change to the Fields tab; input the name of the fields and the respective data elements.

6. Select the Key checkbox for the key fields and select Initial Values for all fields.

7. Save and press the button Technical Settings.

8. Choose a data class and a Size Category by using the input help.

9. Save, go back and choose the menu item Extras – Enhancement Category and input this category.

10. Provide check tables and Reference Fields plus tables if you need to.

11. Save and activate the table. The table is now being created on the database. This is what is meant
by "metadata-driven creation" of database tables: You define the metadata and once you activate
this metadata, the table is created on the database.

Providing Some More Check Tables

Now you can test to which degree you have already understood the steps you need to define a table. We still
have to create the check tables for the columns BANK and CITY, and I will keep the description of how to do
this really short. In case you have any problems when creating theses tables just return to the last section.
For the field BANK in the table YACCOUNT we create the table YBANK with only one column BANK and the
data element Y_BANK: Again we choose A as the delivery class, but this time we select
Display/Maintenance Allowed. This is important, because we will input some banks into this table in the Data
Browser (SE16), and this is only possible if the maintenance of the table in the SE16 allows it with this value
for the attribute Data Browser/Table View Maintenance. The technical settings and the enhancement
category for the table YBANK are the same as for the table we have defined above. So you should know
how to handle this.

We need another check table for the field CITY in the table YACCOUNT. We name this table YCITY. Apart
from the columns this table has the same attributes as the table YBANK and the column CITY with the data
element Y_CITY and another column CURRENCY with the data element S_CURR. After you have
completed their definitions, we need to create the foreign key relationships with the relevant columns of the
table YACCOUNT.
You should also be able to do this on your own by now. Let me just give you some hints on how to do this:
Mark the relevant line in the table YACCOUNT, press the Key icon, enter a short text plus the relevant check
table, press the button Generate Proposal, and input the Cardinality 1:CN.

You may ask what the second column CURRENCY in this table is for. We will use this table YCITY to
generate test entries for the table YACCOUNT in another blog. For reasons of simplicity we suppose that the
currency of an account is determined by the city of the respective account: For example, all accounts on
banks in New York have Dollar as the currency. To uniquely assign each city to a currency we write the
respective currency for each city in the same row as the city. Our data generator program will select the city
and currency and one dataset from one row of the table YCITY. When looking at the code of the program
that generates the test data for us, you will understand why and how this simple table will do the same job as
a long CASE construction and keep the code far more readable.

Of course, in a more complex example with a more complete data model we would also add the country,
maybe as a column of the currency table or in a table of its own. But I have decided to keep our example
simple instead of defining as many tables and attributes as we would need in a more real-world example.

Though we want to keep the model simple we will quickly establish another foreign-key-relationship for the
table YCITY. With some experience in data modeling you probably know which relationship is still missing:
We mark the line CURRENCY in the table YCITY, press the Key symbol, and we get the right proposal by
the system: Check table SCURX. So we complete the definition of this check table in the same way as
before when we defined the other check tables. So much for some short considerations on the design of our
check tables

Do not forget to save and activate the table YBANK and YACCOUNT, and there we are: We have defined a
table with four check tables, which also provide an input help for the respective column of the table. You
might ask yourself why there are more input helps than check tables. That there is an input help for the
column LAST_ENTRY results from the fact that every date field gets a calendar as an input help by the
system for free. The input help for the column CATEGORY is based on the fixed values we have input in its
domain

The table SCUSTOM and the table SCURX are already well filled with data, and the tables YBANK and
YCITY will be filled by us in the DATA BROWSER (SE16).

Summary

By now you should be able

 To define database tables

 Including all the attributes

 To define the data elements and domains you need

 To reuse existing data types

 To establish the foreign key relationships with check tables


From a more semantic point of view we created the tables we need in subsequent blogs. Moreover you
should have understood the basics of the concept of a client in the SAP world, what it is good for, how it is
technically realized, and which impact this concept has on the design of database tables. What is still
missing is the content of these tables. And this is what we will provide in the next blog: We will write a little
program of some 70 lines that enables you to create a number of random entries for these tables. Doing this
you will understand once more what is so good about internal tables.

HOW TO DYNAMICALLY CREATE TEST DATA FOR OUR DATABASE TABLE

Since you have to test an application to see if it works, and since you only can test it, when you have some
test data, what we are doing here is an essential step: In this blog of our series (find the whole series here)
we will fill the database table YACCOUNT we have created in the last blog with random entries. We will first
manually provide a small set of test data for the check tables YBANK and YCITY in the Data Browser
(SE16). Using these entries in the check table a program of some 70 lines will create random entries for the
table YACCOUNT. It is these entries that will be the data for the SELECTs we will perform later to provide
data for queries started in a Web Dynpro ABAP interface. You need quite some data in your database tables
if a SELECT with a complex condition should return a reasonable result set. So it will be a good idea to
create some thousands of datasets with the data generating program. In principle, you can choose any
number of entries you want to apart from the fact that for numbers larger than a million the performance of
the program will diminish. So let us better take account of the fact that we just work on a little demo system
and be content with creating some thousands of test dataset. But this discussion already hints one
advantage of the program we are going to write: You can create the number of data sets you want provided
your system has the relevant resources.

The Basic Principle of How to Create the Entries Randomly

The basic principles of how we create the entries for the database table YACCOUNT is simple:
We use a loop and create each dataset separately. We create a random value for each column of the table
in a way that the value fulfills two conditions:

1. The random value meets the semantic and syntactic constraints for the respective column satisfied.

2. It is guaranteed that there is only one dataset with the same composite key: unique-key condition.

Let us consider the different types of semantic conditions for the different columns. First of all we have to fill
the check tables that have no data so fare:

A. Fill the tables YBANK and YCITY with some data. As described in the last blog a line of the table YCITY
contains both the city and the currency assigned to the city. The customers table needs not be filled as it
already contains some hundreds of datasets. The data in these check tables plus the fixed values we have
defined for the column CAT define the constraints that the random values we create for the respective
columns have to meet: The random value for each column has to be a member of the set defined by the
entries in the check table. For example, a valid city has to be part of the table YCITY etc.

B. How do we create one dataset: For columns with a check table we have to make sure that the random
value is an element of the set defined in the check table. How is this done?

1. Load the relevant check table into an internal table.

2. Get the number of entries (NmbEn) of this internal table.

3. Create a random integer z between 1 and NmbEn of the relevant table.

4. Select a line from the internal table randomly by index access with index z.

C. As for the account number we have to create a number that is between 10000000 and 99999999 and to
assure the uniqueness of the composite key. This is achieved by creating the values for BANK and CITY for
a dataset first. Then a random account number is created and only accepted if there is no other dataset in
the internal table with the same composite key. If there is already a dataset with that key, another random
number is created and so on, until a unique key is created.

D. The structure of the table YCITY assures that every account has the currency that is assigned to its city:
The table YCITY provides a unique currency for every city. Once a line is chosen from this table randomly
the city and the currency of the respective dataset are determined at the same time.

E. The balance is simply calculated by creating a random integer between 0 and an upper limit.

F. The entry date is the system date.

G. The values for the category are just random integers between 1 and 3.

So each column of the dataset will contain random data that meet the semantic and syntactic constraints by
the mechanisms described. After a dataset is created it is added to an internal table of the same line type as
the database table YACCOUNT, and the next dataset is created. Once the number of datasets that the user
has provided as a parameter to the program is created the whole internal table is stored in the database.

How to Fill Database Tables in the Data Browser

Let us now look in some more detail at how we fill the tables YBANK and YCITY with values:
The steps to fill a table with values in the Data Browser are simple:

1. Go to the Data Browser (SE16).

2. Select the Create Entries Icon. (second from the left)

3. Type in the values and press the Save button.

4. Press the Reset button.

5. Repeat this step for all values you want to input.

This the button you press at the start screen of the SE16:

And this is what the screen looks like where you input the data:
Input these values in table YBANK:

DEUTSCHE BANK, JP MORGAN, CITIBANK, WASHINGTON MUTUAL, COMMERZBANK, UBS,


UNICREDITO ITALIANO, CITYGROUP, CREDIT SUISSE, BANK OF SCOTTLAND, HYPOVEREINSBANK,
and DIREKTBANK.

Input these pairs of values into the table YCITY:

BASEL, CHF
BOSTON, USD
FRANKFURT, EUR
MILANO, EUR
MUNIC, EUR
NEW YORK, USD,
PARIS, EUR
LONDON, GBP

The program that generates the test data works fine with any other set of banks and cities/currencies. So if
you prefer other banks and towns just type them in. It is understood that the more banks and cities you have
the more diverse will be the generated test data.

As I have told you in the last blog the design of the tables YBANK and SCURX is not as elaborate as it
should be. So a field for a country is missing in both tables. Still we can take advantage of the fact that we
have defined SCURX as a check table for the table YBANK. When inputting the data in this field, we will get
a value help so that we can input only currencies that are defined in table SCURX.

Looking at the Program Itself

Now it is time to have a look at the program that generates the data. I will present the listing of this program
twice. First, I will use a listing with line numbers that make it easy to refer to each line in some explanation.
At the end of the blog I will present a complete listing without line numbers so that you can easily paste it in
your editor.

Let us start by having a look at the relevant data definitions we need:

1 REPORT y_fill_account_table.
2 * internal tables and work areas for database tables.
3 DATA: wa_acc TYPE yaccount,
4 itab_acc LIKE HASHED TABLE OF yaccount
5 WITH UNIQUE KEY mandt acc_num bank city,
6 wa_bank TYPE ybank,
7 itab_bank LIKE STANDARD TABLE OF ybank,
8 wa_city TYPE ycity,
9 itab_city LIKE STANDARD TABLE OF ycity,
10 wa_scustom TYPE scustom,
11 itab_scustom LIKE STANDARD TABLE OF scustom,
12 z TYPE i.
13 * References to different objects of class cl_abap_random_int
14 * and counter for the number of lines of the itabs.
15 DATA: rnd_bank TYPE REF TO cl_abap_random_int,
16 rnd_city LIKE rnd_bank,
17 rnd_scust LIKE rnd_bank,
18 rnd_cat LIKE rnd_bank,
19 rnd_account LIKE rnd_bank,
20 rnd_balance LIKE rnd_bank,
21 bank_count TYPE i,
22 city_count TYPE i,
23 scust_count TYPE i,
24 cat_count TYPE i VALUE 3,
25 max_start_balance type i value 45000,
26 cat_high type i value 3.
27 * How many datasets to create
28 PARAMETERS: numb_acc TYPE i DEFAULT 10.

First of all, there is the definition of an internal table that should hold the data for the database table
YACCOUNT in line 4 and 5 plus the work area of the relevant line type in line 3. A hashed table is a table
that is by a hash algorithm. There is no table index. The position of a row in the memory is calculated by
specifying a key using a hash function that provides a unique value for each table row. If you want to read a
dataset from a large hashed table this is faster by degrees than a search in a standard or a sorted table. In
fact the time you need for a search in a hashed table increases logarithmically with the number of entries in
the internal table. It is because of this advantage that we choose this type of internal table for our program.
Later we have to check if the key of a new dataset we have created randomly is unique. To do this we have
to search if the key of this dataset does already exist in the internal table itab_acc.

We need internal tables and work areas for all check tables of the table YACCOUNT as the random values
should be taken from these tables (lines 6 to 11). As these tables are not very large and only accessed by
index, a standard table suffices. Again you see how easy it is in ABAP to define an internal table that has the
same type as a database table. The references in the lines 15 to 20 are used for objects created by a factory
method of the class cl_abap_random_int. The PARAMETERS statement enables the user to choose how
many datasets should be created. I do not think I need to explain the definition of the integers.

The next lines do some more preparatory work:

29 DELETE FROM yaccount. "delete all lines from the db table yaccount
30 * Fill internal table from relevant db table
31 * and get the number of lines.
32 SELECT * FROM ybank INTO TABLE itab_bank.
33 bank_count = LINES( itab_bank ).
34 SELECT * FROM ycity INTO TABLE itab_city.
35 city_count = LINES( itab_city ).
36 SELECT * FROM scustom INTO TABLE itab_scustom.
37 scust_count = LINES( itab_scustom ).
38 * Get objects that have a method to create a
39 * random number between min and max.
40 *for account categories
41 rnd_cat = cl_abap_random_int=>create( min = 1 max = cat_high ). "
42 * for number of banks
43 rnd_bank = cl_abap_random_int=>create( min = 1 max = bank_count ).
44 * for number of customers
45 rnd_scust = cl_abap_random_int=>create( min = 1 max = scust_count ).
46 * for number of cities
47 rnd_city = cl_abap_random_int=>create( min = 1 max = city_count ).
48 * for account number which has 8 digits
49 rnd_account = cl_abap_random_int=>create( min = 10000000
50 max = 99999999 ).
51 * for initial balance
52 rnd_balance = cl_abap_random_int=>create( min = 0
53 max = max_start_balance ).

In line 29 we delete all lines from the database table YACCOUNT and from line 32 to 37 we load the content
of the database tables YBANK, YCITY and SCUSTOM in the relevant internal tables and get the respective
number of entries in each internal table. In line 41 we create an object that produces a random number
between one and the number of categories. This is done by a public static factory method of the global class
cl_abap_random: Public components of global classes are available in the whole system.
In ABAP it is quite common to provide services as methods of global classes. Surely you remember the
object oriented way to output a table also uses a method of a global class (cf. blog 10 of our series).

In the same way we create random-integer-producer-objects for the three check tables (lines 43 to 47), the
account number and the initial balance of each account.

Next we create the random entries in a way that assures that the syntactic and semantic constraints are met:

54 DO numb_acc TIMES.
55 z = rnd_bank->get_next( ). " Get random number
56 READ TABLE itab_bank INDEX z INTO wa_acc-bank. "Get a bank randomly
57 z = rnd_city->get_next( ).
58 READ TABLE itab_city INDEX z INTO wa_city. "Get dataset from ycity
59 wa_acc-city = wa_city-city. "randomly
60 wa_acc-currency = wa_city-currency. "Currency depends on the city
61 DO. "get an account number that is unique for bank and city
62 z = rnd_account->get_next( ).
63 wa_acc-acc_num = z.
64 READ TABLE itab_acc FROM wa_acc TRANSPORTING NO FIELDS.
65 IF sy-subrc <> 0. "Check if there is already a dataset
66 EXIT. "with the same key in itab_acc
67 ENDIF.
68 ENDDO.
69
70 z = rnd_scust->get_next( ).
71 READ TABLE itab_scustom INDEX z INTO wa_scustom.
72 wa_acc-customer = wa_scustom-id.
73 wa_acc-balance = rnd_balance->get_next( ).
74 wa_acc-category = rnd_cat->get_next( ).
75 wa_acc-last_entry = sy-datum.
76 INSERT wa_acc INTO TABLE itab_acc.
77 ENDDO.
78 INSERT yaccount FROM TABLE itab_acc.
79 WRITE: 'Database Table yaccount successfully filled with ',
80 numb_acc,' datasets' .

By looping numb_acc times it is made sure that we create the number of datasets chosen by the user. It is
within this loop that the dataset is built: We create a random number between 1 and the number of banks in
the check table in line 55. By using this number for an index read from the relevant internal table we get a
bank randomly and move this value to the relevant component of our structure wa_acc. The mechanism
works in an analogous way for each random value from a check table. Just note the advantage resulting
from the fact that each row in the database table YCITY contain a city and the respective currency for the
city: When reading from the table YCITY we get a structure with the components city and currency, and not
just any currency, but the currency assigned to the city. This way it is assured that each account has a
currency that is determined by the city.

Let us now have a closer look at the inner loop from line 61 to line 68. What is this loop for? This loop is to
assure that all lines of the internal table itab_acc will have a unique index. In line 63 the work area wa_acc
contains all the key fields we have filled with random values. The statement READ TABLE itab FROM wa
reads the dataset with the same key as the work area wa from the internal table itab. So we are looking in
the internal table itab_acc if it already contains a dataset with the same key as the work area. If the account
number we have created has produced a composite key that already exists another random account number
should be created. If the account number is part of a unique key that is a key that does not exist so far in the
internal table itab_acc the sy-subrc after reading the table in line 64 is different than zero and the loop is left.
From line 70 to 74 other random values are created and the entry column is filled with the system date.
Lines 78 to 80 are almost self-explanatory: The whole internal table is inserted into the database table and
we output some information as to how many datasets we have created.

And that is it. To use this program yourself create an empty report y_fill_account_table in the package
y_abap_demo and insert the program code provided at the end of this blog by copy and paste.

Running the Program

To check if the program works, run it, insert a number such as for example 1500, and see if you get the
output:

Next we open the Data Browser (SE16), input YACCOUNT and press the leftmost button Content. In the
next window we press the button Number of Entries, and there we are:

The dialog window shows us that our program has done what it is made for. We can close the dialog window
and press the leftmost button Execute to look at the rows in detail:
Summary

What we done in this blog amount to three different things described from different points of view:

1. We have implemented a program that creates the test data we need for the subsequent Web Dynpro
blogs.

2. You have seen a mechanism that you can adapt easily to create test data for your own programs.

3. When explaining the details of the program you have learned some more details about ABAP such
as how to define references to instances of a global class, how services are provides as method of
global classes, how to read lines from internal tables in different ways, and some more details.

The Complete Program Code

REPORT y_fill_account_table.
* internal tables and work areas for database tables.
DATA: wa_acc TYPE yaccount,
itab_acc LIKE HASHED TABLE OF yaccount
WITH UNIQUE KEY mandt acc_num bank city,
wa_bank TYPE ybank,
itab_bank LIKE STANDARD TABLE OF ybank,
wa_city TYPE ycity,
itab_city LIKE STANDARD TABLE OF ycity,
wa_scustom TYPE scustom,
itab_scustom LIKE STANDARD TABLE OF scustom,
z TYPE i.
* References to different objects of class cl_abap_random_int
* and counter for the number of lines of the itabs.
DATA: rnd_bank TYPE REF TO cl_abap_random_int,
rnd_city LIKE rnd_bank,
rnd_scust LIKE rnd_bank,
rnd_cat LIKE rnd_bank,
rnd_account LIKE rnd_bank,
rnd_balance LIKE rnd_bank,
bank_count TYPE i,
city_count TYPE i,
scust_count TYPE i,
cat_count TYPE i VALUE 3,
max_start_balance type i value 45000,
cat_high type i value 3.
* How many datasets to create
PARAMETERS: numb_acc TYPE i DEFAULT 10.
DELETE FROM yaccount. "delete all lines from the db table yaccount
* Fill internal table from relevant db table
* and get the number of lines.
SELECT * FROM ybank INTO TABLE itab_bank.
bank_count = LINES( itab_bank ).
SELECT * FROM ycity INTO TABLE itab_city.
city_count = LINES( itab_city ).
SELECT * FROM scustom INTO TABLE itab_scustom.
scust_count = LINES( itab_scustom ).
* Get objects that have a method to create a
* random number between min and max.
*for account categories
rnd_cat = cl_abap_random_int=>create( min = 1 max = cat_high ). "
* for number of banks
rnd_bank = cl_abap_random_int=>create( min = 1 max = bank_count ).
* for number of customers
rnd_scust = cl_abap_random_int=>create( min = 1 max = scust_count ).
* for number of cities
rnd_city = cl_abap_random_int=>create( min = 1 max = city_count ).
* for account number which has 8 digits
rnd_account = cl_abap_random_int=>create( min = 10000000
max = 99999999 ).
* for initial balance
rnd_balance = cl_abap_random_int=>create( min = 0
max = max_start_balance ).
DO numb_acc TIMES.
z = rnd_bank->get_next( ). " Get random number
READ TABLE itab_bank INDEX z INTO wa_acc-bank. "Get a bank randomly
z = rnd_city->get_next( ).
READ TABLE itab_city INDEX z INTO wa_city. "Get dataset from ycity
wa_acc-city = wa_city-city. "randomly
wa_acc-currency = wa_city-currency. "Currency depends on the city
DO. "get an account number that is unique for bank and city
z = rnd_account->get_next( ).
wa_acc-acc_num = z.
READ TABLE itab_acc FROM wa_acc TRANSPORTING NO FIELDS.
IF sy-subrc <> 0. "Check if there is already a dataset
EXIT. "with the same key in itab_acc
ENDIF.
ENDDO.

z = rnd_scust->get_next( ).
READ TABLE itab_scustom INDEX z INTO wa_scustom.
wa_acc-customer = wa_scustom-id.
wa_acc-balance = rnd_balance->get_next( ).
wa_acc-category = rnd_cat->get_next( ).
wa_acc-last_entry = sy-datum.
INSERT wa_acc INTO TABLE itab_acc.
ENDDO.
INSERT yaccount FROM TABLE itab_acc.
WRITE: 'Database Table yaccount successfully filled with ',
numb_acc,' datasets' .

YOUR FIRST ABAP OBJECTS

After you have learned how to create database tables and ABAP dictionary types in part 14 and part 15 of
our ABAP for Newbies series, now it is a good time to create your first ABAP class, which works with this
data.

Our first goal is an application which allows to display and change the data of a selected customer. In this
blog we will create the necessary ABAP object and in the next one we will create the user interface with Web
Dynpro. The intention is of course not to demonstrate a well thought out, realistic example of object
orientated modelling of a real business problem, which is a science in itself, and would go beyond the scope
of this blog. Here we want to demonstrate how classes can be implemented in ABAP Objects in the form of a
tiny example.

The customer class will have a constructor, a set of public attributes and a save method which stores
changed attributes to the database.
To create an ABAP class go to the ABAP workbench SE80, select "Class/Interface” and enter the name
YCL_CUSTOMER in the input field and hit enter.

Confirm the pop up and enter a description in the next window while leaving the other settings as they are.

Double click the YCL_CUSTOMER class on the left hand side (below "Object Name”) and select the
Attribute tab on the right hand side, to create the attributes of the class. We choose a subset of the
SCUSTOM database columns as attributes of our class. Select the Attributes tab and add the attributes
based on the ABAP dictionary types used for the corresponding database table column:

ID TYPE S_CUSTOMER
NAME TYPE S_CUSTNAME
STREET TYPE S_STREET
POSTCODE TYPE POSTCODE
CITY TYPE CITY
COUNTRY TYPE S_COUNTRY
TELEPHONE TYPE S_PHONENO
EMAIL TYPE S_EMAIL

All attributes should be public Instance attributes, set by the Level and Visibility column. The result looks like
this:

Of course we could also declare the attributes as private and offer setter and getter methods, which might be
better style but let’s keep our example as simple as possible for the moment.

Let’s assume an application which wants to instantiate a customer object knows in most cases already the ID
of the customer (by a query method of a customer manager class for example). Therefore we create a
constructor for the class with the customer ID as an optional parameter. The constructor then gets the data
of the customer and fills the object’s attributes with the values from the database.

To create a constructor click on the Constructor button on the upper right hand corner and the editor for the
already existing but empty constructor method opens.

Click on "Parameters” to add the customer ID as optional (check checkbox in third column!) parameter of the
dictionary type S_CUSTOMER.

Clicking on "Methods” will bring you back to the former view and a double click on the CONSTRUCTOR
method opens the ABAP editor.

In the constructor we will first check if the customer ID has been provided or not, since it was declared as an
optional parameter.

If the ID is available we select the data of the customer with this ID from the database into a structure. The
structure type is available in the ABAP dictionary because the database table SCUSTOM is based on it.
Sometimes people are confused that a table in the database (table=many lines) is represented as structure
(=single line) in the ABAP dictionary, but for the moment lets simply accept this as a fact.

The structure is declared at the top of the method with the data: statement and filled with the Open SQL
statement SELECT…FROM…INTO. The important point is that SQL is directly integrated into ABAP. You
just type in the SQL statements into your ABAP code. The application server automatically gives you the
connection to the database and hides completely the differences between the SQL dialects of different
database which can drive programmers crazy. This is done via the "Open SQL” called layer in the application
server, offering a unified SQL which is translated into the specific SQL dialect of the currently used database,
making ABAP programming independent of the database vendors.

Then the attributes of the object instance are filled with the result we got from the database. A column, the so
called component of a structure can be directly accessed with the "-" separator, for example the name of the
customer is available as S_CUSTOMER-NAME.
The whole listing of the constructor method looks like:

METHOD constructor.

* declaration of a structure matching the database table


DATA: s_customer TYPE scustom.

* check if ID parameter has been supplied


IF id IS SUPPLIED.

* get the data of the customer from the database


SELECT SINGLE * FROM scustom INTO s_customer WHERE id = id.

* fill the object's attributes with the data


me->id = id.
me->name = s_customer-name.
me->street = s_customer-street.
me->postcode = s_customer-postcode.
me->city = s_customer-city.
me->country = s_customer-country.
me->telephone = s_customer-telephone.
me->email = s_customer-email.

ENDIF.

ENDMETHOD.

Type in the coding (and I recommend to type it rather than cut and paste), save and check the syntax of the
method with the check button. If no errors occur you can activate the class with the button next to the check
button.

A special feature of the ABAP workbench is that it contains a test environment which you can use out of the
box to test and execute your ABAP coding directly without the need of writing a test program. After you have
successfully activated your class click on the test button and the workbench will display the following:

This screen is a built in test feature of the ABAP workbench. It automatically generates a test UI for an ABAP
class based on its methods and attributes. The first screen offers all static public methods of a class, in our
case only the constructor with its single parameter. Choose for example 00000001 as customer ID (1.) and
click the instantiate button (2.). An object instance is created and its attributes are displayed:
We see the first customer in our dataset is a company named SAP AG, located in Walldorf, Germany.
Unfortunately the data is already outdated. Last year the city of Walldorf renamed the Neurottstrasse to
Dietmar-Hopp-Allee in honour of the founder and former CEO of SAP. Although we can change the street
name due to the public attributes we still need a method which allows us to save the changed data to the
database.

To create this new method go back to the class builder with the green back button click the Methods tab and
go into change mode. Create a new method SAVE as public instance method. A double click on SAVE leads
you to the editor. The code to save the current attribute values to the database is pretty simple:

METHOD save.

* declaration of structure
DATA: s_customer TYPE scustom.

* fill structure with current attribute values


s_customer-id = me->id.
s_customer-name = me->name.
s_customer-street = me->street.
s_customer-postcode = me->postcode.
s_customer-city = me->city.
s_customer-country = me->country.
s_customer-telephone = me->telephone.
s_customer-email = me->email.

* update the data in the DB


MODIFY scustom FROM s_customer.

ENDMETHOD.

It is necessary to put the current attribute values into a structure first, because the SQL statements for
updating or modifying database tables need the values in a structure matching the database table structure.
The MODIFY keyword is the Open SQL statement for either updating an existing dataset or creating a new
one. (We could have chosen here also the UPDATE statement, but we want to enhance the class later also
with the capability to create and save new entries into the database, therefore we chose the MODIFY.) Enter
the code into the method and activate the class.

If you now click the Test button and instantiate the customer 00000001, the test environment will display also
the new SAVE method.
Now we can correct the address to Dietmar Hopp Allee 16 (2.). Check the Upper/lower case active checkbox
(1.), otherwise the data will be converted to uppercase and click on the clock/run icon (3.) right to the SAVE
method.

Now the data is updated and if you call the test again or look into the database table with the transaction
SE16 it will display the new address.

Although the integrated test capabilities of the ABAP workbench are quite useful for test purposes, we want
to have a "real” application example in the end, of course. With our first ABAP class, we can start with
creating a user interface in Web Dynpro, which allows to display, change and save customer addresses in
the next blog.

STARTING WITH WEB DYNPRO FOR ABAP


This blog of our ABAP Trial Version for Newbies series should be of interest to everybody who is working in
the ABAP environment since Web Dynpro is SAP's main UI technology for currently developed and future
applications. With Web Dynpro for ABAP SAP offers this mighty UI framework also for the large community
of ABAP developers and it's probably a good advice for every ABAP developer to start exploring the Web
Dynpro development model as soon as possible. With the SAP NetWeaver 7.0 ABAP Trial Version we have
the perfect environment at hand to do this.

The best way to learn is by doing, so we will create a small Web Dynpro application which illustrates the
basic idea behind the Web Dynpro programming model.

In our first small Web Dynpro example we use the YCL_CUSTOMER ABAP objects class we created in the
last blog of the series. The Web Dynpro application should display, change and save the data of a given
customer. This small example will already demonstrate the separation of the UI layer from the core logic. The
Web Dynpro layer uses the ABAP class but does not know anything about the way the class retrieves and
stores the data while the customer class does not care if it is used by an application with a web user
interface or called by other backend services.

Create your first Web Dynpro Component

The core of a Web Dynpro project is the Web Dynpro component. The component contains the visible parts
of the UI and the logic which steers its behavior. We start in the ABAP Workbench (SE80) with creating a
new Web Dynpro component. Select "Web Dynpro Comp. /Intf." from the drop down list and enter the name
for the new component for example "YWD_CUSTOMER".
Hit enter and confirm the pop up.

You can enter a description in the next window while leaving the other options untouched. Also the "Object
Directory Entry" popup of the transport system should already be familiar to you. It's up to you if you want to
create the component simply as local object or to put it into a transportable package.

The workbench has now created the Web Dynpro component with a component controller, which is the
backbone of our WD component, a component interface (which will be explained later) and a window, which
is the place where the visible parts of a Web Dynpro component - the views - will later be arranged and
where it can be defined how they will be displayed.

Model View Controller and the Context

The Web Dynpro model is based on the famous Model-View-Controller paradigm, used in almost all modern
UI frameworks. The visible layout is defined by views, which contain the arrangement of UI elements
(buttons, tables, input fields, etc...). The invisible parts, which steer the behavior of the UI, handle the data,
contain event handlers etc. are the so called controllers with the component controller being the core
controller of the component. Its role is to handle and retrieve the data from the business logic or model which
is in our case the YCL_CUSTOMER class.

We define the kind of data the WD component should handle in the component controller's context. Each
Web Dynpro controller contains a hierarchical structure called context to store data. The hierarchy contains
nodes as structuring elements and attributes for the data.

Select the component controller and go to the "Context" tab.


The context is still empty, just the root node named "CONTEXT" is visible. We want our Web Dynpro
component to display the data of a customer. Therefore we define a context structure which contains the
attributes of our customer class YCL_CUSTOMER.

Right click on the "CONTEXT" root node and select "Create - Node" (Be sure to be in change mode).

The upcoming popup allows us to create a context structure based on ABAP dictionary data types. This
comes in handy since the attributes of our customer class are based on data types already defined in the
ABAP dictionary as columns of the SCUSTOM structure.

Therefore we choose "SCUSTOM" as "Dictionary structure" for the new node named "CUSTOMER".

Before confirming click the "Add Attribute from Structure" button!


In the next pop up select

ID
NAME
STREET
POSTCODE
CITY
COUNTRY
TELEPHONE
EMAIL

and confirm. The context of the component controller now contains a context node named "CUSTOMER"
with attributes corresponding to the attributes of the SCUSTOM structure. The context is now able to store
the data of one customer and should look like this:
Data in the View

Before we continue with the implementation of the necessary code to retrieve the data of a customer into the
context, let’s first create a view with the UI elements so we can test out the Web Dynpro component in an
early stage and see how it works in general.

Right click the WD component name YWD_CUSTOMER at the left hand side and select "Create - View":

Enter "CUSTOMER_VIEW" as name and confirm. The workbench shows the layout tab of the newly created
view. Because the layout preview tab displays the preview via HTTP a browser user/password popup might
turn up. Use your system user (user: bcuser pwd: minisap) to start the preview (which is still empty).
A real world application contains usually several views, each for a specific task with its specific data and
interactive UI elements and event handlers. Therefore Web Dynpro creates in addition to the component
controller for each view another controller, the view controller. The task of the view controller is to handle
only the data and user actions of its view, while the component controller is responsible for the whole data of
the Web Dynpro component and the communication with the business logic. In our simple case we have only
one view and therefore the view controller needs the same data as the component controller. To display the
data the view needs it in its own context. The data transfer is done via context mapping between the two
controller contexts.

Nodes of different contexts can be mapped if they have the same structure. The framework ensures that
mapped context nodes always contain the same values at runtime.

To define the mapping between the component controller and the view controller go to the context tab of the
view. The tab displays the context of the view controller on the left hand side and the context of the
component controller at the right hand side. Now drag and drop the CUSTOMER node from the component
controller context to the view controller context. This will create a new context node of the same structure in
the view controller which is already mapped.
You will be asked if you really want to copy the node to the view controller and map it. Confirm this and you
should end up with a CUSTOMER context node in the view controller context which is mapped to the
component controller context.

Defining the View Layout

Now we want to create the layout of the view which should display the customer data out of the context. A
view displays data and offers user interaction with UI elements. These UI elements are bound to the nodes
and attributes of the view controller's context.

Switch back to the layout tab. You see the empty view area and the available UI elements. Select the
"Standard Container" UI element library from the bottom of the list. First we need a group UI element as
container for several input fields, labels, and buttons. The Group UI element is the left one in the first row of
the Standard Container elements. Drag and drop it onto the layout area (1) and the group element will also
appear in a hierarchical view at the right hand side with a caption as sub element (2). (If you can’t drag and
drop right click on ROOTUIELEMENTCONTAINER then click Insert Element and select Group from the Type
list.) This tree displays all UI elements of a view under the main container called the
ROOTUIELEMENTCONTAINER. Since some UI elements can contain other UI elements this can become a
pretty complex tree structure. For example the Group UI element is such a container element which already
contains a caption element.

New UI elements can either be added to the view by drag and drop or in the tree at the right hand side with a
right mouse click. We want to display all attributes of the customer in text input fields. Instead of adding each
input field individually we use a wizard which creates the input fields with correct labels and binds them to the
customer context node of the view controller.

Right click onto the GROUP in the tree and choose "Create Container Form" from the menu.
In the upcoming "Create Context Binding" popup click on "Context" (1) and select the CUSTOMER node (2)
in the "Choose Context" popup and confirm.

Confirm again the selection in the "Create Context Binding" pop up.

The wizard has created a label and an input field for each attribute of the CUSTOMER node and it has also
created the binding between the context node attributes and the input fields. This means that any data which
is stored in the context is automatically displayed in the input fields and any user input in the fields will be
automatically stored in the context.

You see the labels and input fields in the layout preview. If you select a UI element in the tree structure the
properties of the selected UI element are displayed below in a table and can be changed. Let’s use this to
clean up the layout.

First select the "CAPTION [Header]" element below the group element and set its text property to "Customer
Data". Next select the GROUP element itself and change the "Layout" property from "FlowLayout" to
"GridLayout". Change further down in the property list the "ColCount" property to 2 and save the view. The
layout should now look tidier with the labels in the first column of each row.
Let’s have a look how our almost finished Web Dynpro component looks like in this state. We haven't
implemented the data retrieval yet, therefore it will not display any data but the general layout is already fixed
and I assume you are curious by now how the whole thing looks in a browser.

To be visible we have to put the view into the window of the component. The window is a container for views.
Real applications contain several views and sometimes also several windows. Therefore it is necessary to
declare which view belongs to which window.

Double click on the Window YWD_CUSTOMER (1) (By default the window of a WD component has the
same name as the component itself but it is another kind of object). The still empty window structure is now
displayed on the right hand side.

Now drag and drop the view CUSTOMER_VIEW from the left hand side to the YWD_CUSTOMER window in
the window structure (2). You can check if the view has been included by clicking the triangle left from the
window to display its structure.

A First Test

Now activate the whole project by selecting the YWD_CUSTOMER component in the object tree with a
double click and clicking on the activation button (sevenths icon in the icon row on top of the workbench). A
popup appears with all inactive objects you have created in the component. All should be selected. Confirm
the popup.

The last thing we need to see our example in a browser is a new entity called Web Dynpro application. So far
we have created a Web Dynpro Component, which contains the core Web Dynpro entities and defines our
UI. The Web Dynpro Application is the handle which allows to start the component.

Right click on the YWD_CUSTOMER component and select "Create - Web Dynpro Application". You can
add a description to the WD Application. Save the WD Application with the save button on top of the
workbench. Since a WD Application is also a transportable object select a package or save it as local object.

Now a new node "Web Dynpro Applications" has appeared in the object tree with the YWD_CUSTOMER
application beneath it. You can test the WD Application with the WD component by right mouse click on the
application object (1) and selecting "Test".

The browser will be started and tries to call the Web Dynpro application which itself instantiates the
YWD_CUSTOMER Web Dynpro component and displays its window with the view. Since the application is
running on the server you have to log on with your user credentials (user: bcuser pwd: minisap). (Don't worry
if a time out error occurs. This just means that the default 60sec limit for a HTTP request are not sufficient to
compile the Web Dynpro framework on the server, which might be necessary if it is the first time you try to
run a Web Dynpro application. Just try again until the view appears. Later request will be much faster.)

The browser should display the view:

OK, this probably doesn't knock your socks off but shows already some important features. For example the
label texts are the correct ones retrieved from the ABAP dictionary data types. This works directly out of the
box without any development effort. The texts are also language dependent. If you change the last two
characters in the URL from "EN" to "DE" the view will be displayed with German texts for the labels (the Trial
version contains only English and German texts, but real systems contain all kinds of languages).

There's also a value help available for the Customer Number, although we have nothing implemented for
that. The Web Dynpro framework displays automatically a value help if one is defined in the ABAP dictionary
for the data type which is used for the context attribute that is bound to the input field. In the case of the
Customer Number there is a rather complex value help defined for the data type SCUSTOM-ID as part of the
data types used in standard SAP training workshops. Experienced ABAP developers will be glad to hear that
their existing value help defined for GUI based transaction is fully usable in Web Dynpro.

Bringing Life into the Component

Let's continue with the implementation of the code that displays and allows to change customer data. We
want to add a button and if a user has entered or selected a customer ID the view should display the address
data of the customer.

As mentioned, retrieving data from the business logic or model is the task of the component controller. Select
the component controller in the workbench. First we add a reference variable of our YCL_CUSTOMER class
as attribute to the component controller. Select the "Attributes" tab and enter the attribute CUSTOMER of the
type (reference) YCL_CUSTOMER:

The component controller has to offer a method which creates a customer object for a given customer ID and
fills its context structure with the attributes of the customer.

Switch to the Methods tab of the component controller and create a new method READ_CUSTOMER. A
double click on the method names opens the ABAP editor.

Implement the following code into the method:

METHOD read_customer .

DATA: cnode TYPE REF TO if_wd_context_node,


custom_id type scustom-id.

* get reference of CUSTOMER context node


cnode = wd_context->get_child_node( 'CUSTOMER' ).

* get current value of the ID attribute


cnode->get_attribute( EXPORTING name = 'ID'
IMPORTING value = custom_id ).

* instantiate the customer object for the ID


CREATE OBJECT wd_this->customer EXPORTING id = custom_id.

cnode->set_attribute( name = 'ID' value = wd_this->customer->id ).


cnode->set_attribute( name = 'NAME' value = wd_this->customer->name ).
cnode->set_attribute( name = 'STREET' value = wd_this->customer->street ).
cnode->set_attribute( name = 'POSTCODE' value = wd_this->customer->postcode ).
cnode->set_attribute( name = 'CITY' value = wd_this->customer->city ).
cnode->set_attribute( name = 'COUNTRY' value = wd_this->customer->country ).
cnode->set_attribute( name = 'TELEPHONE' value = wd_this->customer->telephone ).
cnode->set_attribute( name = 'EMAIL' value = wd_this->customer->email ).

ENDMETHOD.

First we declare the variables for a reference to a context node and for the ID of a customer.
Next we retrieve the reference of the CUSTOMER node from the controller's context. We use the node's
"get_attribute" method to get the current value of the "ID" context attribute.
With the ID we instantiate the CUSTOMER object with the CREATE statement. WD_THIS is the self
reference of the component controller. Therefore the customer object reference we have added as class
attribute to the component controller can be accessed as WD_THIS->CUSTOMER.

Finally we set the context's attributes with the values of the current customer object.

This method should be called if the user clicks a button. To add the button to the view select the
CUSTOMER_VIEW and go to the layout tab. The button is the first element in the "Standard Simple" library
of UI elements. Drag and drop the button to the view. Select it in the tree hierarchy and set its text property to
"Get Customer" (1).

The button has to trigger an action. To create such an action click on the create button next to the "onAction"
property (2):

In the upcoming pop up name the new action GET_CUSTOMER and confirm. A double click on the newly
created action name in the Property table (3) will open the ABAP editor for the action's method handler
ONACTIONGET_CUSTOMER.

This event handler is a method of the view controller because the button belongs to the view. Remember that
the view controller and the component controller are two different objects. It is not possible to link an action
of a button directly to a component controller. Handling the events of UI elements of a view is always the task
of the view controller. What we have to do now is simply calling the component controller's
READ_CUSTOMER method from the event handler in the view controller. This is quite straightforward since
every view controller has access to the reference of the component controller. Therefore our event handler
consists of a single line of code:

METHOD ONACTIONGET_CUSTOMER .

* call the component controllers read_customer method


wd_comp_controller->read_customer( ).

ENDMETHOD.

Save and activate everything and test the WD application again. If you type in a customer number, for
example 00000003 the data of the corresponding customer will be displayed:
Because this blog got longer than expected, I leave the last part, adding the functionality to save changed
address data for you as homework. But you have everything you need to know at hand. Create a new
SAVE_CUSTOMER method in the component controller in which you take the current context attribute
values, put them in the customer object's attributes and call the save method of the customer object.

Add a button to the view, which triggers an action that calls the SAVE_CUSTOMER method of the
component controller and you are done.

Conclusion

If this was your first encounter with Web Dynpro you probably think by now that the Web Dynpro framework
is quite complex. A lot of new entities appeared and most of the concepts are new and it takes some time to
get used to everything. The learning curve might be steeper than in other more low level UI environments,
where you get first results faster. But you might have noticed something during this example: You never
cared about any HTML, JavaScript, HTTP or browser issues. It was never necessary to think what kind of
HTML data or script has to be sent to the browser to create a specific effect. All you thought about was really
the user interface of your application. Where a button should be placed, which part of the business data
should be displayed, which action should be triggered by a button and so on. These kind of questions can be
complex and sometimes hard to solve. Creating good user interfaces is still an art. But when you deal with
this art, you should concentrate on what your UI should look like and what it should do and not what happens
during a HTTP request or what kind of effect a browser cache can have or if a specific JavaScript statement
is supported by all browsers.

This is the fundamental feature of the Web Dynpro framework. Concentrate on the user interface and not on
the underlying rendering technologies.
www.sap.com

© 2015 SAP SE or an SAP affiliate company. All rights reserved.


No part of this publication may be reproduced or transmitted in any form
or for any purpose without the express permission of SAP SE or an SAP
affiliate company.
SAP and other SAP products and services mentioned herein as well as their
respective logos are trademarks or registered trademarks of SAP SE (or an
SAP affiliate company) in Germany and other countries. Please see
http://www.sap.com/corporate-en/legal/copyright/index.epx#trademark for
additional trademark information and notices. Some software products
marketed by SAP SE and its distributors contain proprietary software
components of other software vendors.
National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for
informational purposes only, without representation or warranty of any kind,
and SAP SE or its affiliated companies shall not be liable for errors or
omissions with respect to the materials. The only warranties for SAP SE or
SAP affiliate company 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.
In particular, SAP SE or its affiliated companies have no obligation to pursue
any course of business outlined in this document or any related presentation,
or to develop or release any functionality mentioned therein. This document,
or any related presentation, and SAP SE’s or its affiliated companies’
strategy and possible future developments, products, and/or platform
directions and functionality are all subject to change and may be changed by
SAP SE or its affiliated companies at any time for any reason without notice.
The information in this document is not a commitment, promise, or legal
obligation to deliver any material, code, or functionality. All forward-looking
statements are subject to various risks and uncertainties that could cause
actual results to differ materially from expectations. Readers are cautioned
not to place undue reliance on these forward-looking statements, which
speak only as of their dates, and they should not be relied upon in making
purchasing decisions.

You might also like