The delivered process type ABAP has the disadvantage that it does not return a defined state if execution was successful or not. But often you want to react properly at the end of the ABAP program and continue with loading or in case of error do some cleanup or at least stop the chain.
I want to show you step by step how you can create easily your own process type for ABAP that returns either successful or not for use in process chains. All code is below. All you need is the excellent Howto-Paper for creating your own process type: http://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/509f3ae6-e36e-2910-48a8-ab43dc167...
Download i. It's really highly recommended to implement your own process types.
Step 1.) Create a return value table
Go to table maintenance, e.g SE 11 and create table ZABAP_STATUS.
Enter a short description for this table, e.g. Table for use in process type ZCL_ABAP_RC. Enter delivery type A. Create fields as described below:
Set the technical settings described below:
Save and activate. Ignore the warnings at activation.
Step 2.) Create your own process type class
Open Class builder (SE24) and enter name of new class for process type e.g. ZCL_ABAP_RC.
In the popup choose class.
Now switch to properties tab and enter type group RS under forward declarations.
Switch to the ‘Interface’ tab strip, and specify the following interfaces:
- IF_RSPC_EXECUTE Mandatory interface, which is called on the execution of the
process type
- IF_RSPC_GET_VARIANT Optional interface for the selection of the variants
- IF_RSPC_MAINTAIN Optional interface for the maintenance of the variants (in our
case call of the Process Chain maintenance)
Switch to the ‘Methods’ tab strip. To satisfy the minimum requirements implement the following methods, e.g. press redefine button and enter code:
- IF_RSPC_GET_VARIANT~GET_VARIANT Pick Process Chain from custom table
CALL METHOD cl_rspc_variant=>f4
EXPORTING
i_type = 'ABAP'
i_variant = i_variant
i_objvers = i_objvers
i_t_select = i_t_select
i_allow_new = rs_c_false
IMPORTING
e_variant = e_variant
e_variant_text = e_variant_text
EXCEPTIONS
aborted = 1
nothing_found = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
RAISING nothing_selected.
ENDIF.
- IF_RSPC_GET_VARIANT ~EXISTS Indicate variant exist (for syntax check of whole Process Chain)
CALL METHOD cl_rspc_variant=>exists
EXPORTING
i_type = 'ABAP'
i_variant = i_variant
RECEIVING
r_exists = r_exists.
- IF_RSPC_EXECUTE~GIVE_CHAIN
return = rs_c_false.
- IF_RSPC_MAINTAIN~GET_HEADER Define title for variant
DATA: l_r_variant TYPE REF TO cl_rspc_variant,
l_s_attrib TYPE rspcvariantattr,
l_s_text TYPE rspcvariantt.
CALL METHOD cl_rspc_variant=>create
EXPORTING
i_type = 'ABAP'
i_variant = i_variant
i_objvers = i_objvers
i_no_transport = rs_c_true
- IF_RSPC_MAINTAIN~MAINTAIN
PERFORM displaymode_set IN PROGRAM saplrspc_processes USING i_display_only.
CALL FUNCTION 'RSPC_VARIANT_MAINTAIN'
EXPORTING
i_type = 'ABAP'
i_objvers = 'A'
i_dynnr = '0200'
i_repid = 'SAPLRSPC_PROCESSES'
i_callback_at_exit = 'ABAP_CHANGED'
i_variant = i_variant
i_display_only = i_display_only
EXCEPTIONS
aborted = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'I' NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
EXIT.
ENDIF.
CALL FUNCTION 'RSPC_VARIANT_GET'
IMPORTING
e_variant = e_variant
e_variant_text = e_variant_text.
- IF_RSPC_GET_VARIANT~WILDCARD_ENABLED returns just ‘X’
result = 'X'.
- IF_RSPC_EXECUTE~EXECUTE Performs the check against custom table
This method is executed when the process chain runs. The coding is taken from the ABAP process type. You can find all the coding in class CL_RSPC_ABAP. In this method you find the part where the hand-over of the ABAP program to the process chain takes place:
DATA: l_uid TYPE sysuuid_25,
l_r_variant TYPE REF TO cl_rspc_variant,
l_t_info TYPE TABLE OF rspcvariant,
l_s_info TYPE rspcvariant,
l_program TYPE programm,
l_progvari TYPE raldb_vari,
l_event TYPE btceventid,
l_param TYPE btcevtparm,
l_dest TYPE rfcdest,
l_msg(100) TYPE c,
l_s_log TYPE rspcabapasync,
l_chainid TYPE rspc_chain,
l_pripar TYPE pri_params,
l_t_values type table of RSPARAMS,
l_s_value type RSPARAMS,
l_arcpar TYPE arc_params.
* ==== Makro for abnormal ending ====
DEFINE log_abort.
call function 'RSSM_GET_TIME'
importing
e_timestamps = l_s_log-timestamp.
l_s_log-state = 'X'.
modify rspcabapasync from l_s_log.
call function 'DB_COMMIT'.
END-OF-DEFINITION.
* ==== Get Instance ====
CALL FUNCTION 'RSSM_UNIQUE_ID'
IMPORTING
e_uni_idc25 = l_uid.
e_instance = l_uid.
* ==== get variant ====
CALL METHOD cl_rspc_variant=>create
EXPORTING
i_type = 'ABAP'
i_variant = i_variant
i_no_transport = rs_c_true
RECEIVING
r_r_variant = l_r_variant
EXCEPTIONS
locked = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
EXIT.
ENDIF.
CALL METHOD l_r_variant->get_info
IMPORTING
e_t_rspcvariant = l_t_info.
CALL METHOD l_r_variant->free.
* ==== Check if run allowed ====
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_ASYNCHRON'.
IF sy-subrc = 0.
SELECT SINGLE * FROM rspcabapasync INTO l_s_log
WHERE variante = i_variant
AND state = 'A'.
IF sy-subrc = 0.
MESSAGE e052(rspc) WITH
i_variant l_s_log-instance l_s_log-log_id.
EXIT.
ENDIF.
ENDIF.
* ==== Log start ====
CALL FUNCTION 'GET_JOB_RUNTIME_INFO'
IMPORTING
jobcount = l_s_log-jobcount
EXCEPTIONS
no_runtime_info = 1
OTHERS = 2.
CALL FUNCTION 'RSSM_GET_TIME'
IMPORTING
e_timestamps = l_s_log-timestamp.
l_s_log-variante = i_variant.
l_s_log-log_id = i_logid.
l_s_log-instance = e_instance.
l_s_log-state = 'A'.
INSERT rspcabapasync FROM l_s_log.
CALL FUNCTION 'DB_COMMIT'.
* ==== Datenübergabe an Programm ====
SELECT SINGLE chain_id FROM rspclogchain INTO l_chainid
WHERE log_id = l_s_log-log_id.
EXPORT instance FROM l_s_log-instance
log_id FROM l_s_log-log_id
chain_id FROM l_chainid
TO DATABASE rspc_buffer(ab)
ID l_s_log-variante.
CALL FUNCTION 'DB_COMMIT'.
* ==== Start ====
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_PROGRAM'.
IF sy-subrc = 0.
* ---- Programm ----
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'PROGRAM'.
l_program = l_s_info-low.
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'VARIANT'.
l_progvari = l_s_info-low.
CALL FUNCTION 'GET_PRINT_PARAMETERS'
EXPORTING
no_dialog = 'X'
line_size = 255
IMPORTING
out_archive_parameters = l_arcpar
out_parameters = l_pripar
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'I' NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
SUBMIT (l_program) USING SELECTION-SET l_progvari
TO SAP-SPOOL WITHOUT SPOOL DYNPRO
LINE-SIZE 255
SPOOL PARAMETERS l_pripar
ARCHIVE PARAMETERS l_arcpar
AND RETURN.
* read parameters of program variant
* look in Z_BAP_STATUS for status of ABAP
data: l_subrc type ZABAP_STATUS-status.
SELECT SINGLE status into l_subrc FROM ZABAP_STATUS WHERE report = l_program.
if sy-subrc <> 0.
e_state = 'X'.
exit.
endif.
* set e_state accordingly
if l_subrc <> 0.
MESSAGE ID 'RSPC' TYPE 'I' NUMBER 051
WITH 'BI' l_msg(50) l_msg+50(50).
e_state = 'X'.
exit.
else.
e_state = 'F'.
exit.
endif.
ELSE.
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_PLANNED'.
IF sy-subrc = 0.
* ---- Event ----
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'EVENT'.
l_event = l_s_info-low.
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'PARAM'.
l_param = l_s_info-low.
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_LOCAL'.
IF sy-subrc = 0.
* Lokal
CALL FUNCTION 'RSSM_EVENT_RAISE'
EXPORTING
i_eventid = l_event
i_eventparm = l_param
EXCEPTIONS
bad_eventid = 1
eventid_does_not_exist = 2
eventid_missing = 3
raise_failed = 4
OTHERS = 5.
IF sy-subrc <> 0.
log_abort.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
EXIT.
ENDIF.
ELSE.
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_DESTINATION'.
IF sy-subrc = 0.
* Remote
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'DESTINATION'.
l_dest = l_s_info-low.
CALL FUNCTION 'RPY_FUNCTIONMODULE_READ'
DESTINATION l_dest
EXPORTING
functionname = 'ROPC_EVENT_RAISE'
EXCEPTIONS
error_message = 1
function_not_found = 2
invalid_name = 3
system_failure = 5 MESSAGE l_msg
communication_failure = 5 MESSAGE l_msg
OTHERS = 4.
IF sy-subrc = 5.
log_abort.
MESSAGE e051(rspc) WITH l_dest l_msg(50) l_msg+50(50).
EXIT.
ELSEIF sy-subrc = 2.
log_abort.
MESSAGE e045(rspc) WITH l_dest.
ELSEIF sy-subrc <> 0.
log_abort.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
EXIT.
ENDIF.
CALL FUNCTION 'ROPC_EVENT_RAISE'
DESTINATION l_dest
EXPORTING
i_eventid = l_event
i_eventparm = l_param
EXCEPTIONS
bad_eventid = 1
eventid_does_not_exist = 2
eventid_missing = 3
raise_failed = 4
system_failure = 5 MESSAGE l_msg
communication_failure = 6 MESSAGE l_msg
OTHERS = 7.
IF sy-subrc = 5.
log_abort.
MESSAGE e051(rspc) WITH l_dest l_msg(50) l_msg+50(50).
EXIT.
ELSEIF sy-subrc <> 0.
log_abort.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
EXIT.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
* ==== End ====
READ TABLE l_t_info INTO l_s_info
WITH KEY fnam = 'X_SYNCHRON'.
IF sy-subrc = 0.
* ---- Synchron call ----
CALL FUNCTION 'RSSM_GET_TIME'
IMPORTING
e_timestamps = l_s_log-timestamp.
* look in Z_BAP_STATUS for status of ABAP
SELECT SINGLE status into l_subrc FROM ZABAP_STATUS WHERE report = l_program.
if sy-subrc <> 0.
e_state = 'X'.
exit.
endif.
* set e_state accordingly
if l_subrc <> 0.
MESSAGE ID 'RSPC' TYPE 'I' NUMBER 051
WITH 'BI' l_msg(50) l_msg+50(50).
e_state = 'X'.
exit.
else.
e_state = 'F'.
exit.
endif.
* e_state = 'F'.
CLEAR e_hold.
* l_s_log-state = 'F'.
* l_s_log-state = 'X'.
* MODIFY rspcabapasync FROM l_s_log.
CALL FUNCTION 'DB_COMMIT'.
ELSE.
* ---- Asynchron call ----
e_state = 'A'.
e_hold = 'X'.
ENDIF.
The other methods provided by the interfaces are not needed and can be left unimplemented.
Activate the class with all its methods.
The tricky part are following lines of code:
data: l_subrc type ZABAP_STATUS-status.
SELECT SINGLE status into l_subrc FROM ZABAP_STATUS
WHERE report = l_program.
if sy-subrc <> 0.
e_state = 'X'.
exit.
endif.
* set e_state accordingly
if l_subrc <> 0.
MESSAGE ID 'RSPC' TYPE 'I' NUMBER 051
WITH 'BI' l_msg(50) l_msg+50(50).
e_state = 'X'.
exit.
else.
e_state = 'F'.
exit.
endif.
The process type reads in the Z-table, if there is an entry for the executed ABAP program. That’s the only pre-condition to use this process type with your ABAP reports in process chains:
All ABAP reports have to write their execution result into this Z-table!
Step 3.) Create your new process type
Call transaction RSPC, or use the icon in the Administrator Workbench.
Open any of the existing process chains, or create a new one. Call the maintenance of the process types by choosing from menu ‘Settings -> Maintain Process Types’.
Press change button to switch from table display to table change mode. Then press button “New entries”. Create a new entry in the table, and specify the settings as shown in the picture:
For testing I wrote just a small program call ed ZABAP_TEST:
data: l_data like zabap_Status.
if sy-datum >= 20071231.
sy-subrc = 0.
else.
sy-subrc = 4.
endif.
l_data-report = 'ZABAP_TEST'.
l_Data-status = sy-subrc.
insert into zabap_status values l_data.
if sy-subrc <> 0.
update zabap_Status from l_data.
endif.
You can easily switch to produce true or false.
In RSPC build an easy new process chain, executing our test abap and the new process type. In case of error, chain should stop. In case of no error it should e.g. rebuild an index of an cube.
So the process chain looks like that:
Schedule and execute it.
Have fun with it!