BTP - Application Job (Exit Check)
What can you use the exits in the application job for and how are they defined? You can find out more about this in this article.
Table of contents
In the last article we looked at creating the application job and built our first executable job. We have already noticed the first exits in the job catalog. In this article we want to take a closer look at these and what we can do with them.
Introduction
After creating the job catalog, we end up in the form and the object is available in the ABAP Development Tools. In the upper section we find our execution class, in which the parameters and the execution are defined.
In the lower section there are three exits available for checks, value help and notifications. In this article we will introduce you to the exams in more detail.
Creation
The checks take care of validating the input parameters when scheduling the job and provide the user with feedback in the form of messages if incorrect, empty or different values are entered. There are two ways to implement the check:
- New creation of a test class
- Choose an existing class
In the second way, the class can be added using the "Browse" button or the Content Assist (CTRL + Spacebar). In the first way, all you need to do is click on the corresponding exit name to start the wizard for creating the class.
We now store the name of the class and the description there and complete the generation. The class is created in the system but has no implementations or interfaces.
Therefore, there should be an error message in the job catalog, which unfortunately is not very specific, but only outputs the message: "Check class ... is invalid". Basically, the corresponding interface is now missing in the class to implement the checks. The interface IF_APJ_JT_CHECK was used in the past, but this is now deprecated.
Therefore, we use the new interface IF_APJ_JT_CHECK_20 to implement the checks. After implementation, you will notice that the quick fix (CTRL + 1) for the interface does not work. This is because the methods in the interface were implemented using DEFAULT IGNORE. Accordingly, our class now looks emptier:
CLASS zcl_bs_demo_job_adt_chk DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_apj_jt_check_20.
ENDCLASS.
CLASS zcl_bs_demo_job_adt_chk IMPLEMENTATION.
ENDCLASS.
To implement a method, you just have to define it in the class implementation and then fill it with source code.
METHOD if_apj_jt_check_20~check_and_adjust.
ENDMETHOD.
Methods
In this section you will learn more about the individual methods, their function and effect. We will address the most important ones first.
CHECK_AND_ADJUST
The method takes care of checking the entries and can generate messages that alert the user to errors. However, the user's entries can also be overwritten or corrected, for example if certain values should be converted into correctly formatted values. We receive information from outside such as:
- Current user
- Current job catalog
- Parameters (meta information, characteristics)
Our sample implementation will give you an idea of how it works:
DATA(ld_country) = ct_value[ KEY param parameter_name = 'R_LAND' ]-low.
DATA(lt_country) = FILTER #( ct_value USING KEY param WHERE parameter_name = CONV #( 'COUNTRY' ) ).
IF ld_country = abap_true AND lt_r_country IS INITIAL.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '001' ) INTO TABLE et_msg.
ELSE.
ev_successful = abap_true.
ENDIF.
We first read the radio button R_LAND and then filter all entries to COUNTRY so that we can then check these values. For reasons of clarity, we do not handle errors if no entries are found. If the radio button is selected and there are no entries as a filter, an error message is transferred to the ET_MSG table. If no errors were found, the EV_SUCCESSFUL flag should be set to ABAP_TRUE so that the check knows that everything was checked successfully.
The check is called in the “Application Jobs” app via the “Check” and “Schedule” buttons, i.e. when the check is called explicitly or implicitly by scheduling the job. In the event of an error, the messages are displayed and scheduling is aborted.
INITIALIZE
As the name of the method suggests, it is called when the parameters are loaded for display for the first time. Default values from the template can be overwritten. The method is only called once, right at the start, and you receive the same information as with the CHECK_AND_ADJUST method. You can now adjust the values accordingly in CT_VALUE, but there will be no entries if the values have not been preset in the template.
TRY.
ct_value[ KEY param parameter_name = 'TEXT' ]-low = 'Init with Event'.
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( parameter_name = 'TEXT' sign = 'I' option = 'EQ' low = 'Init with Event' ) INTO TABLE ct_value.
ENDTRY.
TRY.
ct_value[ KEY param parameter_name = 'TEST' ]-low = abap_false.
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( parameter_name = 'TEST' sign = 'I' option = 'EQ' low = abap_false ) INTO TABLE ct_value.
ENDTRY.
In our example coding we want to preassign the value of the text, which is empty in the standard version, so we have to go through the first CATCH to accept the new parameter. We no longer want to set the test flag for the second parameter, so that the checkbox is always empty when starting. Since a default value is already set here, it still needs to be overwritten. However, it is always advisable to react to both situations. We then see the end result in the “Application Jobs” app when scheduling the job.
GET_DYNAMIC_PROPERTIES
The method can dynamically adjust parameters in the app; the options READ-ONLY or HIDDEN are available. The individual fields can be controlled depending on the parameters set. The method is called during initialization, but also after every "check". Currently it is not possible to call the method when a parameter value is changed, so this should be handled with care.
DATA(ls_radiobutton_text) = VALUE #( it_value[ KEY param parameter_name = 'R_TEXT' ] OPTIONAL ).
IF ls_radiobutton_text-low = abap_false.
INSERT VALUE #( job_parameter_name = 'TEXT' read_only_ind = abap_true ) INTO TABLE rts_dynamic_property.
ELSE.
INSERT VALUE #( job_parameter_name = 'TEXT' read_only_ind = abap_false ) INTO TABLE rts_dynamic_property.
ENDIF.
In the example above, we read the current value for the radio button for the text and then check whether it is set. If it is not set, then we set the text field to display. Here it is important to reset the status again, as the system remembers the current status. So if the field is to be opened again, the entry must be set to ABAP_FALSE.
The radio button is at the top for Country, so the text field is now blocked. If we now set the radio button to text and press the “Check” button, the logic is run through again and the image changes.
CHECK_AUTHORIZATIONS
Here you have the option of carrying out an authorization check if you want to reference users or entries that are not covered by the general authorization for the job. As always, you get access to the current values in the input, the current user or the job catalog for differentiation. The method is called during checking and scheduling.
ev_successful = abap_true.
IF iv_username = 'CB9980000000'.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '002' message_v1 = iv_username ) INTO TABLE et_msg.
CLEAR ev_successful.
ENDIF.
Here you can carry out authorization checks in various ways. In our simple example we check that a specific user cannot carry out the job. If the check was successful, the EV_SUCCESSFUL flag should definitely be set or simply set first for simplicity if several checks follow. You then receive the error message in the scheduling.
CHECK_START_CONDITION
The last method checks the start conditions when scheduling the job. However, it is not run during the "check", but only when the "Schedule" is carried out. Here you have the opportunity to check the scheduling criteria again and prevent the job from being scheduled.
IF is_schedule_info-periodic_granularity IS NOT INITIAL.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '003' ) INTO TABLE et_msg.
ev_incorrect = abap_true.
ENDIF.
In this example we do not allow recurring scheduling, only a one-time execution. To do this, we check the PERIODIC_GRANULARITY field in the execution values. If a value is stored there, we issue a corresponding error message and set the EV_INCORRECT flag to ABAP_TRUE.
Other methods
We have not examined the following methods in more detail or provided any examples, but we would still like to explain the function to you here:
- CHECK_AND_ADJUST_PARAMETER - Called when the user changes parameters in order to check or, if necessary, adjust the values.
- ADJUST_READ_ONLY - Adjust values for fields that are set to display only.
- ADJUST_HIDDEN - Adjust values for hidden fields.
You can also find some of the usage and documentation in ABAP Doc in the interface, in case you get stuck with the implementation. Otherwise, an empty implementation also helps to set a breakpoint and look at the variables/contents in the debugger.
Complete example
Here again is the complete test class from today's article for readjustment in your system.
CLASS zcl_bs_demo_job_adt_chk DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_apj_jt_check_20.
ENDCLASS.
CLASS zcl_bs_demo_job_adt_chk IMPLEMENTATION.
METHOD if_apj_jt_check_20~check_and_adjust.
DATA(ld_country) = ct_value[ KEY param parameter_name = 'R_LAND' ]-low.
DATA(lt_country) = FILTER #( ct_value USING KEY param WHERE parameter_name = CONV #( 'COUNTRY' ) ).
IF ld_country = abap_true AND lt_country IS INITIAL.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '001' ) INTO TABLE et_msg.
ELSE.
ev_successful = abap_true.
ENDIF.
ENDMETHOD.
METHOD if_apj_jt_check_20~initialize.
TRY.
ct_value[ KEY param parameter_name = 'TEXT' ]-low = 'Init with Event'.
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( parameter_name = 'TEXT' sign = 'I' option = 'EQ' low = 'Init with Event' ) INTO TABLE ct_value.
ENDTRY.
TRY.
ct_value[ KEY param parameter_name = 'TEST' ]-low = abap_false.
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( parameter_name = 'TEST' sign = 'I' option = 'EQ' low = abap_false ) INTO TABLE ct_value.
ENDTRY.
ENDMETHOD.
METHOD if_apj_jt_check_20~get_dynamic_properties.
DATA(ls_radiobutton_text) = VALUE #( it_value[ KEY param parameter_name = 'R_TEXT' ] OPTIONAL ).
IF ls_radiobutton_text-low = abap_false.
INSERT VALUE #( job_parameter_name = 'TEXT' read_only_ind = abap_true ) INTO TABLE rts_dynamic_property.
ELSE.
INSERT VALUE #( job_parameter_name = 'TEXT' read_only_ind = abap_false ) INTO TABLE rts_dynamic_property.
ENDIF.
ENDMETHOD.
METHOD if_apj_jt_check_20~check_authorizations.
ev_successful = abap_true.
IF iv_username = 'CB9980000000'.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '002' message_v1 = iv_username ) INTO TABLE et_msg.
CLEAR ev_successful.
ENDIF.
ENDMETHOD.
METHOD if_apj_jt_check_20~check_start_condition.
IF is_schedule_info-periodic_granularity IS NOT INITIAL.
INSERT VALUE #( id = 'ZBS_DEMO_JTUTORIAL' type = 'E' number = '003' ) INTO TABLE et_msg.
ev_incorrect = abap_true.
ENDIF.
ENDMETHOD.
ENDCLASS.
Conclusion
The check exit is one of the most extensive and therefore requires a lot more explanation. We hope the article helped you to better understand the individual methods and the implementation. This allows you to make the application job even more robust and make better use of the various functions.