This is a test message to test the length of the message box.
Login
BTP Application Job
Erstellt von Software-Heroes

BTP - Application Job (Interne API)

62

Wie plant man einen Job im System ein, wenn wir mitten in der Verarbeitung unserer Anwendung sind? In diesem Artikel erfährst du mehr zur API.

Werbung


Jobs werden nicht nur über die Fiori Apps eingeplant, sondern müssen auch in Anwendungen einplanbar sein und zwar ohne den Eingriff des Nutzers. In diesem Artikel zeigen wir dir, wie du die API nutzen kannst und wie du damit einfach Jobs im System ausführen kannst.

 

Einleitung

Geht es um die Einplanung und Ausführung von Jobs im System, gibt es die freigegebene API in der Form der Klasse CL_APJ_RT_API. Diese Klassen stellt Methoden zur Verfügung, mit denen man eine einfache Ausführung oder wiederkehrende Pattern einplanen kann. Möchtest du einen Application Job einplanen, dann solltest du diese API nutzen.

 

Vorbereitung

Bevor wir mit dem Aufruf der API starten, benötigen wir für unseren Job noch einige Parameter. Teilweise sind Parameter im Template Pflicht und werden durch Validierungen überprüft, deshalb bereiten wir einen Satz Parameter vor der Einplanung für alle Beispiele vor. Die Parameter halten wir in einer Tabelle als Attribut (Member) der Klasse.

DATA mt_parameter TYPE cl_apj_rt_api=>tt_job_parameter_value.

mt_parameter = VALUE cl_apj_rt_api=>tt_job_parameter_value(
    ( name = 'TEXT' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = 'Planned Job' ) ) )
    ( name = 'COUNTRY' t_value = VALUE #( ( sign = 'I' option = 'BT' low = 'DE' high = 'EN' ) ) )
    ( name = 'R_TEXT' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_false ) ) )
    ( name = 'R_LAND' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_true ) ) )
    ( name = 'TEST' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_false ) ) ) ).

 

Den Job den wir in diesem Beispiel verwenden, haben wir bereits in einem anderen Artikel erstellt. Über den Link findest du weitere Hinweise zur Erstellung und Nutzung von Application Jobs.

 

Einplanung

Für die Einplanung eines Jobs benötigen wir die Methode SCHEDULE_JOB der Klasse, diese bietet die nötige Schnittstelle, um den Job im System einzuplanen.

 

Einmalig

Im ersten Schritt wollen wir den Job einmal Ausführen lassen und das direkt nach dem Aufruf der Methode. Dazu befüllen wir die Schnittstelle mit den benötigten Informationen. Dazu zählt auch das Job-Template, welches wir angelegt haben, plus die entsprechenden Parameter und die Startoptionen.

DATA(ls_start) = VALUE cl_apj_rt_api=>ty_start_info( start_immediately = abap_true ).

cl_apj_rt_api=>schedule_job( EXPORTING iv_job_template_name   = 'ZBS_DEMO_JOB_ADT_TEMPLATE'
                                       iv_job_text            = 'Single run from Code (Immediately)'
                                       is_start_info          = ls_start
                                       it_job_parameter_value = mt_parameter
                             IMPORTING ev_jobname             = DATA(ld_jobname)
                                       ev_jobcount            = DATA(ld_jobcount) ).

out->write( |Job planned under Jobname { ld_jobname } and Jobcount { ld_jobcount }| ).

 

Nach Ausführung des Codings erhalten wir in der Konsole die Erfolgsmeldung und die Ausgabe von Jobname und Jobcount. Über die beiden Werte kommen wir später an weitere Informationen zum Job:

 

Prüfen wir dann die Fiori App "Application Jobs", dann finden wir dort den Job mit der entsprechenden Bezeichnung. Da der Job eine sehr kurze Laufzeit hat, wurde dieser bereits durchgeführt und steht auf "Finished".

 

Regelmäßig

Als nächstes planen wir einen wiederkehrenden Job ein, dieser soll sofort starten und dann zwei Mal wiederholt werden. Der Quellcode für die Einplanung des Jobs sieht nun wie folgt aus:

DATA(ls_start) = VALUE cl_apj_rt_api=>ty_start_info( ).
GET TIME STAMP FIELD ls_start-timestamp.
ls_start-timestamp = cl_abap_tstmp=>add( tstmp = ls_start-timestamp
                                         secs  = 120 ).

DATA(ls_end) = VALUE cl_apj_rt_api=>ty_end_info( type = 'NUM' max_iterations = 3 ).

DATA(ls_scheduling_info) = VALUE cl_apj_rt_api=>ty_scheduling_info(
    periodic_granularity = 'W'
    periodic_value       = 1
    test_mode            = abap_false
    timezone             = 'CET'
    weekday_info         = VALUE #( on_tuesday = abap_true on_saturday = abap_true ) ).

cl_apj_rt_api=>schedule_job( EXPORTING iv_job_template_name   = 'ZBS_DEMO_JOB_ADT_TEMPLATE'
                                       iv_job_text            = 'Recurring run'
                                       is_start_info          = ls_start
                                       it_job_parameter_value = mt_parameter
                                       is_end_info            = ls_end
                                       is_scheduling_info     = ls_scheduling_info
                             IMPORTING ev_jobname             = DATA(ld_jobname)
                                       ev_jobcount            = DATA(ld_jobcount) ).

 

Dazu die folgende Erklärung, um die Teile besser einordnen zu können:

  • Start - Dieses Mal setzen wir den Zeitstempel, um den Job zu einer bestimmten Uhrzeit und nicht sofort einzuplanen. Dabei rechnen wir auf die aktuelle Uhrzeit zwei Minuten dazu.
  • Ende - Wir möchten, dass der Job nach zwei Wiederholungen abbricht, dazu setzen wir den TYPE auf 'NUM', also Anzahl, und die Anzahl der Wiederholungen auf 3. Der aktuelle Lauf zählt ebenfalls, deshalb benötigen wir für zwei Wiederholungen die Anzahl von drei Jobs.
  • Einplanung - Wir setzen die Einplanung mit 'W' auf wöchentlich und die Frequenz auf 1, also alle einer Woche. Der Job soll nur an den Wochentagen Dienstag und Samstag laufen. Dabei ist allerdings wichtig, dass der Sofortstart auch an einem der beiden Tage läuft, sonst bekommst du einen Abbruch in der Verarbeitung.

 

Nach der Einplanung können die Jobs wieder in der App gefunden werden. Wenn du die Einschränkung auch auf die Zukunft vornimmst, dann findest du auch die eingeplanten Jobs.

 

Konstanten

Für die Einplanung der Jobs werden verschiedene Werte benötigt, die im Interface IF_APJ_RT_TYPES als Konstantenstruktur abgebildet werden. Da das Interface im Moment nicht freigegeben ist, müssen die Werte im Code hart hinterlegt werden, können aber hier eingesehen werden. Über die Strukturen und die Domänen, findet man die Werte in den Festwerten ebenfalls. Über die Element Info kannst du sie auch in den ABAP Development Tools anzeigen:

 

Informationen

An einigen Stellen wollen wir den aktuellen Status eines Jobs prüfen oder vielleicht weitere Informationen zu einem Job lesen, dazu gibt es ebenfalls verschiedene Methoden, um an die Informationen zu kommen. Benötigen wir einfach nur den Status und den entsprechenden Text dazu, steht die Methode GET_JOB_STATUS zur Verfügung:

cl_apj_rt_api=>get_job_status( EXPORTING iv_jobname         = 'FEDC1903ACDA1EEEABE45F7233854BD6'
                                         iv_jobcount        = 'Bsgasykr'
                               IMPORTING ev_job_status      = DATA(ld_status)
                                         ev_job_status_text = DATA(ld_text) ).

out->write( |Status: { ld_status } - { ld_text }| ).

 

Dadurch erhalten wir das folgende Ergebnis als Ausgabe in der Console:

 

Benötigst du einige Informationen mehr zum Job, vielleicht auch die Laufzeit, den User oder Informationen zum genutzten Template, dann kannst du die Methode GET_JOB_DETAILS verwenden:

DATA(ls_job_details) = cl_apj_rt_api=>get_job_details( iv_jobname  = 'FEDC1903ACDA1EEEABE45F7233854BD6'
                                                       iv_jobcount = 'Bsgasykr' ).

 

Das Ergebnis der Abfrage hier einmal in der Variablenansicht in den ABAP Development Tools:

 

Weitere Methoden

Alle Methoden der API zu erklären, würde den Rahmen des Artikels sprengen. Die Klasse bietet allerdings noch verschiedene Methoden an, um zum Beispiel weiter Aktionen durchzuführen:

  • CANCEL_JOB - Abbrechen eines laufenden Jobs.
  • FIND_JOBS_WITH_JCE - Such nach Jobs die das entsprechende Template verwenden. Dabei werden nur Jobs zurück gegeben die laufen oder in der Zukunft eingeplant sind.
  • COPY_JOB - Kopieren eines Jobs.
  • GENERATE_JOBKEY - Generierung von Jobname und Jobcount, bereits vor der Einplanung des Jobs. Mit diesen Informationen kann ein Job eingeplant werden und die automatische Vergabe unterbunden werden.

 

Vollständiges Beispiel

Hier findest du noch einmal die komplette ausführbare Klasse zum Testen. Die Methode READ_JOB_INFO muss entsprechend mit Werten aus deinem System befüllt werden, hier findest du noch unsere Dummy Werte des Joblaufs:

CLASS zcl_bs_demo_job_api DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    DATA mt_parameter TYPE cl_apj_rt_api=>tt_job_parameter_value.

    METHODS plan_single_run
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.

    METHODS plan_recurring_runs
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.

    METHODS read_job_info
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.


CLASS zcl_bs_demo_job_api IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    mt_parameter = VALUE cl_apj_rt_api=>tt_job_parameter_value(
        ( name = 'TEXT' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = 'Planned Job' ) ) )
        ( name = 'COUNTRY' t_value = VALUE #( ( sign = 'I' option = 'BT' low = 'DE' high = 'EN' ) ) )
        ( name = 'R_TEXT' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_false ) ) )
        ( name = 'R_LAND' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_true ) ) )
        ( name = 'TEST' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = abap_false ) ) ) ).

    plan_single_run( out ).
    plan_recurring_runs( out ).
    read_job_info( out ).
  ENDMETHOD.


  METHOD plan_single_run.
    TRY.
        DATA(ls_start) = VALUE cl_apj_rt_api=>ty_start_info( start_immediately = abap_true ).

        cl_apj_rt_api=>schedule_job( EXPORTING iv_job_template_name   = 'ZBS_DEMO_JOB_ADT_TEMPLATE'
                                               iv_job_text            = 'Single run from Code (Immediately)'
                                               is_start_info          = ls_start
                                               it_job_parameter_value = mt_parameter
                                     IMPORTING ev_jobname             = DATA(ld_jobname)
                                               ev_jobcount            = DATA(ld_jobcount) ).

        io_out->write( |Job planned under Jobname { ld_jobname } and Jobcount { ld_jobcount }| ).

      CATCH cx_apj_rt INTO DATA(lo_error).
        io_out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.


  METHOD plan_recurring_runs.
    TRY.
        DATA(ls_start) = VALUE cl_apj_rt_api=>ty_start_info( ).
        GET TIME STAMP FIELD ls_start-timestamp.
        ls_start-timestamp = cl_abap_tstmp=>add( tstmp = ls_start-timestamp
                                                 secs  = 120 ).

        DATA(ls_end) = VALUE cl_apj_rt_api=>ty_end_info( type = 'NUM' max_iterations = 3 ).

        DATA(ls_scheduling_info) = VALUE cl_apj_rt_api=>ty_scheduling_info(
            periodic_granularity = 'W'
            periodic_value       = 1
            test_mode            = abap_false
            timezone             = 'CET'
            weekday_info         = VALUE #( on_tuesday = abap_true on_saturday = abap_true ) ).

        cl_apj_rt_api=>schedule_job( EXPORTING iv_job_template_name   = 'ZBS_DEMO_JOB_ADT_TEMPLATE'
                                               iv_job_text            = 'Recurring run'
                                               is_start_info          = ls_start
                                               it_job_parameter_value = mt_parameter
                                               is_end_info            = ls_end
                                               is_scheduling_info     = ls_scheduling_info
                                     IMPORTING ev_jobname             = DATA(ld_jobname)
                                               ev_jobcount            = DATA(ld_jobcount) ).

        io_out->write( |Job planned under Jobname { ld_jobname } and Jobcount { ld_jobcount }| ).

      CATCH cx_apj_rt INTO DATA(lo_error).
        io_out->write( lo_error->get_text( ) ).
    ENDTRY.
  ENDMETHOD.


  METHOD read_job_info.
    cl_apj_rt_api=>get_job_status( EXPORTING iv_jobname         = 'FEDC1903ACDA1EEEABE45F7233854BD6'
                                             iv_jobcount        = 'Bsgasykr'
                                   IMPORTING ev_job_status      = DATA(ld_status)
                                             ev_job_status_text = DATA(ld_text) ).

    io_out->write( |Status: { ld_status } - { ld_text }| ).

    DATA(ls_job_details) = cl_apj_rt_api=>get_job_details( iv_jobname  = 'FEDC1903ACDA1EEEABE45F7233854BD6'
                                                           iv_jobcount = 'Bsgasykr' ).

    io_out->write( ls_job_details ).
  ENDMETHOD.
ENDCLASS.

 

ABAP Cloud

Funktionsbausteine wie JOB_OPEN funktionieren in der Welt von ABAP Cloud nicht mehr, weil die Objekte für den Entwickler in TIER-1 nicht zur Verfügung stehen. Im Fall der Application Jobs hat sich auch das zu automatisierende Objekt geändert (Report zu Klasse). Über den Cloudification Repository Viewer findest du die Nachfolgeobjekte bzw. API um wie gewohnt Jobs über deine Verarbeitung einplanen zu können.

 

Fazit

Die Einplanung von Application Jobs ist recht einfach mit einem Methodenaufruf erledigt. Die bereitgestellte API erlaubt uns alle Grundoperationen durchzuführen, um einen Job einzuplanen, auszuplanen und Informationen dazu zu lesen.


Enthaltene Themen:
BTPApplication JobABAP EnvironmentAPI
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.


RAP - Custom Entity Wertehilfe (Deep Dive)

Kategorie - ABAP

Mit der Custom Entity hast du in RAP die meisten Freiheiten in der Entwicklung von ABAP Cloud Anwendungen, doch wie sieht es mit potentiellen Fehlern aus?

12.07.2024

BTP - Business Configuration (Einstellungen)

Kategorie - ABAP

Schauen wir uns im ABAP Environment einmal die Einstellungen des Maintanance Objects an und welche Auswirkungen sie auf die Pflege haben.

31.05.2024

RAP - Deep Action in OData v4

Kategorie - ABAP

In diesem Artikel schauen wir uns einmal Aktionen mit tiefen Strukturen an, wie wir sie erzeugen und Daten an einen API Endpunkt übergeben können.

24.05.2024

BTP - Business Configuration (Anpassung)

Kategorie - ABAP

Wie sieht es eigentlich mit Anpassungen des RAP Business Objekts im Kontext der Business Configuration aus? Mehr Informationen in diesem Artikel.

17.05.2024

BTP - Business Configuration (ohne Transport)

Kategorie - ABAP

Wie nutzt man eigentlich die Business Configuration ohne die Transportaufzeichnung? In diesem Artikel klären wir, ob es möglich ist.

07.05.2024