Beginner

Hello World in ABAP

Your first ABAP program - the classic Hello World example running on Node.js via the open-abap transpiler

Every programming journey starts with Hello World. While ABAP traditionally requires SAP system access, the open-abap project lets us run ABAP code on Node.js by transpiling it to JavaScript.

The Code

Create a file named hello.abap:

1
2
REPORT zhello.
WRITE 'Hello, World!'.

That’s it - just two lines for ABAP Hello World!

Understanding the Code

Let’s break down this simple program:

REPORT Statement

1
REPORT zhello.
  • REPORT - Declares this is an executable program (report)
  • zhello - The program name (Z prefix indicates custom/customer namespace in SAP)
  • . - ABAP statements end with a period

In SAP systems, program names must start with Z or Y for customer-developed programs. The standard SAP namespace uses other prefixes.

WRITE Statement

1
WRITE 'Hello, World!'.
  • WRITE - Outputs text to the list buffer
  • 'Hello, World!' - A character literal (string)
  • . - Statement terminator

Unlike most languages that print directly to console, ABAP writes to a “list” - a buffer that displays when the program finishes. This design comes from ABAP’s origins as a report generator.

Running with Docker

Running ABAP outside SAP requires the open-abap transpiler. Here’s a Docker command that sets up everything:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Pull the Node.js image
docker pull node:20

# Run the ABAP program
docker run --rm -v $(pwd):/work node:20 sh -c '
cd /work && mkdir -p abap_project/src && cd abap_project && \
npm init -y >/dev/null 2>&1 && \
npm install --silent @abaplint/transpiler-cli @abaplint/runtime 2>/dev/null && \
echo "{\"input_folder\":\"src\",\"output_folder\":\"output\",\"write_unit_tests\":false,\"options\":{\"ignoreSyntaxCheck\":true}}" > abap_transpile.json && \
echo "{\"global\":{\"files\":\"/src/**/*.*\"},\"syntax\":{\"version\":\"v702\",\"errorNamespace\":\".\"}}" > abaplint.json && \
cp /work/hello.abap src/zhello.prog.abap && \
echo "<?xml version=\"1.0\"?><abapGit version=\"v1.0.0\"><asx:abap xmlns:asx=\"http://www.sap.com/abapxml\"><asx:values><PROGDIR><NAME>ZHELLO</NAME><SUBC>1</SUBC></PROGDIR></asx:values></asx:abap></abapGit>" > src/zhello.prog.xml && \
./node_modules/.bin/abap_transpile >/dev/null && \
echo "import runtime from \"@abaplint/runtime\";globalThis.abap = new runtime.ABAP();await import(\"./output/zhello.prog.mjs\");" > run.mjs && \
node run.mjs && cd /work && rm -rf abap_project'

Understanding the Docker Command

This command does several things:

  1. Mounts current directory - -v $(pwd):/work makes your hello.abap available
  2. Creates project structure - Sets up npm project with required dependencies
  3. Installs transpiler - @abaplint/transpiler-cli converts ABAP to JavaScript
  4. Creates config files - Sets up the transpiler configuration
  5. Adds abapGit metadata - The XML file describes the ABAP object
  6. Transpiles and runs - Converts ABAP to JS and executes it

The open-abap transpiler requires files in abapGit format (.prog.abap for programs, with matching .xml metadata).

Expected Output

Hello, World!

How open-abap Works

The open-abap project transpiles ABAP to JavaScript:

ABAP Source → Transpiler → JavaScript → Node.js Runtime

For example, our WRITE statement becomes:

1
abap.statements.write(abap.CharacterFactory.get(13, 'Hello, World!'));

The @abaplint/runtime package provides the abap object with all ABAP statement implementations.

Alternative: Simplified Runner Script

For repeated development, create a runner script. Save as run_abap.sh:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
# run_abap.sh - Run ABAP files using open-abap transpiler

ABAP_FILE=${1:-hello.abap}
PROJECT_DIR=$(mktemp -d)

cd "$PROJECT_DIR"
npm init -y >/dev/null 2>&1
npm install --silent @abaplint/transpiler-cli @abaplint/runtime

mkdir -p src
cat > abap_transpile.json << 'EOF'
{"input_folder":"src","output_folder":"output","write_unit_tests":false,"options":{"ignoreSyntaxCheck":true}}
EOF

cat > abaplint.json << 'EOF'
{"global":{"files":"/src/**/*.*"},"syntax":{"version":"v702","errorNamespace":"."}}
EOF

# Extract program name from REPORT statement
PROG_NAME=$(grep -i "^REPORT" "$OLDPWD/$ABAP_FILE" | awk '{print tolower($2)}' | tr -d '.')
PROG_NAME=${PROG_NAME:-zhello}

cp "$OLDPWD/$ABAP_FILE" "src/${PROG_NAME}.prog.abap"
cat > "src/${PROG_NAME}.prog.xml" << EOF
<?xml version="1.0"?><abapGit version="v1.0.0"><asx:abap xmlns:asx="http://www.sap.com/abapxml"><asx:values><PROGDIR><NAME>${PROG_NAME^^}</NAME><SUBC>1</SUBC></PROGDIR></asx:values></asx:abap></abapGit>
EOF

./node_modules/.bin/abap_transpile >/dev/null 2>&1

cat > run.mjs << EOF
import runtime from "@abaplint/runtime";
globalThis.abap = new runtime.ABAP();
await import("./output/${PROG_NAME}.prog.mjs");
EOF

node run.mjs

cd "$OLDPWD"
rm -rf "$PROJECT_DIR"

Usage:

1
2
chmod +x run_abap.sh
./run_abap.sh hello.abap

ABAP Syntax Basics

Even in Hello World, we can explore ABAP’s distinctive syntax:

Statement Structure

1
KEYWORD parameter1 parameter2.
  • Keywords are uppercase (though ABAP is case-insensitive)
  • Statements end with periods
  • Multiple statements per line are allowed but discouraged

Variations on WRITE

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
REPORT zhello.

" Simple output
WRITE 'Hello'.

" New line
WRITE / 'World'.

" Output with positioning
WRITE AT 10 'Positioned'.

" Multiple items
WRITE: 'A', 'B', 'C'.

" Using colon for repeated keyword
WRITE: / 'Line 1',
       / 'Line 2',
       / 'Line 3'.

The colon (:) after WRITE allows multiple outputs with a single keyword - a common ABAP pattern.

Comments

1
2
3
4
" This is a comment (modern style)
* This is also a comment (classic style - must be at line start)

WRITE 'Hello'.  " Inline comment

Data Types Preview

ABAP has rich data types built for business applications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
REPORT zdata_demo.

" Text types
DATA lv_char TYPE c LENGTH 10.    " Fixed-length character
DATA lv_string TYPE string.       " Variable-length string

" Numeric types
DATA lv_int TYPE i.               " Integer
DATA lv_packed TYPE p DECIMALS 2. " Packed decimal (for money)

" Date and time
DATA lv_date TYPE d.              " Date (YYYYMMDD)
DATA lv_time TYPE t.              " Time (HHMMSS)

lv_string = 'Hello, World!'.
WRITE lv_string.

The ABAP List System

WRITE doesn’t immediately print - it writes to a “list buffer”:

1
2
3
4
5
6
7
REPORT zlist_demo.

WRITE 'First line'.
WRITE / 'Second line'.  " / creates new line
WRITE / 'Third line'.

" The list displays when the program ends

This design enables:

  • Scrollable reports
  • Print-ready output
  • Page headers/footers
  • Interactive reports (in SAP GUI)

String Templates (Modern ABAP)

ABAP 7.40+ introduced string templates:

1
2
3
4
5
6
REPORT ztemplate.

DATA(lv_name) = 'World'.
DATA(lv_greeting) = |Hello, { lv_name }!|.

WRITE lv_greeting.

Note: String templates use | delimiters and { } for embedded expressions.

Real SAP vs open-abap

Feature comparison:

FeatureSAP Systemopen-abap
Core ABAP syntaxFullMost of 7.02+
Database (Open SQL)FullSQLite/PostgreSQL
WRITE statementYesYes
ALV gridsYesNo
SAP GUI dialogsYesNo
Web servicesYesPartial
Unit testsABAP UnitYes

open-abap is excellent for:

  • Learning ABAP syntax
  • Algorithm practice
  • Unit testing logic
  • Running on platforms like Exercism

For full SAP development, you’ll need SAP system access.

Getting SAP Access

For complete ABAP development:

SAP Learning Hub

  • Free trial systems from SAP
  • Web-based access
  • Good for certification prep

ABAP Platform Trial (Docker)

  • Full SAP system in Docker
  • Requires 16GB+ RAM
  • Large download (~23GB)
1
2
docker run --stop-timeout 3600 -it --name a4h -h vhcala4hci \
  sapse/abap-cloud-developer-trial:latest

SAP BTP Trial

  • Cloud-based ABAP environment
  • Free tier available
  • Modern ABAP Cloud development

Historical Note

ABAP was created in 1983 by Gerd Rodé at SAP. The name originally stood for “Allgemeiner Berichts-Aufbereitungs-Prozessor” (German for “General Report Preparation Processor”), reflecting its origins as a report generation language for SAP R/2 mainframes.

The WRITE statement and list buffer concept come directly from this report-generation heritage - ABAP was designed to create formatted business reports, not interactive console applications.

Today, ABAP powers critical systems at 90% of Fortune 500 companies, processing trillions of dollars in transactions annually.

Next Steps

Continue to Variables and Data Types to learn about ABAP’s rich type system designed for business applications.

Key Takeaways

  1. REPORT declares an executable program
  2. WRITE outputs to the list buffer
  3. Periods terminate all ABAP statements
  4. Z/Y prefix indicates customer namespace
  5. open-abap transpiles ABAP to JavaScript for Node.js
  6. ABAP’s list buffer comes from its report-generation origins
  7. Modern ABAP (7.40+) includes string templates and inline declarations

Running Today

All examples can be run using Docker:

docker pull node:20
Last updated: