Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
BaerbelWinkler
Active Contributor
6,808
Encouraged by the feedback I received in the Coffee Corner, here is a 2nd Q&A turned into a blog post. I decided to do this in this particular case because I didn't just get a very simple solution to my question but because it also examplifies how helpful the SAP community can be - and even in possibly record time!

About a year ago and in preparation for our upgrade to the SAP HANA database I started to look into the SCI/ATC options and how to make good use of them. One thing which was bugging me was that I wasn't able to find anything about how to call the ATC from a report program and provide the results in one go for multiple objects/transports. So, I posted a question about just that in Answers on Feb. 22, 2017 at 8:06 in the morning my time In Germany. Imagine my surprise, when I got a notification about a response from axel.jebens  within an hour - at 8:48 to be precise! - which was short and to the point:


Hi,

There is an object-oriented API which you can use to create an own program based on class CL_SATC_API_FACTORY. Please check out the example program RSATC_API_USAGE_EXAMPLE. There is a remote-enabled API and example program, too. See program RSATC_API_REMOTE_USAGE_EXAMPLE.

Hope it helps!

This turned out to be exactly what I was looking for and it was easy to implement as well! I checked out the sample code, copied it into a test-program, tweaked some of the hard-coded values to fit our own data (i.e. the program name or transport ID) and checked the results of this prototyping.

The next step was to add the logic - with some more tweaks - into a program I already had which lets me select transport-requests by various criteria. I basically just needed to add another routine to call the API from within a loop through the table with the already selected transports. I also decided to ignore any errors along the way (apart from a wrong check-variant) as I'm mainly using this for spot checks. I already had the program running each morning to send an email with a list of currently open transport-requests so I added the ATC-summary to that email. The ATC-information just includes the transport-ID and the number of findings encountered, but the details can be looked at as needed via Tcode ATC in the dev-system. So, as time allows, I can now use that email to do some spot checks on e.g. transports showing many findings. I had this up and running around noon.



Here is how the tweaked code looks like:
METHOD trigger_atc.

"Local definitions for ATC API calls
DATA:
l_factory TYPE REF TO cl_satc_api_factory,
l_object_set TYPE REF TO if_satc_object_set,
l_variant TYPE REF TO if_satc_check_variant,
l_configuration TYPE REF TO if_satc_run_configuration,
l_controller TYPE REF TO if_satc_run_controller,
l_result_access TYPE REF TO if_satc_result_access,
l_findings TYPE scit_rest,
l_findings_extension TYPE satc_ci_findings_extension,
l_ext_field_list TYPE satc_ci_finding_ext_field_list,
l_msg TYPE string,
l_cx TYPE REF TO cx_root,
l_description(128) TYPE c.

"Table for transport numbers
DATA: BEGIN OF ls_transp,
strkorr LIKE e070ctv-strkorr,
as4user LIKE e070ctv-as4user,
name_last LIKE user_addr-name_last,
END OF ls_transp.

DATA: lt_transp LIKE TABLE OF ls_transp.

DATA: ls_dl_objects LIKE LINE OF gt_dl_objects.

"Restrict to relevant ABAP-objects (via sel-screen input)
LOOP AT gt_dl_objects INTO ls_dl_objects WHERE pgmid IN s_pgmid
AND object IN s_obj_em
AND trkorr IN s_cts.
"Add transport-ID to internal table for summary listing in email
ls_transp-strkorr = ls_dl_objects-strkorr.
ls_transp-as4user = ls_dl_objects-as4user.
ls_transp-name_last = ls_dl_objects-name_last.
COLLECT ls_transp INTO lt_transp.
ENDLOOP.

LOOP AT lt_transp INTO ls_transp.

CREATE OBJECT l_factory.
TRY.
l_object_set = cl_satc_object_set_factory=>create_for_transport( i_transport = ls_transp-strkorr ).
CATCH cx_satc_empty_object_set INTO l_cx.
IF sy-batch EQ gc_x.
MESSAGE i000(38) WITH 'Processing of transport'(E03) ls_transp-strkorr 'ended with error:'(e04).
MESSAGE l_cx TYPE 'I'. " Object set contains no checkable objects
ENDIF.
CONTINUE.
CATCH cx_satc_not_found INTO l_cx.
IF sy-batch EQ gc_x.
MESSAGE i000(38) WITH 'Processing of transport'(E03) ls_transp-strkorr 'ended with error:'(e04).
MESSAGE l_cx TYPE 'I'. " Object set contains no checkable objects
ENDIF.
CONTINUE.
CATCH cx_satc_invalid_argument INTO l_cx.
IF sy-batch EQ gc_x.
MESSAGE i000(38) WITH 'Processing of transport'(E03) ls_transp-strkorr 'ended with error:'(e04).
MESSAGE l_cx TYPE 'I'. " Object set contains no checkable objects
ENDIF.
CONTINUE.
CATCH cx_satc_failure INTO l_cx.
IF sy-batch EQ gc_x.
MESSAGE i000(38) WITH 'Processing of transport'(E03) ls_transp-strkorr 'ended with error:'(e04).
MESSAGE l_cx TYPE 'I'. " Object set contains no checkable objects
ENDIF.
CONTINUE.
ENDTRY.

TRY.
l_variant = l_factory->get_repository( )->load_ci_check_variant( i_name = p_chkv ).
CATCH cx_satc_not_found INTO l_cx.
MESSAGE l_cx TYPE 'E'. " Specified Code Inspector variant was not found
ENDTRY.

CONCATENATE p_chkv
ls_transp-strkorr
sy-datum
sy-uzeit
ls_transp-as4user
ls_transp-name_last
INTO l_description
SEPARATED BY ' - '.


l_configuration = l_factory->create_run_config_with_chk_var(
i_object_set = l_object_set
i_check_variant = l_variant
i_description = l_description ).

l_configuration->set_pragma_option( i_option = if_satc_ac_project_constants=>c_mode_fndng_xmptd_in_code-show_as_open ).

l_controller = l_factory->create_run_controller( l_configuration ).

TRY.
l_controller->run( IMPORTING e_result_access = l_result_access ).
CATCH cx_satc_failure INTO l_cx.
MESSAGE l_cx TYPE 'E'. " ATC check run failed (no authorization, etc.)
ENDTRY.

l_ext_field_list-package_name = abap_true.
l_ext_field_list-exc_validity = abap_true.

TRY.
l_result_access->get_findings(
EXPORTING
i_ext_field_list = l_ext_field_list
IMPORTING
e_findings = l_findings
e_findings_extension = l_findings_extension ).
CATCH cx_satc_failure INTO l_cx.
MESSAGE l_cx TYPE 'E'. " Result access failed (no authorization, etc.)
ENDTRY.

l_msg = 'Number of Findings / Extensions: &1 / &2'(I01).
REPLACE ALL OCCURRENCES OF '&1' IN l_msg WITH |{ lines( l_findings ) }|.
REPLACE ALL OCCURRENCES OF '&2' IN l_msg WITH |{ lines( l_findings_extension ) }|.

CONCATENATE l_msg
ls_transp-strkorr
ls_transp-as4user
ls_transp-name_last
INTO l_msg
SEPARATED BY space.

gs_atc_msg-msg = l_msg.
APPEND gs_atc_msg TO gt_atc_msg.

ENDLOOP.


"Add the ATC-summary to the simple list
SKIP 1.
WRITE: / 'Summary of ATC-findings:'(i02).

LOOP AT gt_atc_msg INTO gs_atc_msg.
WRITE: / gs_atc_msg-msg.
ENDLOOP.

ENDMETHOD.

So, from asking the question to having a working solution implemented took not even 5 hours in this case. Which is quite a quick turnaround as far as I can tell!

Do you have similar examples of where the community came through this quickly?
8 Comments
Labels in this area