ABAP - CL_BP_ABAP_JOB
This article is about the scheduling of jobs with the help of the class CL_BP_ABAP_JOB and why it is better to use the class than the function modules.
Table of contents
What is the first thing you think of when you think about scheduling jobs? Probably first to transaction SM36/7 or the function modules JOB_CREATE and JOB_SUBMIT? Today we will show you the class CL_BP_ABAP_JOB and how you can easily plan your own jobs with it.
Function modules
The first classic objects, the function modules, were very popular in the beginning, mainly because of the encapsulated and reusable logic. In the course of time, however, there were also disadvantages because, unlike classes, they are relatively rigid. If you want to report errors externally, you have to define numerous exceptions with which it was relatively difficult to return additional information. The interface and implementation in the source code are therefore in some cases even 30-50 lines only to call a function, which did not necessarily make the source code clearer. There were also disadvantages of the static structure and the fact that global data was still available after a call.
That is why SAP has started in many areas to pack function modules in classes (facade pattern) and to provide a (relatively) clean interface. The aim was to create lighter, publicly reusable APIs, which in many cases worked quite well.
CL_BP_ABAP_JOB
Another class is CL_BP_ABAP_JOB, which encapsulates the various function modules from the job scheduling area. But we can already tell you that the class was not developed 100% cleanly, but you can use it for simple planning.
DATA(lo_job) = NEW cl_bp_abap_job( ).
lo_job->set_name( 'CLASS_JOB_START' ).
lo_job->set_report( 'Z_TEST_REPORT' ).
lo_job->set_variant( 'TEST' ).
lo_job->set_effective_user( sy-uname ).
lo_job->set_language( sy-langu ).
lo_job->start_simple( ).
This is the simplest form of scheduling a job. In the first part, the class first needs the information on the job name, report and the variant that is to be executed. As a second step, the executing user is required and the language in which the job is to be scheduled. The job is then immediately scheduled and executed using the START_SIMPLE method.
Hint: The START_SIMPLE method does not offer any possibility of error handling; if not all parameters are filled, you as the caller do not receive any information about this. The job is scheduled when everything is okay. This method is sufficient for simple planning, but for more precise error handling you have to switch to our second variant.
Better scheduling
You can plan better and more precisely with the same class via the IF_BP_JOB_ENGINE interface, as more granular options are available here. Unfortunately, the methods are still equipped with the old exception handling, which makes handling not that "light". The beginning is similar to the simple scheduling, whereby you also have to set the job type that this is required (method SET_JOB_TYPE).
DATA(lo_job) = NEW cl_bp_abap_job( ).
lo_job->set_name( 'CLASS_JOB_START' ).
lo_job->set_job_type( cl_bp_const=>job_type_abap ).
lo_job->set_report( 'Z_TEST_REPORT' ).
lo_job->set_variant( 'TEST' ).
lo_job->set_effective_user( sy-uname ).
lo_job->set_language( sy-langu ).
lo_job->start_simple( ).
The next step is to cast the class on the interface IF_BP_JOB_ENGINE or address the interface directly via the class. We take this step for easier access to the methods. The job still needs a trigger, we set this with the method SET_TRG_TYPE and use the trigger for the start by date and time. The trigger is prepared in the next step and passed to the engine at the end.
DATA(lo_engine) = CAST if_bp_job_engine( lo_job ).
lo_job->set_trg_type( cl_bp_const=>trg_type_date ).
DATA(lo_trigger) = NEW cl_tc_date_trigger( ).
lo_trigger->set_sdlstrtdt( sy-datum ).
lo_trigger->set_sdlstrttm( CONV t( sy-uzeit + 30 ) ).
lo_engine->generate_job_count(
EXCEPTIONS
cant_create_job = 1
invalid_job_data = 2
jobname_missing = 3
OTHERS = 4
).
lo_engine->plan_job_step(
EXCEPTIONS
bad_priparams = 1
bad_xpgflags = 2
invalid_jobdata = 3
jobname_missing = 4
job_notex = 5
job_submit_failed = 6
program_missing = 7
prog_abap_and_extpg_set = 8
OTHERS = 9
).
lo_engine->release_job(
EXPORTING
i_trg_obj = lo_trigger
EXCEPTIONS
cant_start_immediate = 1
invalid_startdate = 2
jobname_missing = 3
job_close_failed = 4
job_nosteps = 5
job_notex = 6
lock_failed = 7
OTHERS = 8
).
In this step, we schedule the job for 30 seconds. In addition to the trigger CL_TC_DATE_TRIGGER, there is also the class CL_TC_EVT_TRIGGER to schedule a job that reacts to an event. As you can see, the classic exception handling is used here, which is not that nice to handle.
Exchangeable
Such API components, like this class, should basically also ensure that the underlying infrastructure can be exchanged without a lot of effort, without changing a lot of source code. Such constructs are ideally suited for migrations without having to exchange too much source code. DAOs (Data Access Objects) are also a popular pattern for such objects.
Conclusion
With the class presented today, you can easily carry out simple job scheduling and receive a light interface with minor errors. Suitable for a quick implementation and to keep your own code small and effective.