← Back to Clean Core Architecture Hub
CLEAN CORE ARCHITECTURAL GUIDE #13

SAP Application Jobs & Background Scheduling Architecture

Author: Andrea Antonio Perrelli Scope: SAP S/4HANA Cloud (Public & Private) & On-Premise 2022+ Framework: Application Jobs Framework (cl_apj_rt_api)
Core Clean Core Shift: In classic SAP ERP, batch processing relied on procedural reports (REPORT statements with PARAMETERS / SELECT-OPTIONS) and transactions SM36/SM37. In modern ABAP Cloud, classic reports are deprecated and transaction SM36 is obsolete. Background processing is executed through the Application Jobs Framework using object-oriented classes and contract-released APIs.
Limited Time Deal

Master S/4HANA Clean Core Architecture & Extensibility

Get the Complete SAP Enterprise Architecture Suite: 40 Retina architecture diagrams, 61 production-grade code listings, and decision frameworks. Use code FLASH80 at checkout for 80% OFF.

1. Architectural Comparison: Classic Batch vs. Application Jobs

Architectural Dimension Classic SAP ECC / R/3 Batch ABAP Cloud Application Jobs (Clean Core)
Implementation Unit Procedural executable REPORT in SE38/SE80 Global ABAP Class implementing if_apj_rt_exec_object
Parameter Interface Dynpro selection screens (PARAMETERS, SELECT-OPTIONS) Design-time interface if_apj_dt_exec_object
Job Definition Artifact Manual transaction SM36 entry Eclipse ADT Job Catalog Entry & Job Template
Programmatic Scheduling CALL FUNCTION 'JOB_OPEN', JOB_SUBMIT, JOB_CLOSE Released API cl_apj_rt_api=>schedule_job( ) (Contract C1)
Logging & Spool Classic spool requests (WRITE) & job log (MESSAGE) Unified Application Log cl_bali_log linked to Fiori Job Log
Monitoring UI SAP GUI transaction SM37 SAP Fiori App Application Jobs (F1240)
Clean Core Level Level D (Technical Debt) Level A (100% Cloud Compliant)

2. The Three Pillars of an Application Job

An Application Job in ABAP Cloud is composed of three distinct artifacts that work in synchronization:

  1. The Execution Class: A global ABAP class that implements:
    • if_apj_dt_exec_object: Declares parameters, default values, and value helps at design time.
    • if_apj_rt_exec_object: Receives runtime parameter values and executes business logic.
  2. The Job Catalog Entry: An ADT metadata artifact (type APJC) that connects the technical execution class to the SAP Fiori Application Jobs engine.
  3. The Job Template: An ADT configuration artifact (type APJT) that defines preset default values and parameter visibility for end users.

3. Production Implementation: The Job Execution Class

Below is a complete, production-grade implementation of a clean core Application Job execution class that handles runtime parameters, executes business processing, and writes structured messages to the Application Log:

" =====================================================================
" CLASS: ZCL_APJ_INVOICE_RECON
" Architecture: SAP Application Job with Structured Application Logging
" Language Version: ABAP Cloud (Language Version 5)
" =====================================================================
CLASS zcl_apj_invoice_recon DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_apj_dt_exec_object. " Design-Time Interface (Parameters)
    INTERFACES if_apj_rt_exec_object. " Runtime Interface (Execution)
ENDCLASS.

CLASS zcl_apj_invoice_recon IMPLEMENTATION.

  METHOD if_apj_dt_exec_object~get_parameters.
    " 1. Define input parameters exposed to SAP Fiori Job Scheduling
    et_parameter_def = VALUE #(
      ( selname = 'P_BUKRS' kind = if_apj_dt_exec_object=>parameter datatype = 'C' length = 4 param_text = 'Company Code' )
      ( selname = 'P_TEST'  kind = if_apj_dt_exec_object=>parameter datatype = 'C' length = 1 param_text = 'Test Run (No Commit)' )
    ).

    " 2. Provide default values
    et_parameter_val = VALUE #(
      ( selname = 'P_BUKRS' kind = if_apj_dt_exec_object=>parameter sign = 'I' opt = 'EQ' low = '1000' )
      ( selname = 'P_TEST'  kind = if_apj_dt_exec_object=>parameter sign = 'I' opt = 'EQ' low = 'X' )
    ).
  ENDMETHOD.

  METHOD if_apj_rt_exec_object~execute.
    DATA: lv_bukrs TYPE c LENGTH 4,
          lv_test  TYPE abap_boolean.

    " 1. Extract parameters from runtime container
    LOOP AT it_parameters INTO DATA(ls_param).
      CASE ls_param-selname.
        WHEN 'P_BUKRS'. lv_bukrs = ls_param-low.
        WHEN 'P_TEST'.  lv_test  = xsdbool( ls_param-low = 'X' ).
      ENDCASE.
    ENDLOOP.

    " 2. Initialize Clean Core Application Log
    TRY.
        DATA(lo_log) = cl_bali_log=>create_with_header(
                         header = cl_bali_header_setter=>create(
                                    object      = 'ZFIN_RECON'
                                    subobject   = 'BATCH'
                                    external_id = |RECON_{ cl_abap_context_info=>get_system_date( ) }|
                                  )
                       ).

        lo_log->add_item(
          item = cl_bali_message_setter=>create(
                   severity   = if_bali_constants=>c_severity_status
                   id         = 'ZAPJ_MSG'
                   number     = '001'
                   variable_1 = CONV #( lv_bukrs )
                 )
        ).

        " 3. Execute business logic via released CDS View Entities
        SELECT CompanyCode, AccountingDocument, FiscalYear, TotalGrossAmountInTransacCrcy
          FROM I_JournalEntry
          WHERE CompanyCode = @lv_bukrs
            AND IsReversed  = @abap_false
          INTO TABLE @DATA(lt_entries)
          UP TO 500 ROWS.

        lo_log->add_item(
          item = cl_bali_message_setter=>create(
                   severity   = if_bali_constants=>c_severity_status
                   id         = 'ZAPJ_MSG'
                   number     = '002'
                   variable_1 = CONV #( lines( lt_entries ) )
                 )
        ).

        " 4. Commit Application Log to SAP Fiori Application Jobs app
        cl_bali_log_db=>get_instance( )->save_log(
          log                       = lo_log
          assign_to_current_appl_job = abap_true
        ).

      CATCH cx_bali_runtime INTO DATA(lx_err).
        " Log exception if logging engine encounters an error
    ENDTRY.
  ENDMETHOD.

ENDCLASS.

4. Programmatic Job Scheduling via cl_apj_rt_api

In many enterprise scenarios, background jobs must be triggered dynamically by business events, RAP actions, or API webhooks rather than manual scheduling in Fiori. The released API cl_apj_rt_api=>schedule_job provides full programmatic control:

" Trigger immediate or periodic job programmatically from an action handler
DATA: ls_start_info TYPE cl_apj_rt_api=>ty_start_info,
      lt_params     TYPE cl_apj_rt_api=>tt_job_parameter_value.

" Immediate background execution
ls_start_info-start_immediately = abap_true.

" Bind dynamic parameters
lt_params = VALUE #(
  ( name = 'P_BUKRS' t_value = VALUE #( ( sign = 'I' option = 'EQ' low = '1000' ) ) )
  ( name = 'P_TEST'  t_value = VALUE #( ( sign = 'I' option = 'EQ' low = '' ) ) )
).

TRY.
    cl_apj_rt_api=>schedule_job(
      EXPORTING
        iv_job_template_name   = 'ZTEMPL_INVOICE_RECON'
        iv_job_text            = 'Automated End-of-Day Settlement Batch'
        is_start_info          = ls_start_info
        it_job_parameter_value = lt_params
      IMPORTING
        ev_jobname             = DATA(lv_name)
        ev_jobcount            = DATA(lv_id)
    ).
  CATCH cx_apj_rt INTO DATA(lx_apj).
    " Handle scheduling failure cleanly
ENDTRY.

5. Governance & Clean Core Rules for Background Jobs

Recommended Clean Core Developer Tools

Explore free client-side interactive utilities to accelerate your S/4HANA migration:

⏱️ Application Job Generator 🔢 Number Range Generator 🧭 Decision Wizard & ADR 🎯 Readiness Assessment

Accelerate Your SAP Transformation

Get complete architectures, downloadable code listings, and decision frameworks in the official handbooks.