Clean ABAP

Clean ABAP is the ABAP implementation of Clean code. Clean code is one of the key principles to adhere to when going Agile. Clean code is part of agile software development craftmanship. Read more on clean code in the original book.

Clean ABAP reference site

Clean ABAP is published and maintained on a dedicated Clean ABAP Github site.

The site itself is excellent and also has a special chapter how to best start with Clean ABAP.

The site is extensive and might be overwhelming. If you are a more traditional person, you can also read the SAP Press book on Clean ABAP code.

Blog on SAP site on clean ABAP can be found here and here.

Patterns and anti-patterns

The Clean ABAP explanation on the site contains both patterns (how you should do) and anti-patterns (how you should not do).

Anyhow the Clean ABAP principles are fully built on Object Orientation. That is a must.

Introducing Clean ABAP in your organization

Regardless if your organization is doing Agile or Waterfall development, or other development methodologies, Clean ABAP can be applied anyhow.

First step is to embrace the Clean ABAP as a principle direction. It will take time to get there. Not all developers will pick up as fast as you might want to. It also takes time to refactor old code to the Clean ABAP principles.

Discuss as developers as a team which part of the principles and improvements you want to pick up first. If you master a few, you can make it mandatory. Then take the next set. Some might pick up more at a higher pace. But keep the discussion going to improve and pick up every 2 weeks (sprint) at least 1 improvement item.

For a nice overview: read this SAP blog.

Peer review or pair programming: ATC variant

You can make the Clean ABAP code rules a part of your peer review or pair programming.

There is an ATC variant that can be uploaded that check for the clean ABAP code rules. Read this blog for instructions on how to do this.

Boy Scout rule

The boy scout rule is as follows: leave the place nicer than when you arrived, even though you didn’t make the mess. When you do this repetitively the world becomes a cleaner place.

This also applies to poor code: don’t just do your change, but take along some minor improvements as well. When you do this a couple of times, the poor code will improve every time towards good code.

But this principle you also need to embrace and explain. There might be unlucky situations where the clean up part might cause unexpected bug. This might happen in 0.01% of the cases. When it happens you might get resistance and pushback. But stand up for the principle, and simply correct the bug. It is worth it in the long run.

Clean ABAP Eclipse plug-in: ABAP cleaner

To speed up clean ABAP in practice, you can install the clean ABAP cleaner plug-in. Read this blog on how to do this.

ODATA V4 activation

This blog will explain how to activate ODATA V4.

Questions that will be answered in this blog are:

  • How to activate ODATA V4 on your SAP system?
  • Does SAP support ODATA V3?
  • Do all consuming applications support ODATA V4?
  • What are the differences of ODATA V2 and V4?

ODATA V4

In the typical FIORI use case you will activate ODATA V2. SAP has skipped ODATA V3. ODATA V4 is supported by SAP.

Constraints of SAP ODATA V4 are listed in OSS note 2322624 – SAP Gateway SAP_GWFND OData V4 protocol – Known Constraints.

Filtering is powerful in ODATA V4. Read more on this in OSS note 2305033 – SAP Gateway OData V4 $flter Consulting Note.

Keep in mind not all application fully support all aspects of ODATA V4 or might not be able to consume ODATA V4 at all. Check first with the consumer before publishing an ODATA on V4.

Activation of ODATA V4

First step in activation is to check the virus scan settings for ODATA:

Activation of ODATA V4 messages via service administration:

Or use transaction /iwbep/v4_admin:

And for the front end /iwfnd/v4_admin:

Press button Add service groups:

Push the button Get Service Groups:

And select your entry and press Publish Service Groups:

Which one to publish has to be told to you. The consultant requesting it might link to the API hub.

After activation, you can use the Service Test button to check if the activation is ok:

On the screen hit Execute and the result should be a HTTP 200 success message:

OSS notes and background

Background notes:

Bug fix OSS notes:

Useful background blogs:

Differences between ODATA V2 and V4

For UI consumption differences between ODATA V2 and V4 read this SAP help file.

Generic blog on main differences ODATA V2 and V4: read here.

Or read this SAP blog on differences ODATA V2 and V4 for SAP specific.

Humor

New input welcome, leave a comment!

What does the SAP abbreviation stand for?

  • SAP = Slow And Painful
  • SAP = Software Aus Pakistan
  • SAP = Shut up And Pay
  • SAP = Sanduhr Anschau Program
  • SAP = Schreibs Auf Papier
  • SAP = Suffer After Purchase
  • SAP = System against People
  • SAP = Start Applying Patches
  • SAP = Surrender and Pay
  • SAP = Sit and Panic
  • SAP = Severely Aged Programs
  • SAP = Submit (security bugs) and Pray
  • SAP = Sammelbecken Arbeitsloser Physiker -> German for Pool of Unemployed Physicists

Competence

Competence is limited, incompetence is unlimited
Below each level of incompetence there a next level of even worse incompetence
We don't need to remove the BigTruck button in STMS since nobody will be so stupid to start the ImportAll
Fundamental laws of stupidity:
1. Everybody underestimates the amount of stupid people
2. Stupidity is not related to any other characteristic of a person 
3. Stupid people damage others and themselves
4. Not-stupid people underestimate the damage of stupid people
5. Stupid people are more dangerous than smart criminals

Integrate SO10 text in webdynpro

This blog will explain how to integrate SO10 standard text in webdynpro. It will also show how to use this to integrate it into page on the right after logon (see also this blog).

Setup SO10 text

Start transaction SO10 and create text for logon:

Now enter the text and save it:

We have entered text (as explained in SO10 blog). Important: add the <br/> tags to create the line break.

Setup webdynpro screen

We will now setup webdynpro screen into which we will integrate SO10 text above.

Go to SE80 and create webdynpro Z_LOGON_INFO and go to the main view context and create this structure:

This is the data container for the string to show on the screen.

In the Layout View add element for logon text of type FormattedTextView:

Bind the text from the data element:

And map the data source:

In the view go to the methods and fill the WDDOINIT method:

Full code:

METHOD wddoinit .

  DATA: lt_table    TYPE TABLE OF tline,
        ls_table    TYPE tline,
        iv_textname TYPE tdobname VALUE 'Z_TEXT_FOR_LOGON', "Text created in SO10.
        lv_string   TYPE string,
        ex_lines    TYPE string.

  DATA lo_nd_data TYPE REF TO if_wd_context_node.
  DATA lo_el_data TYPE REF TO if_wd_context_element.
  DATA ls_data TYPE wd_this->element_data.

  CONSTANTS: lc_txtid(4)   TYPE c VALUE 'ST',
             lc_txtobj(10) TYPE c VALUE 'TEXT'.

  CALL FUNCTION 'READ_TEXT'
    EXPORTING
      id       = lc_txtid
      name     = iv_textname
      language = sy-langu
      object   = lc_txtobj
    TABLES
      lines    = lt_table.

  LOOP AT lt_table INTO ls_table.
    CONCATENATE ex_lines ls_table-tdline INTO ex_lines SEPARATED BY space.
  ENDLOOP.

  lo_nd_data = wd_context->get_child_node( name = wd_this->wdctx_data ).
  lo_el_data = lo_nd_data->get_element( ).
  lo_el_data->set_attribute(
    name =  'SO10TEXT'
    value = ex_lines  ).

ENDMETHOD.

The code calls with function module READ_TEXT the text set into Z_TEXT_FOR_LOGON and binds it to the SO10TEXT element. Remark: the formatted text in webdynpro now processes the </BR> settings.

And create the webdynpro application:

And test it:

Restrictions

The formatted text is processed by class CL_WD_FORMATTED_TEXT. See help.sap.com on this. Restrictions are listed (like no use of commands), and list of allowed tags.

Adding URL

Adding a URL to the standard text and show it in webdypro is not possible (as far as known). To add a URL, add to LinkToUrl item in the webdynpro.

Insert as launch page

Now we follow the instructions from the blog on the logon text. Start transaction SM30_SSM_CUST and set the parameter SESS_URL:

Now log on again:

Sending hyperlink in email with ABAP code

This blog will explain the ABAP code you can use to send an email from SAP system which is in HTML format including hyperlink.

Questions that will be answered in this blog are:

  • Which basis settings do I need to make for HTML mail format sending?
  • What code snippets can I re-use to send a hyperlink in an email from my custom ABAP program?

Basis settings for HTML mail

In order to be able to send an mail with a hyperlink the mail must have HTML format.

First check this table entry exists in table SXCONVERT2:

If not create it.

Now go to transaction SCOT and set the output format of RAW to HTM:

Save the settings.

ABAP code to mail hyperlink

The ABAP code to mail is as follows:

*&---------------------------------------------------------------------*
*& Report zemail_cl_bcs
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
  REPORT  zemail_cl_bcs.

  CONSTANTS:
    gc_subject TYPE so_obj_des VALUE 'ABAP Email with CL_BCS',
    gc_raw     TYPE char03 VALUE 'HTM'.

  DATA:
    gv_mlrec         TYPE so_obj_nam,
    gv_sent_to_all   TYPE os_boolean,
    gv_email         TYPE adr6-smtp_addr,
    gv_subject       TYPE so_obj_des,
    gv_text          TYPE bcsy_text,
    zls_text         TYPE soli,
    xhtml_string     TYPE xstring,
    gr_send_request  TYPE REF TO cl_bcs,
    gr_bcs_exception TYPE REF TO cx_bcs,
    gr_recipient     TYPE REF TO if_recipient_bcs,
    gr_sender        TYPE REF TO cl_sapuser_bcs,
    t_hex            TYPE solix_tab,
    gr_document      TYPE REF TO cl_document_bcs.

  DATA: zlv_longstring_message TYPE string.
  DATA: zlt_et_soli TYPE soli_tab.
  DATA: zls_et_soli TYPE soli.

  TRY.
      "Create send request
      gr_send_request = cl_bcs=>create_persistent( ).

      "Email FROM...
      gr_sender = cl_sapuser_bcs=>create( sy-uname ).
      "Add sender to send request
      CALL METHOD gr_send_request->set_sender
        EXPORTING
          i_sender = gr_sender.

      "Email TO...
      gv_email = 'guru@saptechnicalguru.com'.
      gr_recipient = cl_cam_address_bcs=>create_internet_address( gv_email ).
      "Add recipient to send request
      CALL METHOD gr_send_request->add_recipient
        EXPORTING
          i_recipient = gr_recipient
          i_express   = 'X'.

      CONCATENATE '<html><strong>Decission needed</strong><br/><br/>'
      '<tr><th style="color:blue;">Approval item</th>'
      '<a href=https://server:port/sap/bc/ui2/flp#WorkflowTask-displayInbox?allItems'
      '=true&/detail/XXX999_PGW/000000226597/TaskCollection(SAP__Origin=&#39;XXX999_PGW&#39;,InstanceID=&#39;000000226597&#39;)> click here to decide 000000226597</a>'

                   INTO zlv_longstring_message.

      CONCATENATE zlv_longstring_message '</html>' INTO zlv_longstring_message.

      CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
        EXPORTING
          text   = zlv_longstring_message
        IMPORTING
          buffer = xhtml_string
        EXCEPTIONS
          failed = 1
          OTHERS = 2.

      CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
        EXPORTING
          buffer     = xhtml_string
        TABLES
          binary_tab = t_hex.

      gr_document = cl_document_bcs=>create_document(
                      i_type    = gc_raw
                      i_hex    = t_hex
                      i_length  = '1200'
                      i_subject = gc_subject ).
      "Add document to send request
      CALL METHOD gr_send_request->set_document( gr_document ).

* set send immediately flag
      gr_send_request->set_send_immediately( 'X' ).
      "Send email
      CALL METHOD gr_send_request->send(
        EXPORTING
          i_with_error_screen = 'X'
        RECEIVING
          result              = gv_sent_to_all ).
      IF gv_sent_to_all = 'X'.
        WRITE 'Email sent!'.
      ENDIF.

      "Commit to send email
      COMMIT WORK.

      "Exception handling
    CATCH cx_bcs INTO gr_bcs_exception.
      WRITE:
        'Error!',
        'Error type:',
        gr_bcs_exception->error_type.
  ENDTRY.

The end result is as follows in the mail:

The hyperlink in the mail jumps to the URL, which in this case is the URL link to this specific workflow item in the FIORI inbox.

The coding explained

We use the CL_BCS class from SAP. BCS stands for Business Communication Service. This class provides all modern options to send mail. We set the sender and receiver.

We now build the mail in HTML. All is stored in zlv_longstring_message. We start with the <html> tag, and a header text in bold (strong). Then we add the text with the hyperlink (a href) in blue color.

The hyperlink towards the FIORi inbox contains ‘ characters. This does not convert well for all further on steps. So we replace ‘ instead the &#39 text. This &#39 text is the HTML character coding for an apostrophe (‘). In this way there is no misinterpretation at any browser.

At the end, we add the closing tag </html>. Now the HTML build up is ready and can be used to send.

The HTLM is converted via function modules SCMS_STRING_TO_XSTRING and SCMS_XSTRING_TO_BINARY to a binary. This binary is set as document with type HTM to the mail. The mail is then sent with immediate flag.

SO10 standard text

With transaction SO10 you can maintain standard texts. These texts can be used in SapScript, SmartForms and your own ABAP code.

Questions that will be answered in this blog are:

  • How to create a standard text in SO10?
  • How to set default editor for SO10?
  • How to transport SO10 standard texts?
  • How to call SO10 standard text in ABAP code?
  • How to insert hyperlink into SO10 text?

Create standard text

Start transaction SO10, enter the text name and press the create button:

Now enter the text in the editor and save it:

Transporting standard texts

After saving the standard text the tool just saves the text without prompting for transport. This is as designed. The text can be maintained directly in production this way. Either by IT or even by business users.

If you do want to transport the standard texts, use program RSTXTRAN to add the standard text to the transport:

Read standard text from ABAP code

You can read the standard text from your own ABAP code by calling function module READ_TEXT

Example code:

DATA: IT_TLINES type table of TLINE.

REFRESH IT_TLINES.

CALL FUNCTION 'READ_TEXT'
      EXPORTING
*       CLIENT                        = SY-MANDT
        ID                            = 'ST'
        LANGUAGE                      = 'E'
        NAME                          = 'Z_DEMO_TEXT'
        OBJECT                        = 'TEXT'
*       ARCHIVE_HANDLE                = 0
*       LOCAL_CAT                     = ' '
*     IMPORTING
*       HEADER                        =
      TABLES
        LINES                         =  IT_TLINES
*     EXCEPTIONS
*       ID                            = 1
*       LANGUAGE                      = 2
*       NAME                          = 3
*       NOT_FOUND                     = 4
*       OBJECT                        = 5
*       REFERENCE_CHECK               = 6
*       WRONG_ACCESS_TO_ARCHIVE       = 7
*       OTHERS                        = 8.

Inserting graphic in SO10

Follow the instructions in OSS note 2918753 – How to insert graphic in SO10.

Inserting hyperlink in SO10

First create hypertext in transaction SO72. Select type CHAP:

In SO10 now select the menu option Insert / Text / Hypertext:

Hyperlink is now inserted into SO10:

Changing the editor

Many people don’t like the word tool as editor. It is not precise enough. You can run program RSCPSETEDITOR to change the setting for everybody:

Untick the MS word as editor and press the Activate button.

Relevant OSS notes:

Check custom code for use of unreleased SAP objects

Custom code can use standard SAP code and SAP objects. Some of these objects might technically exist, but are in an unreleased status. This might mean SAP will not give support on them, or might remove them in a future upgrade.

Also when you want to move to the BTP ABAP cloud, you cannot use the unreleased code.

Questions that will be answered in this blog are:

  • How can I scan my custom code for use of unreleased standard SAP objects?

Tool preparation

First install the program SYCM_UPLOAD_RELEASED_OBJECTS by applying OSS notes 2989803 – Check Usage of Released Objects with the Latest List of Released Objects and 3143521 – Check for Released Objects: Introduce Finding “Usage of API that will not be released”.

And download the attached file in the same note in the attachments section;

Now run program SYCM_UPLOAD_RELEASED_OBJECTS and upload the file to a new SCI variant:

After the upload, you will find this new variant SAP_CP_READINESS_REMOTE in SCI:

ATC run for unreleased code

Now you can start new ATC run with this newly created variant SAP_CP_READINESS_REMOTE:

Run the variant for you custom code (can take few hours).

Result can be shown as special whitelist item:

ABAP code to write to application log

The SLG1 application log is a powerful mechanism to support team in SAP systems.

This blog will explain how you can write to the application log in your own custom ABAP code using ABAP code below.

It is recommended to create one single SE24 ABAP class for the application log that can be re-used in all your custom code.

Instantiation method

First method to create is the instantiation method:

   DATA: zls_log        TYPE bal_s_log,
         zlt_log_handle TYPE bal_t_logh,
         zlt_message    TYPE bal_t_msg. 

      zls_log-object     = ziv_object.
      zls_log-subobject  = ziv_subobj.
      zls_log-extnumber  = ziv_extnumber.
      zls_log-aluser     = sy-uname.
      zls_log-alprog     = sy-repid.


 CALL FUNCTION 'BAL_LOG_CREATE'
      EXPORTING
        i_s_log                 = zis_log
      IMPORTING
        e_log_handle            = zgv_log_handle
      EXCEPTIONS
        log_header_inconsistent = 1
        OTHERS                  = 2.

As input you have to give SLG1 object name and sub object name. You can re-use existing or create new custom one in transaction SLG0.

Now you have a log handler.

Add the messages

Now you can add a method to add one or more messages, re-using the log handler:

zls_msg      TYPE bal_s_msg,

      CALL FUNCTION 'BAL_LOG_MSG_ADD'
        EXPORTING
          i_log_handle     = zgv_log_handle
          i_s_msg          = zls_msg
        EXCEPTIONS
          log_not_found    = 1
          msg_inconsistent = 2
          log_is_full      = 3
          OTHERS           = 4.

Save the log

Create a method for saving the application log, again re-using the log handle:

    CALL FUNCTION 'BAL_DB_SAVE'
      EXPORTING
        i_t_log_handle   = zlt_log_handle
      EXCEPTIONS
        log_not_found    = 1
        save_not_allowed = 2
        numbering_error  = 3
        OTHERS           = 4.

Set up once and re-use

Set up the application logging helper class once in SE24 and tell all your developers to re-use it. You might find out that you developer already used the function modules above a lot in their Z code. This can be found with the ABAP code scanner tool. Check case by case when it makes sense to swap to the central helper class.

New Z application log objects

Using transaction SLG0 you can set up custom application log objects and sub-objects.

ABAP editor lock

ABAP programs can be protected from changes by setting the editor lock. Only do this for very critical programs.

This blog will primarily focus on methods to remove the editor lock.

Editor lock

The editor lock is set on the properties of an ABAP program:

The property to set is the Editor Lock tickbox.

When this is set only the author can change the program.

Change user for editor lock

In some cases you have a valid reason to lift the editor lock. If the person has left, or you need to change the program for bug fixing emergency and you can’t wait until the owner is back.

Change editor lock via SE03

As basis administrator you can change the owner of the editor lock in transaction SE03:

Change via SU01 usage

When person left: alter the password for this user in SU01. Log on as this user and remove the editor lock.

Via table editing of table PROGDIR

Goto table PROGDIR and view the content (via SE11). Search for your program and edit the entry:

Remove the EDTX flag and save. Editor lock is gone.

Via program

You can use Z program below to remove the lock:

REPORT  zedit_lock_remove.

TABLES: trdir.

PARAMETERS: p_prog LIKE trdir-name OBLIGATORY.

START-OF-SELECTION.
  SELECT SINGLE * FROM trdir WHERE name = p_prog.

  IF sy-subrc = 0.
    IF trdir-edtx = 'X'.
      MOVE ' ' TO trdir-edtx.
      MODIFY trdir.
      WRITE: /'Editor Lock was removed from', p_prog.
    ELSE.
      WRITE: /'Program', p_prog, 'does not have an Editor Lock'.
    ENDIF.
  ELSE.
    WRITE: /'No match found for program', p_prog.
  ENDIF.

SE95 modification overview

Transaction SE95 can be used to get an overview of modifications in your SAP system.

Questions that will be answered in this blog are:

  • What is the definition of a modification?
  • How can I list all modifications in my system?
  • How can I make a download of all the modifications in my system?
  • How can I filter on real modifications and exclude the modifications caused by OSS notes?

Definition of modifications

This is the most tricky question: how many modifications are in your system? A question that will be asked to you every now and then. The answer can very between a very small number and a very large number. Even with the same system. This is because the way SAP is measuring modifications. OSS notes applied count as modifications. Classical user exits like MV45AFZF also count as modifications. Condition records (VOFM routines starting with RV) also count as modifications. But you can still consider the system as 100% standard.

Real modifications are only those where the customer willingly changed the SAP coding and its functionality, which is not based on an instructions from an OSS note.

In many cases with discussion on system quality, the number of modifications is misused! Be careful to check how your analysis figures will be used.

Modification browser

Start transaction SE95 to reach the modification browser initial screen:

You can now see the SE95 result list:

You can drill down based on the objects.

For a view per package, check the Packages display option on the first screen:

Listing for download

SE95 has a major setback: the list is very hard to export. The modifications are stored in database view SMODIDEVC (which is a view on SMODILOG and TADIR).

From here do select only the MOD (modifcations):

The resulting output list can be easily downloaded into an excel format.

SE95 OSS notes

2971944 – Resetting program modifications in SE95 also resets SAP Note corrections