Periodischer Job mit unabhängigen Steps
Jobverarbeitung is in vielen Bereichen und für viele Funktionalitäten wichtig. Jobeinplanungen sind eine gängige Technik, die jahrzehntelang erprobt ist. Kürzlich bin ich in einem Projekt auf eine Anforderung gestoßen, die nicht so ohne Weiteres mit den Standardmitteln der Jobeinplanung möglich war.
Anforderung
Es soll ein periodischer Job mit mehreren Steps eingeplant werden, deren Verarbeitungsschritte (Steps) unabhängig voneinander sind. Unabhängig heißt in diesem Fall, dass ein Verarbeitungsschritt, der durch einen Kurzdump abbricht, die Ausführung der anderen Schritte nicht beeinträchtigen soll.
Möglichkeit 1
Die erste auf der Hand liegende Möglichkeit ist, einen Job periodisch einzuplanen, der einzelne Verarbeitungsschritte enthält. Leider bricht der gesamte Job ab, wenn einer der Verarbeitungsschritte durch einen Shortdump abbricht. Diese Möglichkeit kommt also nicht in Betracht.
Möglichkeit 2
Die zweite Möglichkeit wäre, die einzelnen Verarbeitungsschritte als einzelne Jobs zu definieren und jeweils den einen Job als Vorgänger des jeweils nächsten Jobs zu definieren. Aber auch hier gibt es eine Einschränkung: Diese Jobs können nicht periodisch geplant werden.
Lösung
Die Lösung für mich war in diesem Fall natürlich ein ABAP Programm. Das folgende Programm kann man periodisch als Job einplanen und hier bis zu fünf Programme unabhängig voneinander, jeweils mit Vorgänger – Nachfolger-Beziehung, definieren. Wenn das Programm ausgeführt wird, startet es das erste Programm sofort als Job. Das zweite Programm wird gestartet, wenn der Job für das erste Programm beendet wurde und so weiter. Dabei ist es unerheblich, ob der Vorgängerjob regulär beendet wurde oder abgebrochen ist.
Das Programm ist fest auf fünf Verarbeitungsschritte ausgelegt. Es kann einfach auf weitere Steps erweitert werden. Sofern noch sehr viele Verarbeitungsschritte verwaltet werden sollten, sollte man die Verarbeitung dynamisch programmieren. Dafür müsste man jedoch auch die Eingabe für die Definition der Verarbeitungsschritte so anpassen, dass die einzelnen Programme in einer Liste (Grid) eingegeben werden können.
Coding
REPORT z_schedule_05_jobs_periodic. PARAMETERS nam1 TYPE btcjob OBLIGATORY. PARAMETERS rep1 TYPE syrepid OBLIGATORY. PARAMETERS var1 TYPE raldb_vari OBLIGATORY. SELECTION-SCREEN SKIP 1. PARAMETERS nam2 TYPE btcjob. PARAMETERS rep2 TYPE syrepid. PARAMETERS var2 TYPE raldb_vari. SELECTION-SCREEN SKIP 1. PARAMETERS nam3 TYPE btcjob. PARAMETERS rep3 TYPE syrepid. PARAMETERS var3 TYPE raldb_vari. SELECTION-SCREEN SKIP 1. PARAMETERS nam4 TYPE btcjob. PARAMETERS rep4 TYPE syrepid. PARAMETERS var4 TYPE raldb_vari. SELECTION-SCREEN SKIP 1. PARAMETERS nam5 TYPE btcjob. PARAMETERS rep5 TYPE syrepid. PARAMETERS var5 TYPE raldb_vari. CLASS lcx_job DEFINITION INHERITING FROM cx_static_check. ENDCLASS. CLASS lcl_define_job DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING iv_name TYPE btcjob iv_report TYPE syrepid iv_variant TYPE raldb_vari RAISING lcx_job. METHODS start IMPORTING iv_pred_jobcount TYPE btcjobcnt OPTIONAL iv_pred_jobname TYPE btcjob OPTIONAL RAISING lcx_job. DATA mv_jobcount TYPE btcjobcnt. DATA mv_jobname TYPE btcjob. DATA mv_released TYPE abap_bool. ENDCLASS. CLASS lcl_define_job IMPLEMENTATION. METHOD constructor. mv_jobname = iv_name. CALL FUNCTION 'JOB_OPEN' EXPORTING jobname = iv_name IMPORTING jobcount = mv_jobcount EXCEPTIONS cant_create_job = 1 invalid_job_data = 2 jobname_missing = 3 OTHERS = 4. IF sy-subrc = 0. CALL FUNCTION 'JOB_SUBMIT' EXPORTING authcknam = sy-uname jobcount = mv_jobcount jobname = iv_name report = iv_report variant = iv_variant EXCEPTIONS bad_priparams = 1 bad_xpgflags = 2 invalid_jobdata = 3 jobname_missing = 4 job_notex = 5 job_submit_failed = 6 lock_failed = 7 program_missing = 8 prog_abap_and_extpg_set = 9 OTHERS = 10. IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_job. ENDIF. ENDIF. ENDMETHOD. METHOD start. CALL FUNCTION 'JOB_CLOSE' EXPORTING jobcount = mv_jobcount jobname = mv_jobname pred_jobcount = iv_pred_jobcount pred_jobname = iv_pred_jobname strtimmed = SWITCH #( iv_pred_jobcount WHEN space THEN 'X' ELSE space ) IMPORTING job_was_released = mv_released EXCEPTIONS cant_start_immediate = 1 invalid_startdate = 2 jobname_missing = 3 job_close_failed = 4 job_nosteps = 5 job_notex = 6 lock_failed = 7 invalid_target = 8 OTHERS = 9. IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_job. ENDIF. ENDMETHOD. ENDCLASS. START-OF-SELECTION. TRY. DATA(job1) = NEW lcl_define_job( iv_name = nam1 iv_report = rep1 iv_variant = var1 ). job1->start( ). IF rep2 IS NOT INITIAL. DATA(job2) = NEW lcl_define_job( iv_name = nam2 iv_report = rep2 iv_variant = var2 ). job2->start( iv_pred_jobname = job1->mv_jobname iv_pred_jobcount = job1->mv_jobcount ). ENDIF. IF rep3 IS NOT INITIAL. DATA(job3) = NEW lcl_define_job( iv_name = nam3 iv_report = rep3 iv_variant = var3 ). job3->start( iv_pred_jobname = job2->mv_jobname iv_pred_jobcount = job2->mv_jobcount ). ENDIF. IF rep4 IS NOT INITIAL. DATA(job4) = NEW lcl_define_job( iv_name = nam4 iv_report = rep4 iv_variant = var4 ). job4->start( iv_pred_jobname = job3->mv_jobname iv_pred_jobcount = job3->mv_jobcount ). ENDIF. IF rep5 IS NOT INITIAL. DATA(job5) = NEW lcl_define_job( iv_name = nam5 iv_report = rep5 iv_variant = var5 ). job5->start( iv_pred_jobname = job4->mv_jobname iv_pred_jobcount = job4->mv_jobcount ). ENDIF. CATCH lcx_job. MESSAGE 'Error job creation!' TYPE 'I'. ENDTRY.
- Interview mit Björn Schulz (Software-Heroes.com) - 3. September 2024
- Daten aus ALV ermitteln - 3. September 2024
- So lange es den SAPGUI noch gibt… - 27. Juni 2024