<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d34883048\x26blogName\x3dYour+Friendly+ABAPer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://friendlyabaper.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://friendlyabaper.blogspot.com/\x26vt\x3d-4712760677496349421', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Execute in Background – your way

Isn’t it nice of SAP to provide us with the option to execute the programs in background? Just go to the menu Program -> Execute in Background or, even easier, press [F9] button and – voila! – the program starts to run while you can get back to finding the next mine in the Minesweeper or something of not lesser importance. But, as Adrian Monk says, here is the thing: the users just can’t keep their paws off the Execute button and cannot be relied upon to execute the program only in the background.

My recent task was to create a program that would run in the background but could be easily initiated by an average Joe User. One of the options would be to create an event-triggered background job and a transaction with the sole purpose of triggering the event. But this looked like too much maintenance to me: I would have to set up the job, create the event and, on top of that, make sure it’s all done in at least 3 environments for testing. Being a very lazy person (which, I think, is a positive quality for a programmer) I decided to find an easier option.

After just a couple of hours of intensive search I stumbled upon a nice function module SUBST_START_REPORT_IN_BATCH. Turns out this beauty is easy to use and is pretty much foolproof. Here is the code that I used (it worked right from the first try, so there is no long story to tell today) to display the message to the user and run the program as a background job:
PARAMETERS: p_vkorg TYPE tvko-vkorg OBLIGATORY MEMORY ID vko.

DATA: rspar TYPE TABLE OF rsparams,
wa_rspar LIKE LINE OF rspar.

START-OF-SELECTION.

IF sy-batch IS INITIAL.

wa_rspar-selname = 'P_VKORG'.
wa_rspar-kind = 'P'.
wa_rspar-low = p_vkorg.
APPEND wa_rspar TO rspar.

CALL FUNCTION 'SUBST_START_REPORT_IN_BATCH'
EXPORTING
iv_repname = sy-repid
TABLES
tt_reportparam = rspar
EXCEPTIONS
variant_exist_check_failed = 1
variant_update_failed = 2
variant_update_not_authorized = 3
variant_update_no_report = 4
variant_update_no_variant = 5
variant_update_variant_locked = 6
variant_insert_failed = 7
variant_insert_not_authorized = 8
variant_insert_no_report = 9
variant_insert_variant_exists = 10
variant_insert_variant_locked = 11
variant_write_failed = 12
no_batch_service = 13
no_server_list = 14
batch_scheduling_failed = 15
OTHERS = 16.

IF sy-subrc = 0.
MESSAGE 'Background job has been initiated successfully'
TYPE 'I'.
ELSE.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

ELSE.

* place main program code here

ENDIF.
So what happens here – the user goes into transaction (I just created a Z... transaction for my report), hits Execute and the program goes into sy-batch IS INITIAL part. There it schedules itself in the background (I made the job name the same as the ABAP report name but it could be different), displays a message and stops. But when the background instance runs it goes into the ELSE condition where all the main code is executed.

RSPAR parameter must be filled in with the report parameters (there are also some more parameters for the variant activities). Unfortunately it is not described in the FM documentation how exactly it should be filled in, but you can find all the details in the SAP Help on this subject.

If you look into the function module’s code you’ll see that it is basically calling the FMs JOB_OPEN and JOB_CLOSE. Of course I could’ve also used them directly but I think that SUBST_START_REPORT_IN_BATCH FM is so much more convenient. While we are on it, here is a code fragment where I use the JOB_... function modules to schedule the output processing program RSNAST00 to run in the background for the specific documents (i_objky is filled elsewhere in the code):
PARAMETERS: p_vkorg TYPE tvko-vkorg OBLIGATORY MEMORY ID vko.

RANGES i_objky FOR nast-objky.

DATA: jobname TYPE tbtcjob-jobname,
jobcount TYPE tbtcjob-jobcount.

CONCATENATE p_vkorg '_PRINT_INVOICES' INTO jobname.
CLEAR jobcount.

CALL FUNCTION 'JOB_OPEN'
EXPORTING
jobname = jobname
IMPORTING
jobcount = jobcount.

IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

SUBMIT rsnast00
WITH p_again = space
WITH p_print = space
WITH p_sort = 10
WITH p_suff2 = space
WITH s_kappl = 'V3'
WITH s_nacha = '1'
WITH s_objky IN i_objky
VIA JOB jobname
NUMBER jobcount
AND RETURN.

* Close the job and run immediately
CALL FUNCTION 'JOB_CLOSE'
EXPORTING
jobcount = jobcount
jobname = jobname
strtimmed = 'X'. " Start immediately

IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
The key to success here is to keep the correct order (JOB_OPEN, SUBMIT... or JOB_SUBMIT, JOB_CLOSE) and not to forget jobcount / jobname everywhere. And in case you were wondering – the info on the background jobs is stored in the table TBTCO.

posted by Your Friendly ABAPer @ 15:23,
Direct link to this post