NextLytics Blog

Migration von ABAP-Programmen in eine Cloud-Umgebung

Geschrieben von Stefan Lindner | 09.10.2025 09:00:01

Die Herausforderung: Was passiert mit bestehenden ABAP-Programmen in der Cloud?

Im Rahmen einer Migration wollen oder müssen Sie Ihre SAP-Lösung (ERP oder BW) in eine Cloud-Umgebung bringen (S/4HANA Public Cloud, BTP ABAP Environment, SAP BW-Bridge) und stellen sich die Frage, was mit ABAP-Programmen passieren soll, deren Funktionen weiterhin benötigt werden.
Ein SAPGUI mit auf Dynpros basierenden Dialogen gibt es nicht mehr und damit auch keine Selektionsbildschirme für ABAP-Programme.

Insbesondere müssen Lösungen für ABAP-Programme mit Selektionsbildschirmen gefunden werden, die in der neuen Umgebung einen ähnlichen Umgang (Eingabe, Speicherung, Änderung und Aufruf) ermöglichen – und das ohne auf SAPUI5 oder SAP Fiori umsteigen zu müssen.

Eine Entwicklung mit SAPUI5 und SAP Fiori ist grundsätzlich möglich, bedeutet aber einen erhöhten Aufwand bei der Implementierung, die Einarbeitung in eine neue Entwicklungsumgebung und die Einbindung in das Fiori-Launchpad.

In diesem Artikel wird eine Möglichkeit vorgestellt, um mit Hilfe der Cloud-Version von NextTables Selektionsvarianten zu pflegen und dann für ausgewählte Varianten die bewährte  Funktionalität direkt aus NextTables heraus aufzurufen.
Auch für den Aufruf innerhalb einer Prozesskette wird eine Lösung vorgestellt.

Welcher Lösungsansatz ermöglicht die Weiterverwendung bestehender ABAP-Programme?

Der folgende Ansatz zeigt, wie ABAP-Kode weitgehend beibehalten werden kann.

  • Die im ABAP-Programm verwendeten Selektionen, abgelegt als Varianten, werden in 1 oder 2 Datenbank-Tabellen gespeichert. Für Selektions-Optionen werden 2 Tabellen benötigt.
  • Die Tabellen werden mit NextTables gepflegt.
  • Das ehemalige ABAP-Coding wird in eine Klasse übernommen und lässt sich direkt aus NextTables heraus für eine Variante aufrufen. Dabei müssen kleinere Unterschiede zwischen ABAP und ABAP Cloud beachtet werden. 
  • Fehlermeldungen werden als Meldungsboxen angezeigt.

Soll der Prozess im Hintergrund laufen, kann die Klasse unter Umständen auch aus einer Prozesskette heraus aufgerufen werden und greift auf die Tabellen mit den Varianten zu.

Das ‘Look and Feel’ der vorgestellten Lösung ähnelt dem der alten Lösung mit ABAP-Programmen und bietet dieselbe Funktionalität.

Anwender müssen nicht das Fiori-Launchpad benutzen, NextTables ist direkt über eine URL erreichbar.

Die Entwickler können weiter ihre ABAP-Kenntnisse nutzen und müssen nicht auf die Frontend-Entwicklung mit Fiori umsteigen.

Der Selektionsbildschirm des zu migrierenden Programms mag wie folgt aussehen:

 

    Selektionsbildschirm im alten System (Dynpro)

Es gibt mehrere Einzelfelder, Feldpaare, einen Schalter, einen Bereich und eine Selektionsoption.

Bis auf die Selektionsoption kann man alle zur Selektion benötigten Felder in eine Tabelle aufnehmen. Um die Möglichkeit einer Selektionsoption abzuspeichern, benötigt man eine  weitere Tabelle.

In NextTables kann man dann den Item-Tabellentyp wählen, um beide Tabellen zu verbinden.

 

    Erfassen einer Variante in der neuen Lösung in NextTables.

Für die zweite Variante werden die Selektionsoptionen in einer zweiten Tabelle gepflegt. Diese ist durch die Beziehung auf die Variante 2 vorgefiltert. Zu dieser lassen sich Untervarianten mit unterschiedlichen Selektionen  anlegen.
Über eine zusätzlich eingefügte Schaltfläche lässt sich die Verarbeitung der selektierten Variante starten.
Gegebenenfalls werden am Ende Meldungen zur Verarbeitung angezeigt.
Um die Verarbeitung im Hintergrund laufen zu lassen, kann ein kundeneigener Prozesstyp genutzt werden. Dieser ruft eine Klasse mit der angegebenen Variante auf.

Schritt für Schritt zur Cloud: so läuft die Implementierung ab

Domänen, Datentypen und Tabellen.

Zuerst werden einige Domänen und Datentypen angelegt.

Data element

Domain

Type

Length

Description

ZSL_VARIANT

ZSL_VARIANT

NUMC

4

Selection variant

ZSL_SUBVAR

ZSL_SUBVAR

NUMC

3

Sub-variant for selection

ZSL_SIGN

ZSL_SIGN

CHAR

1

Sign

ZSL_OPTION

ZSL_OPTION

CHAR

2

Possible select option

ZSL_OBJNM

ZSL_OBJNM

CHAR

20

Object name

RSSOURSYSID

RSSOURSYSID

CHAR

2

Source system ID

/BI0/OIMANDT

/BI0/OIMANDT

NUMC

3

Client

ZSL_ATTR

ZSL_ATTR

INT4

10

Attribute value

ZSL_BOOL

ZSL_BOOL

CHAR

1

Flag

ZSL_DATEFROM

ZSL_DATEFROM

DATS

8

Date from

ZSL_DATETO

ZSL_DATETO

DATS

8

Date to

 

Das Definieren von Domänenfestwerten für ZSL_SIGN und ZSL_OPTION erleichtert die Eingabe und vermeidet Fehler.

 Einige wichtige Domänen.

 

Die Einzelwerte der Selektion werden in der Tabelle ZSL_PAR gespeichert.

@EndUserText.label : 'Parametzer selection header'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
Define table zsl_par {
 
Key variant : zsl_variant not null;
Qsys        : rssoursysid;
Client      : mandt;
Object1     : zsl_objnm;
Object2     : zsl_objnm;
Attr1       : zsl_attr;
Attr2       : zsl_attr;
Deltaflag   : zsl_bool;
Vfrom       : zsl_datefrom;
Vto         : zsl_dateto;
}

 

Die Tabelle zur Aufnahme der Selektionsoptionen hat folgende Struktur:

 

@EndUserText.label:'Select options'
@AbapCatalog.enhancement.category:#NOT_EXTENSIBLE
@AbapCatalog.tableCategory:#TRANSPARENT
@AbapCatalog.deliveryClass:#A
@AbapCatalog.dataMaintenance:#RESTRICTED
Define table zsl_par_sel {
 
Key variant : zsl_variant not null;
Key subvar  : zsl_subvar not null;
sign    	 : zsl_sign;
Seloption   : zsl_selopt;
unam_low	 : zsl_objnm;
unam_high   : zsl_objnm;
}

 

NextTables in Aktion – so gelingt die Konfiguration

Nach dem Aufruf von NextTables wird zuerst eine neue Konfiguration für die Tabelle ZSL_PAR_SEL angelegt (nur, wenn Selektionsoptionen benötigt werden). Wie Sie neue Konfigurationen anlegen erfahren Sie unter der NextTables Knowledge Base.  

Danach wird die Konfiguration für die Tabelle ZSL_PAR angelegt. Benötigt man ZSL_PAR_SEL, ist es dabei wichtig, im Bereich Eigenschaften die Felder ‘Item Tabellentyp’ und ‘Item_Tabellenname’ zu füllen. Das führt zu der unten gezeigten speziellen Darstellung.

 

                Definition eines Item-Tebellentyps

 

 

 

Programmfunktionalität migrieren – ohne den Code neu zu schreiben

Die Programmfunktionalität wird in eine Klasse übertragen. In dieser Klasse bildet eine Methode die aufzurufende Schnittstelle, im Beispiel ist das die Methode substitute_report. Diese muss 2 Parameter haben. Über i_variant wird die Variante an die Methode übergeben, an ct_messages können Meldungen angehängt werden. Die Meldungen werden später konvertiert und in NextTables angezeigt.

Die Methode liest zuerst die Selektion aus der übergebenen Variante und führt dann die migrierte Funktionalität aus. In der Praxis wird man einige Fehlermeldungen hinzufügen.

CLASS zslcl_migrated_report DEFINITION
 PUBLIC
 FINAL
 CREATE PUBLIC .
 PUBLIC SECTION .
   TYPES:
     " types to process the tables ZSA_PAR and ZSL_PAR_SEL
     ty_zsl_par     TYPE  zsl_par                          , "
     tt_zsl_par     TYPE  STANDARD TABLE OF zsl_par        , "
     ty_zsl_par_sel TYPE  zsl_par_sel                      , "
     tt_zsl_par_sel TYPE  STANDARD TABLE OF ty_zsl_par_sel . "
   CLASS-METHODS substitute_report
     IMPORTING i_variant   TYPE  ZSL_VARIANT
     CHANGING  ct_messages TYPE  rspc_t_msg                .
 PROTECTED SECTION.
 PRIVATE SECTION.
ENDCLASS.
CLASS zslcl_migrated_report IMPLEMENTATION .
 METHOD substitute_report .
   DATA:
     ls_msg         TYPE  rspc_s_msg        , "
     ls_zsl_par     TYPE  ty_zsl_par        , "
     lt_zsl_par_sel TYPE  tt_zsl_par_sel    , "
     lt_rs_msg      TYPE  rspc_t_msg        , " Messages received
     l_variant      TYPE  string            . "
   FIELD-SYMBOLS:
       TYPE  ANY TABLE    , " Receive the selected rec's
      TYPE  zsl_par      . " One record
   " Read variant data.
   SELECT SINGLE * FROM zsl_par
     WHERE variant EQ @i_variant
     INTO  @ls_zsl_par .
   IF sy-subrc EQ 0 .
     " Read item table.
     CLEAR lt_zsl_par_sel .
     SELECT * FROM zsl_par_sel
       WHERE variant EQ @ls_zsl_par-variant
       INTO  TABLE @lt_zsl_par_sel .
   ELSE .
     " Can occur, if method was called from a process chain.
     " Error message
     ls_msg-msgid   = '/NLY/TABLE_REST' . " Use your message class.
     ls_msg-msgno   = '000'             . " generic message
     ls_msg-msgty   = 'E'               . " Information
     ls_msg-msgv1   = |Variant { i_variant } is unknown. Check table ZSL_PAR.| .
     APPEND ls_msg TO ct_messages       .
     RETURN .
   ENDIF .
   " Transform the selection into select-options or other structures
   " The coding of the former report goes here.
   " ...
   " In case of errors, fill up ct_messages.
   " Sample message that will be displayed in NextTablers.
   ls_msg-msgid   = '/NLY/TABLE_REST' . " Use your message class.
   ls_msg-msgno   = '000'             . " generic message
   ls_msg-msgty   = 'I'               . " Information
   ls_msg-msgv1   = 'ZSLCL_MIGRATED_REPORT=>SUBSTITUTE_REPORT' .
   ls_msg-msgv2   = | was called for variant { i_variant }.| .
   APPEND ls_msg TO ct_messages       .
 ENDMETHOD .
ENDCLASS .

Ist die SAP BW Bridge ein cleverer Übergang - oder doch nur ein Umweg?

Laden Sie hier das Whitepaper herunter!

Nun muss noch das Editor-BAdI von NextTables erweitert werden. Wird schon eine aktive BAdI-Implementierung genutzt, kann diese erweitert werden. Dann muss nur der Filter angepasst werden. Für das vorgestellte Beispiel wird eine neue Implementierung angelegt.

Zwei Dinge sind zu tun. Es muss mindestens eine neue Schaltfläche eingeführt werden, um die implementierte Methode zslcl_migrated_report=>substitute_report  aufzurufen. Im Beispiel wird ein neues Menü ‘Drop down menue’ angelegt, in dem es die Schaltfläche ‘Method with report implementation’ gibt. Das wird in der Methode set_button_data gemacht, welche in /nly/if_editor~set_meta_exit aufgerufen wird.

In der Methode /nly/if_editor~set_update_exit wird die Betätigung der Schaltfläche behandelt. Die implementierte Klasse wird aufgerufen. Die erhaltenen Meldungen werden in das NextTables-Format konvertiert und ausgegeben. Wurden mehrere Zeilen selektiert, dann wird die Klasse in einer Schleife mehrfach aufgerufen.

CLASS zslcl_nt_editor_badi_sample DEFINITION
 PUBLIC
 FINAL
 CREATE PUBLIC .
 PUBLIC SECTION.
   INTERFACES if_badi_interface
     ALL METHODS ABSTRACT .
   INTERFACES /nly/if_badi_editor . " For NextTables
   INTERFACES /nly/if_editor      . " For NextTables
   " To convert standard messages to NextTable messages to be displayed.
   CLASS-METHODS msg_to_nt_msg
     IMPORTING it_msg     TYPE  rspc_t_msg
     EXPORTING et_message TYPE  /nly/tt_message         .
 PROTECTED SECTION.
 PRIVATE SECTION.
   CLASS-METHODS set_button_data
     IMPORTING
       !i_tabname     TYPE /nly/de_tabname
     CHANGING
       !ct_table_info TYPE /nly/ts_table_info .
ENDCLASS .


CLASS zslcl_nt_editor_badi_sample IMPLEMENTATION.
 METHOD /nly/if_editor~set_data_exit .
   " We do not need to do anything in this method for our sample.
 ENDMETHOD .
 METHOD /nly/if_editor~set_meta_exit .
* ******************************************************************************
* ** In this method we set the button data for our sample.
* ******************************************************************************
   set_button_data( EXPORTING i_tabname     = i_tabname
                    CHANGING  ct_table_info = ch_s_table_info
                  ) .
 ENDMETHOD .
 METHOD /nly/if_editor~set_update_exit .
   DATA:
     ls_zsl_par TYPE  zslcl_migrated_report=>ty_zsl_par , " param. record
     l_variant  TYPE  zsl_variant       , "
     lt_rs_msg  TYPE  rspc_t_msg        , " Messages received
     ls_nt_msg  TYPE  /nly/ts_message   , " Message in NextTables format
     lt_nt_msg  TYPE  /nly/tt_message   , " Messages in NextTables format
     l_count    TYPE  i                 .
   FIELD-SYMBOLS:
       TYPE  ANY TABLE    , " To receive the selected rec's
      TYPE  zsl_par      . " One record
   CASE i_tabname .
     WHEN 'ZSL_PAR' .
       CASE i_button .
         WHEN 'METHOD_1' .
           CHECK i_step = 1 .
           CLEAR: lt_rs_msg , ct_messages, l_count .
           " Read selected records
           ASSIGN co_table->* TO  .
           LOOP AT  ASSIGNING  .
             l_variant = -variant .
             " Call the processing class for every record.
             " Your class here.
             zslcl_migrated_report=>substitute_report(
               EXPORTING
                 i_variant      = l_variant
               CHANGING
                 ct_messages    = lt_rs_msg
             ) .
             l_count = l_count + 1 .
           ENDLOOP .
           " Check received messages.
           IF lt_rs_msg IS NOT INITIAL .
             " Convert messages into NextTables style.
             CLEAR lt_nt_msg .
             msg_to_nt_msg(
               EXPORTING  it_msg     = lt_rs_msg
               IMPORTING  et_message = lt_nt_msg
             ) .
             APPEND LINES OF lt_nt_msg TO ct_messages .
             CLEAR lt_rs_msg .
           ENDIF .
           " Add confirmation message.
           ls_nt_msg-type      = /nly/cl_table_rest_v3=>co_msg_type_success .
           ls_nt_msg-visu_type = /nly/cl_table_rest_v3=>co_visu_type_modal  .
           ls_nt_msg-hdr       = 'Method call.'                            .
           ls_nt_msg-msg       = |Method ZSLCL_MIGRATED_REPORT=>| &
                                 |SUBSTITUTE_REPORT was called | &
                                 |{ l_count } time(s).| .
             APPEND ls_nt_msg TO ct_messages .
           e_skip = 'X'.
         WHEN OTHERS .
       ENDCASE . " button
     WHEN OTHERS .
   ENDCASE . " table name
 ENDMETHOD .


 METHOD set_button_data .
   " Add button in the top of the layout.
   " Buttons are table specific.
   CASE i_tabname .
     WHEN 'ZSA_PAR' .
       ct_table_info-buttons = VALUE #( BASE ct_table_info-buttons
                      ( name     = 'NO_ACTION_T'
                        descr    = 'Drop down menue'
                        icon     = 'copy'
                        action   = /nly/cl_table_rest_v3=>co_action_no_action
                        location = /nly/cl_table_rest_v3=>co_location_top
                        tooltip  = 'Call any kind of method.'
                       )
                      ( name       = 'METHOD_1'
                        descr      = 'Method with report implementation'
                        icon       = 'copy' " could be a different icon
                        action     = /nly/cl_table_rest_v3=>co_action_send_sel
                        location   = /nly/cl_table_rest_v3=>co_location_top
                        sort_order = '0'
                        parent     = 'NO_ACTION_T'
                        tooltip  = 'Call method 1 with parameters'
                       )
                      ( name       = 'METHOD_2'
                        descr      = 'Another method (yet empty)'
                        icon       = 'paper-plain' " could be a different icon
                        action     = /nly/cl_table_rest_v3=>co_action_send_sel
                        location   = /nly/cl_table_rest_v3=>co_location_top
                        sort_order = '1'
                        parent     = 'NO_ACTION_T'
                        tooltip  = 'Call method 2 with parameters'
                       )
                     ) .
     WHEN OTHERS .
   ENDCASE .
 ENDMETHOD .


 METHOD msg_to_nt_msg .
   DATA:
     ls_msg     TYPE  rspc_s_msg      , " Standard message
     ls_message TYPE  /nly/ts_message . " Message in NextLytics format
   LOOP AT it_msg INTO ls_msg .
     MESSAGE ID ls_msg-msgid TYPE ls_msg-msgty NUMBER ls_msg-msgno
       WITH ls_msg-msgv1 ls_msg-msgv2 ls_msg-msgv3 ls_msg-msgv4
       INTO DATA(l_e_msg) .
     CASE ls_msg-msgty .
       WHEN 'E' .
         CLEAR ls_message .
         ls_message-type      = /nly/cl_table_rest_v3=>co_msg_type_error .
         ls_message-visu_type = /nly/cl_table_rest_v3=>co_visu_type_modal .
         ls_message-hdr       = 'Fehler' .
       WHEN 'W' .
         CLEAR ls_message .
         ls_message-type      = /nly/cl_table_rest_v3=>co_msg_type_warning .
         ls_message-visu_type = /nly/cl_table_rest_v3=>co_visu_type_modal .
         ls_message-hdr       = 'Warnung' .
       WHEN 'I' .
         CLEAR ls_message .
         ls_message-type      = /nly/cl_table_rest_v3=>co_msg_type_info .
         ls_message-visu_type = /nly/cl_table_rest_v3=>co_visu_type_modal .
         ls_message-hdr       = 'Information' .
     ENDCASE .
     ls_message-msg       = l_e_msg .
     APPEND ls_message TO et_message .
   ENDLOOP .
 ENDMETHOD .
ENDCLASS .

Die BAdI-Implementierung muss zum Enhancement-Spot registriert werden. Der Aufruf-Filter muss für die Parametertabelle angepasst werden und die Erweiterung muss aktiviert werden.

Mehr zur Verwendung von BAdis, um NextTables zu erweitern,gibt es auf der NextTables Knowledge Base

Flexibel bleiben: Aufruf über kundenspezifische Prozesstypen

In der ‘alten’ Umgebung kann man ABAP-Programme mit einer Variante aufrufen. Mit einem eigenen Prozesstyp geht das auch in einer Cloud-Umgebungen, sofern es möglich ist, eigene Prozesstypen zu definieren.

  1. Aufruf des Pflegedialogs: Bridge-Cockpit --> Entwicklung BW Bridge -> Configuration ->Custom Prozesstypen

2     Anlegen eines neuen Prozesstyps.

3     Anlegen der Klasse, die den Prozesstyp implementiert.

Definition eines eigenen Prozesstyps

 

Hinweis: In der Methode  if_rspc_simple_process_type~get_user_interface werden die Parameter festgelegt, die dem Prozesstyp mitgegeben werden können. Die aufgerufene Methode bestimmt, welche Parameter benötigt werden.

Hier werden die Klasse, die Methode und die Nummer der Variante benötigt.

Die aufgerufene Methode muss folgende Schnittstelle beinhalten:

CLASS-METHODS substitute_report
     IMPORTING i_variant   TYPE  ZSL_VARIANT
     CHANGING  ct_messages TYPE  rspc_t_msg                .

Die einfachste Prozesskette hat nur einen Prozessschritt:

 

     Aufruf einer Methode in einer Prozesskette

 

Der Methodenaufruf ist folgendermaßen parametriert:

 

    Parameter des Methodenaufrufs (mit Variante).

 

Migration bestehender ABAP-Programme in SAP-Cloud-Umgebungen: Unser Fazit

Mit diesem Ansatz gelingt es, bewährte ABAP-Funktionalitäten zukunftssicher in Cloud-Umgebungen zu überführen, ohne sie komplett neu entwickeln zu müssen.
Das spart Entwicklungszeit, Kosten und minimiert Projektrisiken – bei gleichzeitig hoher Anwenderakzeptanz.

Wir begleiten Sie gern auf dem Weg in die Cloud – von der Analyse Ihrer bestehenden ABAP-Landschaft über die technische Umsetzung bis zur produktiven Integration in S/4HANA, die SAP BTP oder BW Bridge.

Haben Sie Fragen zu einem anderen Thema? Nehmen Sie einfach Kontakt zu uns auf - wir freuen uns auf den Austausch mit Ihnen!