Purpose
Invoke an ABAP OO method remotely

ABAP OO does not support RMI (Remote Method Invocation) in a similar way as is available for function calls (Remote Function Call interface, RFC). The GuiXT Open Call interface fills this gap and provides a convenient way to call most ABAP OO methods remotely.

The SAP class library contains more than 200 000 classes and some of them can be useful in GuiXT applications. Please keep in mind that SAP may change all methods with the next upgrade, since apparently there exists no concept to declare classes as released for external usage. For frequently used classes such as the ALV classes, which have been in use for many years, only compatible further developments are to be expected on the part of SAP.

A description of the GuiXT "Call" notation can be found in the Call documentation. We describe some additional aspects here.

1. General approach to handling ABAP OO in GuiXT
GuiXT supports only string type variables, no number types, references or pointers, not to mention objects and classes. This simple approach is kept when calling ABAP OO methods.

In GuiXT, an ABAP OO object is always addressed by a freely assignable name, for example "item1". The name is assigned to an ABAP OO object at ABAP level by the GuiXT interface. There is no knowledge on GuiXT level that a variable e.g. V[c1] with the content "item1" refers to an ABAP object of a certain class.

The object names are managed separately for each class, i.e. two objects with the name "item1" can exist, one of class "cl_A" and one of class "cl_B". The class name is specified explicitely in each "Call" statement.

2. Calling static methods
Static methods can be called independently of a particular instance of this class. The GuiXT notation is identical to a function call, with the function name replaced by "classname.methodname":
Call "classname.methodname"  export.name1= ... import.name2= ...

All options of the Call statement such as -try, -dialog ... can be used, including the bundling of calls.

Example 1

// check email address
Set
V[email] "office@synactive.com"
Call "cl_bcs_email_address.validate" -try _
   
export.iv_full_email="email"
if not Q[ok]
    Message "E: Wrong email address format" -statusline
endif


Example 2:

// calculate week number
Set V[mydate] "20.01.2021"
Call
"cl_db6_calendar_tool.weeknumber_of_date"  _
 
export.date="mydate" _
  import.week_number="week"


The SAP Class Builder SE24 shows the static methods and their parameters:

 


You can test methods calls  (at least simple ones) in transaction SE24:






3. Creating an object of a certain class
To create a new object call the "constructor" method of the class and pass a unique object name as parameter "result". This will create an object of the specified class which you can address by its name in the following Call statements. 

Example:

// read text for company code 5400
Set V[ti] "ti01"
Call "cl_text_identifier.constructor" export.result="ti" 
...

Passing an object name without creating the instance first is also possible. The object is then created on the fly by the interface. This automatic creation does not work if the constructor method of the class requires further parameters.

Another way to create objects is to call a method that creates the object and returns the object reference ("factory" methods). In this case you also pass the desired object name with "export=".

Example:


// Create ALV object
Set
V[alv] "alv"
Call "cl_salv_table.factory" export.t_table="mytable" export.r_salv_table="alv"


4. Calling instance methods
For instance methods you add the  object= parameter and specify a GuiXT variable whose content is the object name:

Call "classname.methodname"  object="objvarname" _
export.
name1=" ... import.name2=
...

Note that you do not pass the object name as a string but the name of a GuiXT variable which contains the object name.

Example:

// read text for company code 5400 using the general text identifier class
Set V[ti] "ti01"
Set V[tabname] "T001"
Set V[fieldname] "BUKRS"
Set V[fieldvalue] "5400"

Call "cl_text_identifier.constructor" export.result="ti" 
Call
"cl_text_identifier.if_text_identifier~read_text" object="ti" _
   
export.tabname="tabname" _
   
export.fieldname="fieldname" _
   
export.fieldvalue="fieldvalue" _
   
import.text="fieldtext"


5. Always use "export=" to pass object names
Intuitively one tends to write

Call "cl_text_identifier.constructor" import.result="ti"  //
wrong!

i.e. to use "import=", because the class constructor method returns the new object reference. This would be correct at the ABAP level, but in the additional GuiXT interface layer the direction is reversed in the case of object references: we supply the object name and the interface will associate this name with the new object reference:

Call "cl_text_identifier.constructor" export.result="ti"  // correct

A big advantage of this approach is that it allows us to bundle method calls even if new objects are created and then used in subsequent method calls. See the ALV example in section 8 below.


6. Bundling method calls
Multiple method calls can be bundled into a single remote request in the same way as for function calls. Mixing function calls and method calls in a single bundled request is also supported.

For method calls, the bundling option is even more important because function calls typically contain a larger block of code while method calls have finer granularity.

7. Authorization checks
For each method call, GuiXT checks that the user is authorized to execute the given method. The SAP RFC authorization object S_RFC is used for this purpose, using the artificial function name "classname.methodname". 

The authorization parameters are:

S_RFC
RFC_TYPE=FUNC
RFC_NAME=classname.methodname
ACTVT=16

You may use generic authorizations, e.g.  you can allow all methods of class CL_SALV by specifying the value "CL_SALV.*"  as RFC_NAME.



8. Example: ALV display as popup
In the following example we use the techniques explained above in order to generate an ALV list as a popup window. We start in transaction BP (Business Partner) in an S/4HANA system.

If the role "Customer" is active and "Sales and Distribution" data are displayed, we add
a button "Show orders", allowing the user to display the sales orders of this customer for the selected sales area:




With the button an InputScript "bp_show_orders.txt" is started; it reads sales order data and displays an ALV popup window:



All standard ALV functions can be used, for example selecting the sort order:




GuiXT Script

Set V[partner_role] "&F[Display in BP role]"

// additional buttons in role Customer (FLCU01), group box "Sales area" 
if V[partner_role=FLCU01] and G[Sales Area]
 
Pushbutton (5,82) "@UI\QShow orders of the last 12 months@Show orders"      _
    size=(1,21) process="bp_show_orders.txt"
endif



InputScript "bp_show_orders.txt"

//determine customer number from business partner number
Set V[table] "IBUPACUSTOMER"
Set V[condition] "BUSINESSPARTNER = @BU_PARTNER"
Set V[domname1] "BU_PARTNER"
Set V[domvalue1] "&F[Business Partner]"
Set V[fields] "CUSTOMER"

CreateTable V[customers] kunnr

Call /guixt/dbselect _
  export.table="table" _
  export.condition="condition" _
  export.domname1="domname1" _
  export.domvalue1="domvalue1" _
  export.fields="fields" _
  import.values="customers"

// Set keys
Set V[kunnr] "&V[customers.kunnr.1]"
Set V[vkorg] "&F[Sales Org.]"
Set V[vtweg] "&F[Distr. Channel]"
Set V[spart] "&F[Division]"

// determine start date (today minus 12 months)
Set V[diffmonths] -12
Set V[basedate] "&V[today_ymd]"

Call cl_reca_date.add_months_to_date _
  export.
id_date="basedate" _
  export.
id_months="diffmonths" _
  import.
rd_date="startdate"

// create orders table
CreateTable V[orders]  vkbur audat vbeln auart netwr waerk bstnk ernam

// read orders
Set V[table] "VBAK"
Set V[condition] "kunnr = @KUNNR and audat >= @DATUM and vkorg = '&V[vkorg]' and vtweg = '&V[vtweg]' and spart = '&V[spart]'"
Set V[domname1] "KUNNR"
Set V[domvalue1] "&V[kunnr]"
Set V[domname2] "DATUM"
Set V[domvalue2] "&V[startdate]"
Set V[fields] "vkbur,audat,vbeln,auart,netwr,waerk,bstnk,ernam"

Call /guixt/dbselect _
  export.table="table" export.fields="fields"   export.condition="condition" _
 
export.domname1="domname1" export.domvalue1="domvalue1" _
  export.domname2="domname2" export.domvalue2="domvalue2" _
  import.values="orders"

// object variables
Set V[alv] "alv"
Set V[functions] "alvfunctions"
Set V[display] "alvdisplay"
Set V[sorts] "alvsorts"
Set V[aggregations] "alvaggregations"
Set V[sortcolumn1] "VKBUR"
Set V[sortsequence1] "1"  // ascending
Set V[sortcolumn2] "AUDAT"
Set V[sortsequence2] "2"  // descending
Set V[sortcolumn3] "VBELN"
Set V[sortsequence3] "1"  // ascending
Set V[aggregation1] "NETWR"

// ABAP-True
Set V[TRUE] "X"

// popup position/size
Set V[col1] "10"
Set V[row1] "5"
Set V[col2] "120"
Set V[row2] "40"

// Title
Set V[title] "Orders of the last 12 months"

 // Bundle all requests
Call
bundledRequests="Start" 

// Create ALV object
//
We pass the DDIC structure VBAK for our table  so that ALV uses
// the field attributes and solumn titles from the SAP repository

//
If other fields, not contained in VBAK, are needed, the column width, field type // and column title can be set separately for each column
// by adding further ALV
method calls


Set V[alv] "alv"
Call cl_salv_table.factory export.t_table(VBAK)="orders" export.r_salv_table="alv"

// allow all standard functions
Call cl_salv_table.get_functions object="alv" export.value="functions"
Call cl_salv_functions_list.set_all object="functions" export.value="TRUE"

// Set Title
Call cl_salv_table.get_display_settings object="alv" export.value="display"
Call cl_salv_display_settings.set_list_header object="display" export.value="title"

// Set sort
Call cl_salv_table.get_sorts object="alv" export.value="sorts"
Call cl_salv_sorts.add_sort object="sorts" export.columnname="sortcolumn1"
 
export.sequence="sortsequence1"  export.subtotal="TRUE" 
Call cl_salv_sorts.add_sort object="sorts" _
 
export.columnname="sortcolumn2" export.sequence="sortsequence2"
Call cl_salv_sorts.add_sort object="sorts" export.columnname="sortcolumn3"
 
export.sequence="sortsequence3"

// Set aggrgations
Call cl_salv_table.get_aggregations object="alv" export.value="aggregations"
Call cl_salv_aggregations.add_aggregation object="aggregations" _
 
export.columnname="aggregation1"

// Set popup position
Call cl_salv_table.set_screen_popup object="alv" _
  export.start_column="col1" export.start_line="row1" _
 
export.end_column="col2" export.end_line="row2"

// display popup
Call cl_salv_table.display object="alv"

// run all calls
Call bundledRequests -dialog

Return


Scripts as .zip file

Components
InputAssistant