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

BTP - Application Job (Creation)

706

How do you create a new job in the system? In this article, we'll look at two methods for creating jobs.

Last week we gave you an introduction to the topic of application jobs and how jobs look and work in the cloud and the ABAP environment. In this article we'll look at how such a job is created and how we can then access it.

 

Introduction

Before we create the objects, we want to take a short excursion into the past. When the first jobs were introduced, the only way to create objects in the system was via the ABAP API. There is now also the option of creating all objects in the ADTs. We would like to show this option in more detail, as this is the standard way to create new ones.

 

Preparation

In our demo we will use a spreadsheet to log the runs and visualize information. The execution of the job cannot be easily debugged, so we primarily access this information to track past runs and their contents.

@EndUserText.label : 'Tracking for Jobs'
define table zbs_dmo_jtrack {
  key client     : abap.clnt not null;
  key identifier : sysuuid_x16 not null;
  content        : abap.char(200);
  test           : abap_boolean;
  rdate          : abap.dats;
  rtime          : abap.tims;
}

 

In the "Content" field we can store various content, the remaining fields are used for automatic filling from the values and from the context.

 

Creation (ADT)

The first creation is done via the ABAP Development Tools, ADT for short, and uses the standard ADT objects. To do this, we now create the following objects to define our first job.

 

Create class

First of all, we have to create the execution class, which will later implement the functionality to provide our job with parameters and be the entry point for execution. To do this, we also implement the two interfaces in the system:

  • IF_APJ_DT_EXEC_OBJECT - Providing the GET_PARAMETERS method to define the parameters of the job.
  • IF_APJ_RT_EXEC_OBJECT - Provision of the EXECUTE method that will be started later when the job is executed.

 

 

After executing and assigning the transport, the empty class is available, which we can now fill with content.

CLASS zcl_bs_demo_job_adt_exe DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_apj_dt_exec_object.
    INTERFACES if_apj_rt_exec_object.
ENDCLASS.


CLASS zcl_bs_demo_job_adt_exe IMPLEMENTATION.
  METHOD if_apj_dt_exec_object~get_parameters.
  ENDMETHOD.


  METHOD if_apj_rt_exec_object~execute.
  ENDMETHOD.
ENDCLASS.

 

Create parameters

In the next step we want to create some parameters in the job, which we later want to use for settings, but also to show how the job can be designed. The signature of the method and which tables are available to us:

 

First of all, we define some standard parameters that we want to use later in the job. To do this, we provide all the information in the table that better describes the fields and how they should work later.

et_parameter_def = VALUE #( datatype       = 'C'
                            changeable_ind = abap_true
                            ( selname       = 'TEXT'
                              kind          = if_apj_dt_exec_object=>parameter
                              param_text    = 'Free text'
                              length        = 50
                              lowercase_ind = abap_true
                              mandatory_ind = abap_true )
                            ( selname    = 'COUNTRY'
                              kind       = if_apj_dt_exec_object=>select_option
                              param_text = 'Country'
                              length     = 3 )
                            ( selname         = 'R_TEXT'
                              kind            = if_apj_dt_exec_object=>parameter
                              param_text      = 'Text'
                              length          = 1
                              radio_group_ind = abap_true
                              radio_group_id  = 'R1' )
                            ( selname         = 'R_LAND'
                              kind            = if_apj_dt_exec_object=>parameter
                              param_text      = 'Country'
                              length          = 1
                              radio_group_ind = abap_true
                              radio_group_id  = 'R1' )
                            ( selname      = 'TEST'
                              kind         = if_apj_dt_exec_object=>parameter
                              param_text   = 'Test'
                              length       = 1
                              checkbox_ind = abap_true ) ).

 

Some of the elements are better described:

  • SELNAME - Name of the field, may have a maximum of 8 characters.
  • KIND - Field is parameter or select option. In the interface IF_APJ_DT_EXEC_OBJECT there are the two constants that can be used for this.
  • PARAM_TEXT - Text of the parameter that should later appear in the app; translatable texts should be used here.
  • DATATYPE - Basic type with which the field is defined.
  • LENGTH - Length of the field for later entries in the mask.
  • DECIMALS - Number of decimal places if a decimal data type is used.
  • LOWERCASE_IND - Set to ABAP_TRUE if the content of the field should support upper/lower case.
  • CHECKBOX_IND - Set to ABAP_TRUE if the field should be displayed as a checkbox.
  • RADIO_GROUP_IND - Set to ABAP_TRUE if the field should be displayed as a radio button.
  • RADIO_GROUP_ID - All fields in a group (radio buttons) should have the same ID.
  • MANDATORY_IND - Set to ABAP_TRUE if the field should be a mandatory field. Then an entry is always necessary.

 

Finally, we define some suggested values that will later be incorporated into the template.

et_parameter_val = VALUE #( sign   = 'I'
                            option = 'EQ'
                            ( selname = 'TEST' low = abap_true )
                            ( selname = 'R_TEXT' low = abap_false )
                            ( selname = 'R_LAND' low = abap_true ) ).

 

After generating all objects, the parameter image then looks like this. Our default values are set (checkbox and radio buttons) and the text is defined as a mandatory field. However, the input can only be tested after the “Job Template” step.

 

Job catalog

If you have a corresponding package or have created a new package, you can now create the job catalog. This defines the wrapper for the executable class and the settings that can be defined for startup. To do this, right-click on the package and search for the “Job Catalog” via “New -> Other ABAP Repository Object”.

 

The execution class is a mandatory field and is required to create the catalog. After filling out the information, the wizard can be completed.

 

There are various exits available in the job catalog, which we will take a closer look at in the next article. From here you can also jump to the executive class.

 

Job template

However, before we find the job in the "Application Jobs" app, we first have to create a template. As with the job catalog, we can do this via the wizard as a new object, which is an object of type "Application Job Template".

 

The template is created and you will find all defined elements of the parameters in the list. The suggested values for the template are saved there and loaded when executed.

 

A message will now be displayed that the mandatory parameter is not preset, but we can still activate the object. The check is particularly relevant when scheduling the job.

 

Logic

However, the most important part of the job is the execution logic, we haven't taken this into account yet and still have to implement it in our class. To do this, we go into the class and expand the logic by two steps.

 

Parse parameters

In the first step we receive all inputs as a table and should prepare them for our process. This step is optional, but can provide more clarity for the subsequent steps. First of all, we define fields that hold the contents of our parameters.

DATA ld_text TYPE c LENGTH 50.
DATA lt_r_country TYPE RANGE OF I_Country-Country.
DATA ld_radio_text TYPE abap_boolean.
DATA ld_radio_country TYPE abap_boolean.
DATA ld_test TYPE abap_boolean.

 

Now we can parse the contents of the table and distribute them to the different fields. For parameters, a simple assignment of the content is sufficient; for SELECT-OPTIONS we have to append each line, as there can be more entries that belong to a select option.

LOOP AT it_parameters INTO DATA(ls_parameter).
  CASE ls_parameter-selname.
    WHEN 'TEXT'.
      ld_text = ls_parameter-low.
    WHEN 'COUNTRY'.
      INSERT CORRESPONDING #( ls_parameter ) INTO TABLE lt_r_country.
    WHEN 'R_TEXT'.
      ld_radio_text = ls_parameter-low.
    WHEN 'R_LAND'.
      ld_radio_country = ls_parameter-low.
    WHEN 'TEST'.
      ld_test = ls_parameter-low.
  ENDCASE.
ENDLOOP.

 

Hint: The names of the parameters can have a maximum of 8 characters; there are obviously still dependencies on real selection screens. It is recommended to use a constant interface to define the parameters and resolve them into variables.

 

Execute logic

Now that all content has been distributed to variables, we can now start implementing the actual logic. This is a demo logic, it can just as easily be called another class or method, for simplicity we will do this in the same method. In the first step, we fill the standard fields for each data record.

DATA(ls_database) = VALUE zbs_dmo_jtrack( identifier = cl_system_uuid=>create_uuid_x16_static( )
                                          rdate      = cl_abap_context_info=>get_system_date( )
                                          rtime      = cl_abap_context_info=>get_system_time( )
                                          test       = ld_test ).

 

Then we choose which logic to execute. If the radio button is set for text, then we adopt the text, otherwise the countries are read via the selection and the names are adopted as a comma-separated list.

CASE abap_true.
  WHEN ld_radio_text.
    ls_database-content = ld_text.

  WHEN ld_radio_country.
    SELECT FROM I_CountryText
      FIELDS CountryName
      WHERE Country IN @lt_r_country
        and Language = @sy-langu
      INTO TABLE @DATA(lt_names).

    ls_database-content = concat_lines_of( table = lt_names sep = `, ` ).

ENDCASE.

 

Finally, we write the new data record to the database so that we can later check the run and whether the logic and the transfer worked properly.

INSERT zbs_dmo_jtrack FROM @ls_database.
COMMIT WORK.

 

Application Jobs

Now that we have created the class, the catalog and the template, we can go to the “Application Jobs” app to check the result of the generation and start our first job. We can now select the job template using the search help.

 

We set the execution to “Immediate” to get the result immediately. Now we can see our parameters for the first time and make the appropriate entries for the job.

 

The job starts accordingly via “Schedule”. Now we carry out a second run, but set the test indicator and to text in order to see changes in the result. After the two jobs have run, we can look at our logging table.

 

Complete example

Here is the complete implementation of the job class again, so you can recreate this job in your system.

CLASS zcl_bs_demo_job_adt_exe DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_apj_dt_exec_object.
    INTERFACES if_apj_rt_exec_object.
ENDCLASS.


CLASS zcl_bs_demo_job_adt_exe IMPLEMENTATION.
  METHOD if_apj_dt_exec_object~get_parameters.
    et_parameter_def = VALUE #( datatype       = 'C'
                                changeable_ind = abap_true
                                ( selname       = 'TEXT'
                                  kind          = if_apj_dt_exec_object=>parameter
                                  param_text    = 'Free text'
                                  length        = 50
                                  lowercase_ind = abap_true
                                  mandatory_ind = abap_true )
                                ( selname    = 'COUNTRY'
                                  kind       = if_apj_dt_exec_object=>select_option
                                  param_text = 'Country'
                                  length     = 3 )
                                ( selname         = 'R_TEXT'
                                  kind            = if_apj_dt_exec_object=>parameter
                                  param_text      = 'Text'
                                  length          = 1
                                  radio_group_ind = abap_true
                                  radio_group_id  = 'R1' )
                                ( selname         = 'R_LAND'
                                  kind            = if_apj_dt_exec_object=>parameter
                                  param_text      = 'Country'
                                  length          = 1
                                  radio_group_ind = abap_true
                                  radio_group_id  = 'R1' )
                                ( selname      = 'TEST'
                                  kind         = if_apj_dt_exec_object=>parameter
                                  param_text   = 'Test'
                                  length       = 1
                                  checkbox_ind = abap_true ) ).

    et_parameter_val = VALUE #( sign   = 'I'
                                option = 'EQ'
                                ( selname = 'TEST' low = abap_true )
                                ( selname = 'R_TEXT' low = abap_false )
                                ( selname = 'R_LAND' low = abap_true ) ).
  ENDMETHOD.


  METHOD if_apj_rt_exec_object~execute.
    DATA ld_text          TYPE c LENGTH 50.
    DATA lt_r_country     TYPE RANGE OF I_CountryText-Country.
    DATA ld_radio_text    TYPE abap_boolean.
    DATA ld_radio_country TYPE abap_boolean.
    DATA ld_test          TYPE abap_boolean.

    LOOP AT it_parameters INTO DATA(ls_parameter).
      CASE ls_parameter-selname.
        WHEN 'TEXT'.
          ld_text = ls_parameter-low.
        WHEN 'COUNTRY'.
          INSERT CORRESPONDING #( ls_parameter ) INTO TABLE lt_r_country.
        WHEN 'R_TEXT'.
          ld_radio_text = ls_parameter-low.
        WHEN 'R_LAND'.
          ld_radio_country = ls_parameter-low.
        WHEN 'TEST'.
          ld_test = ls_parameter-low.
      ENDCASE.
    ENDLOOP.

    DATA(ls_database) = VALUE zbs_dmo_jtrack( identifier = cl_system_uuid=>create_uuid_x16_static( )
                                              rdate      = cl_abap_context_info=>get_system_date( )
                                              rtime      = cl_abap_context_info=>get_system_time( )
                                              test       = ld_test ).

    CASE abap_true.
      WHEN ld_radio_text.
        ls_database-content = ld_text.

      WHEN ld_radio_country.
        SELECT FROM I_CountryText
          FIELDS CountryName
          WHERE Country IN @lt_r_country
            and Language = @sy-langu
          INTO TABLE @DATA(lt_names).

        ls_database-content = concat_lines_of( table = lt_names sep = `, ` ).

    ENDCASE.

    INSERT zbs_dmo_jtrack FROM @ls_database.
    COMMIT WORK.
  ENDMETHOD.
ENDCLASS.

 

Creation (API)

There is also an ABAP API in the system for creating objects, which was mainly used at times when the ABAP development tools did not yet support the objects for the jobs. However, you also need the execution class for the job before you can use the API to generate the catalog and template. Here's a piece of example code:

CLASS zcl_bs_demo_poc_job_cre DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
ENDCLASS.


CLASS zcl_bs_demo_poc_job_cre IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    CONSTANTS lc_transport TYPE cl_apj_dt_create_content=>ty_transport_request VALUE '<TRANSPORT_NUMBER>'.
    CONSTANTS lc_package   TYPE cl_apj_dt_create_content=>ty_package           VALUE '<PACKAGE_NAME>'.

    TRY.
        DATA(lo_dt) = cl_apj_dt_create_content=>get_instance( ).

        lo_dt->create_job_cat_entry( iv_catalog_name       = 'ZBS_DEMO_POC_JOB_CATAPI'
                                     iv_class_name         = 'ZCL_BS_DEMO_POC_JOB_EXE'
                                     iv_text               = 'DEMO: Job API'
                                     iv_catalog_entry_type = cl_apj_dt_create_content=>class_based
                                     iv_transport_request  = lc_transport
                                     iv_package            = lc_package ).
        out->write( |Job catalog entry created successfully| ).

      CATCH cx_apj_dt_content INTO DATA(lo_apj_dt_content).
        out->write( |Creation of job catalog entry failed: { lo_apj_dt_content->get_text( ) }| ).
    ENDTRY.

    TRY.
        NEW zcl_bs_demo_job_adt_exe( )->if_apj_dt_exec_object~get_parameters(
          IMPORTING et_parameter_val = DATA(lt_parameters) ).

        IF 1 = 1.
          lo_dt->create_job_template_entry( iv_template_name     = 'ZBS_DEMO_POC_JOB_TEMPAPI'
                                            iv_catalog_name      = 'ZBS_DEMO_POC_JOB_CATAPI'
                                            iv_text              = 'DEMO: Job API'
                                            it_parameters        = lt_parameters
                                            iv_transport_request = lc_transport
                                            iv_package           = lc_package ).
          out->write( |Job template created successfully| ).

        ELSE.
          lo_dt->delete_job_template_entry( iv_template_name     = 'ZBS_DEMO_JOB_TEMPLATE_DEFAULT'
                                            iv_transport_request = lc_transport ).
          out->write( |Job template deleted successfully| ).

        ENDIF.

      CATCH cx_apj_dt_content INTO lo_apj_dt_content.
        out->write( |Creation of job template failed: { lo_apj_dt_content->get_text( ) }| ).
        RETURN.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

 

The code calls the API and first creates the job catalog. In the second step, the parameters are read from the execution class and the template is generated, but the API does not set any default values in the template.

 

Hint: Creating a job catalog and template via the API is only recommended to a limited extent; you should use the standard tools in ADT, as the latest features are always implemented here.

 

Conclusion

There are a few steps and objects required to create a job, but in the end everything is much easier than you think and you have a very clear way to create jobs for tasks. The parameters give you maximum flexibility for input from outside; these are very similar to the selection screens of reports.


Included topics:
BTPApplication JobABAP Environment
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


RAP - Deep Action in OData v4

Category - ABAP

In this article we will look at actions with deep structures, how we can create them and pass data to an API endpoint.

05/24/2024

BTP - Business Configuration (Adaptation)

Category - ABAP

What do adjustments to the RAP business object actually look like in the context of the business configuration? More information in this article.

05/17/2024

BTP - Business Configuration (without Transport)

Category - ABAP

How do you actually use the Business Configuration without the transport recording? In this article we clarify whether it is possible.

05/07/2024

BTP - Business Configuration (Usage)

Category - ABAP

Today it's about using the various apps and transporting the business configuration in the ABAP environment.

05/03/2024

BTP - Business Configuration (Creation)

Category - ABAP

This article is about creating maintenance views in the ABAP environment to maintain data and later transport the settings.

04/26/2024