TRDIR and TADIR: tables behind programs and tables

TRDIR and TADIR are the tables behind programs and table data.

The below section is for experts only. Sometimes direct interception in TRDIR or TADIR is needed to solve nasty upgrade and support package issues. But if you don't know what you are doing: don't touch and raise message to SAP.

TADIR: development objects

TADIR contains the development objects list.

For example you want to know how many Z classes are created in your system, search in TADIR with SE11 and count the records:

Using TADIR with a search on DEVCLASS $TMP will give you a list with all programs in the $TMP (temp) space.

TADIR also has information about the original system. To change: follow the instructions in this blog.

TADIR does not contain a program editor lock. This is stored in table PROGDIR. See more in this blog.

Background notes on TADIR:

TRDIR: source code

TRDIR is a view on table REPOSRC. REPOSRC contains the actual ABAP source codes in RAWSTRING format. In some cases inconsistencies between TRDIR and TADIR might happen (mainly during upgrades). Direct interception on TADIR or TRDIR level might be needed, if you know what you are doing.

Transaction STDR can be used to check consistency:

Background notes on TRDIR:

Clean ABAP code ATC variant

Clean ABAP is the ABAP variant of the clean code principles. All background on clean ABAP code can be read in this blog.

This blog will explain how to upload the ABAP coding for the Clean ABAP ATC variant in your system and activate it.

Load ABAP Git code

To load the ATC variant code for clean ABAP you first need to install the ABAP Git code. Follow the instructions in this blog to do so. Simplest is the offline variant.

Download the ABAP clean code package

Now go to the Github code pal site for ABAP clean code and download the package:

Select the button Code and choose the option Download ZIP.

Upload the package

Now start the ABAP git that you loaded in your first step. Choose the option New Offline:

Give the repository a name and select a package:

Then push the button Create Offline Repo.

Now select Import Zip:

Import the file you downloaded in step 2 from the code pal site.

Next step is the Pull zip:

You might get a screen with differences. Do not select anything there, only press Ok.

Then wait until all the Y objects are pulled into the system. This might take 5 to 10 minutes.

Activating the SCI checks

Now start transaction SCI. Select menu option Code Inspector, Management of, Tests. Select all the newly load Y checks for Clean ABAP code:

Important now: Save them!

Now you can create a global SCI variant:

Select all the Clean code ABAP checks and save the variant:

You might get weird issues upon saving for other items, like for example missing CL_CI_CATEGORY_TOP. In that case, go to transaction SE16 -> look for table SCITESTS -> and look for CL_CI_CATEGORY_TOP if there is no entry. Enter the table SCITESTS and click "Create Entry", add CL_CI_CATEGORY_TOP entry and save.

Test and usage

Take a program you want check. Then select menu option Program, Check, ABAP Test Cockpit with….:

Select the ZCLEAN_ABAP SCI check we created above. Run the checks.

Results:

Tip: click on the blue line to jump to the Clean Code site exactly explaining about the issue.

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.

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.

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.