This is a test message to test the length of the message box.
Login
ABAP XCO Callstack, Tenant
Erstellt von Software-Heroes

ABAP - XCO Callstack und Tenant

125

Wie kommst du mit den XCO Klassen an den ABAP Call Stack und bekommst weitere Informationen zum aktuellen Tenant? In diesem Artikel schauen wir einmal ins Detail.

Werbung


Die XCO Klassen sind Hilfsklassen die verschiedene Funktionen des Alltags gebündelt unter einer öffentlichen API zur Verfügung stellen. Weitere Informationen und eine Übersicht über die XCO Bibliotheken findest du auf der Übersichtsseite.

 

Einleitung

Der Aufrufstack wird vor allem beim Debugging angezeigt und in seltenen Fällen auch einmal in der Entwicklung benötigt, um zu erfahren aus welchem Prozess eine Logik gerufen wurde. Daneben gibt es noch das Tenant Objekt, welches weitere Informationen zum System zurückgibt, wie zum Beispiel die URL des Systems oder die ID des Subaccounts. Daher wollen wir uns die beiden Funktionen in diesem Artikel einmal näher anschauen.

 

Callstack

Möchten wir an die Informationen des Callstacks gelangen, dann holen wir uns im ersten Schritt das Objekt und können dann damit weiterarbeiten. Grundsätzlich musst du das Objekt nicht in einer Variable zwischenspeichern.

DATA(stack) = xco_cp=>current->call_stack.

 

Für unseren Testfall schauen wir uns den Stack in einer Methode der Klasse an, die direkt unter der MAIN Methode liegt. Im Debugger wurde der Callstack dafür wie folgt aussehen:

 

Vollständig

Im ersten Schritt lesen wir den Callstack einmal vollständig über die Methode FULL aus. Im nächsten Schritt benötigen wir einen Formatter für die Ausgabe, dazu können wir die Klasse XCO_CP_CALL_STACK verwenden und über das FORMAT Attribut an den Formatter kommen. Als nächstes können wir dann über das Objekt loopen, wenn wir uns den Stack als Text zurückgeben lassen und über GET_LINES ein Strings Objekt erhalten.

DATA(full_stack) = stack->full( ).
DATA(format_adt) = xco_cp_call_stack=>format->adt( ).

LOOP AT full_stack->as_text( format_adt )->get_lines( )->value INTO DATA(text).
  out->write( text ).
ENDLOOP.

 

In der zweiten Version erweitern wir den Formatter noch um eine Option der Zeilennummern. Dabei erhalten wir zur Aufrufstelle auch noch die Zeilennummer am Text. Hier kannst du zwischen INCLUDE und SOURCE wählen, wie Include vermuten lässt, wird die Zeilennummer auf Basis des Includes errechnet. Da Methoden in Includes verwaltet werden, würdest du hier immer eine relativ niedrige Nummer erhalten und nicht die eigentliche Position in der gesamten Klasse. Das macht das Auffinden in ADT etwas schwerer, da wir hier mit der gesamten Klasse arbeiten.

DATA(full_stack) = stack->full( ).
DATA(format_source) = xco_cp_call_stack=>format->adt( )->with_line_number_flavor(
    xco_cp_call_stack=>line_number_flavor->source ).

LOOP AT full_stack->as_text( format_source )->get_lines( )->value INTO text.
  out->write( text ).
ENDLOOP.

 

Die Ausgabe für die beiden Varianten würde damit wie folgt aussehen.

 

Filter

Im zweiten Schritt wollen wir nicht alle Positionen des Callstacks haben, sondern verschiedene Filter auf die verschiedenen Einträge anwenden. Beginnen wir daher direkt mit der Methode UP_TO, um die ersten Einträge es Stacks zu lesen. Hier solltest du wissen, dass du erst ab der 7 einen Eintrag aus dem Callstack erhältst. Intern werden zuvor die Einträge aus dem Stack gelöscht, die zur XCO Klasse gehören, damit musst du eine höhere Zahl angeben.

DATA(stack_part) = stack->up_to( 8 ).

LOOP AT stack_part->as_text( format_adt )->get_lines( )->value INTO text.
  out->write( text ).
ENDLOOP.

 

Führen wir die Methode mit einer 8 aus, erhalten wir die ersten zwei Zeilen des Stacks, das wäre dann unsere aktuelle Methode und die MAIN Methode der Klasse.

 

Über den kompletten Stack können wir auch mit FROM und TO arbeiten, um gewisse Einträge abzugrenzen. Im nächsten Beispiel verwenden wir die Position, um die ersten beiden Einträge des Stacks zu lesen. Die Funktion liefert das gleiche Ergebnis wie oben (die ersten beiden Einträge).

LOOP AT full_stack->to->position( 2 )->as_text( format_adt )->get_lines( )->value INTO text.
  out->write( text ).
ENDLOOP.

 

Neben der Position kannst du die Werte auch nach Pattern durchsuchen, dazu stehen zwei weitere Methoden zur Verfügung. Diese findest du hinter TO und FROM im Interface.

 

Im nächsten Beispiel wollen wir alle Einträge erhalten, wo der Klassenname unserer aktuellen Klasse entspricht. Da wir hier TO verwenden und das letzte Auftreten, erhalten wir alle Einträge des Stacks. Dies würde wieder den beiden Einträgen von oben entsprechen.

DATA(pattern) = xco_cp_call_stack=>line_pattern->method( )->where_class_name_equals( 'ZCL_BS_DEMO_XCO_CURRENT' ).

LOOP AT full_stack->to->last_occurrence_of( pattern )->as_text( format_source )->get_lines( )->value INTO text.
  out->write( text ).
ENDLOOP.

 

Tenant

Wollen wir Informationen zum aktuellen Tenant bekommen, dann können wir dazu das TENANT Objekt verwenden. Den Tenant solltest du nicht mit dem Mandanten verwechseln. Hierbei erhältst du Informationen zum aktuellen System, dem Global Account und Subaccount, sowie die URL des Systems. Damit sind die Informationen vor allem für die Cloud relevant. Über CURRENT kannst du dir das Objekt holen.

DATA(tenant_info) = xco_cp=>current->tenant( ).

 

Wollen wir an die verschiedenen ID's gelangen, stehen uns die verschiedenen Methoden im Interface zur Verfügung. Dazu ein kleiner Überblick über die Schnittstelle der Klasse.

 

Schauen wir uns im ersten Schritt die verschiedenen IDs an, die wir aus dem Infosystem erhalten können. Dabei steht uns der Global Account zur Verfügung, dieser sollte pro Kunde eigentlich nur einmal vorhanden sein. Der Subaccount beschreibt die Umgebung, wo das ABAP Environment läuft. Die GUID ist die ID des Systems und diese findest du dann auch im externen Format in der URL wieder. Die ID scheint die eindeutige ID zu sein, unter der das System bzw. die Installation läuft. Wie dir an den nachfolgenden Beispielen auffallen wird, gibt es verschiedene Methoden um an die eigentlichen Werte zu gelangen.

DATA(global_account_id) = tenant_info->get_global_account_id( )->as_string( ).
DATA(subaccount_id) = tenant_info->get_subaccount_id( )->as_string( ).
DATA(system_guid) = tenant_info->get_guid( )->value.
DATA(system_id) = tenant_info->get_id( ).

 

Möchtest du die URL zum System erhalten, musst du ich im ersten Schritt dafür entscheiden, welche URL du ausgeben möchtest. Hier unterscheidet das System in UI Komponenten und Ausgabe, sowie in API Endpunkte. Dabei ist der Unterschied recht klein. Über die Klasse XCO_CP_TENANT können wir die verschiedenen URL Typen erhalten.

DATA(system_host_ui) = tenant_info->get_url( xco_cp_tenant=>url_type->ui )->get_host( ).
DATA(system_host_api) = tenant_info->get_url( xco_cp_tenant=>url_type->api )->get_host( ).

 

Das Ergebnis aus der Console hier einmal im Überblick. Da die meisten IDs die Accounts und Systeme darstellen, wurde der Großteil unkenntlich gemacht.

 

Vollständiges Beispiel

Die Klasse findest du einmal hier unter dem Artikel, aber auch als Commit in unserem GitHub Repository. Die Klasse und das Beispiel wurden auf dem ABAP Environment getestet.

CLASS zcl_bs_demo_xco_current DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    METHODS abap_call_stack
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS tenant_info
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.


CLASS zcl_bs_demo_xco_current IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    abap_call_stack( out ).
    tenant_info( out ).
  ENDMETHOD.


  METHOD abap_call_stack.
    DATA(stack) = xco_cp=>current->call_stack.

    DATA(full_stack) = stack->full( ).
    DATA(format_adt) = xco_cp_call_stack=>format->adt( ).
    DATA(format_source) = xco_cp_call_stack=>format->adt( )->with_line_number_flavor(
        xco_cp_call_stack=>line_number_flavor->source ).

    out->write( '### Callstack ADT Format Default (All)' ).
    LOOP AT full_stack->as_text( format_adt )->get_lines( )->value INTO DATA(text).
      out->write( text ).
    ENDLOOP.

    out->write( ` ` ).
    out->write( '### Callstack ADT Format with Source (All)' ).
    LOOP AT full_stack->as_text( format_source )->get_lines( )->value INTO text.
      out->write( text ).
    ENDLOOP.

    DATA(stack_part) = stack->up_to( 8 ).

    out->write( ` ` ).
    out->write( '### Callstack ADT Format (Up To)' ).
    LOOP AT stack_part->as_text( format_adt )->get_lines( )->value INTO text.
      out->write( text ).
    ENDLOOP.

    out->write( ` ` ).
    out->write( '### Callstack ADT Format (To)' ).
    LOOP AT full_stack->to->position( 2 )->as_text( format_adt )->get_lines( )->value INTO text.
      out->write( text ).
    ENDLOOP.

    DATA(pattern) = xco_cp_call_stack=>line_pattern->method( )->where_class_name_equals( 'ZCL_BS_DEMO_XCO_CURRENT' ).

    out->write( ` ` ).
    out->write( '### Callstack ADT Format with Source (Last)' ).
    LOOP AT full_stack->to->last_occurrence_of( pattern )->as_text( format_source )->get_lines( )->value INTO text.
      out->write( text ).
    ENDLOOP.
  ENDMETHOD.


  METHOD tenant_info.
    DATA(tenant_info) = xco_cp=>current->tenant( ).

    DATA(global_account_id) = tenant_info->get_global_account_id( )->as_string( ).
    DATA(subaccount_id) = tenant_info->get_subaccount_id( )->as_string( ).
    DATA(system_guid) = tenant_info->get_guid( )->value.
    DATA(system_id) = tenant_info->get_id( ).
    DATA(system_host_ui) = tenant_info->get_url( xco_cp_tenant=>url_type->ui )->get_host( ).
    DATA(system_host_api) = tenant_info->get_url( xco_cp_tenant=>url_type->api )->get_host( ).

    out->write( global_account_id ).
    out->write( subaccount_id ).
    out->write( system_guid ).
    out->write( system_id ).
    out->write( system_host_ui ).
    out->write( system_host_api ).
  ENDMETHOD.
ENDCLASS.

 

Fazit

An die Verwendung des Callstacks und die Filterung muss man sich erst einmal gewöhnen, über die Dokumentation findest du weitere Informationen, wie die API zu bedienen ist. Der Tenant bietet dahingehend einen einfachen Zugang zu den Methoden.

 

Quelle:
SAP Help - Call Stack
SAP Help - Tenant


Enthaltene Themen:
Modernes ABAPXCOCurrentCall Stack
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


ABAP - XCO Nachricht und Sprache

Kategorie - ABAP

Was kannst du zusätzlich mit Nachrichten und den Sprachobjekten der XCO Bibliothek in ABAP Cloud machen? Lass uns der Frage im Detail nachgehen.

01.07.2025

ABAP - XCO Generation und Info System

Kategorie - ABAP

Wie kannst du mit ABAP Cloud Mitteln neue Objekte im System generieren und Informationen zu diesen erhalten? An einem Beispiel schauen wir uns das genauer an.

27.06.2025

ABAP - XCO Class Runner

Kategorie - ABAP

Wie sieht es mit der Ausführung von ABAP Klassen im Bereich von XCO aus? Schauen wir uns dazu den Class Runner genauer an.

04.02.2025

ABAP - XCO UUID

Kategorie - ABAP

Wie generierst du mit den XCO Klassen eindeutige IDs in ABAP? In diesem Artikel erfährst du, wie schnell und einfach das möglich ist.

28.01.2025

ABAP - XCO Systemfelder

Kategorie - ABAP

Gibt es für SY bzw. SYST auch eine Alternative in der XCO Bibliothek in ABAP Cloud? Einen Blick ist sie auf jeden Fall wert.

24.01.2025