Entering content frameThis graphic is explained in the accompanying text Binding to Object References (Instances) Locate the document in its SAP Library structure

An ABAP object reference is mapped in JavaScript as a proxy object of the predefined proxy class SAPAbapOrefClass. You can specify a – case-sensitive – name for the JavaScript reference using the NAME_PROP parameter of the BIND method.

The components of the proxy object are:

You cannot add other properties or methods to the proxy object in JavaScript. If you assign ABAP object references to bound object references in JavaScript, or if you try to access attributes to non-existent ABAP objects in JavaScript (that is, if the reference variable in ABAP is blank), the JavaScript stops processing.

Access to instance attributes

If you assign a JavaScript object to the object reference variable in ABAP, JavaScript also works with the attributes of the ABAP object to which the object reference variable points after the assignment. The variable in JavaScript is bound to the object reference variable in ABAP, not to the ABAP object (see also BIND_INSTANCE).

The JavaScript object is linked to the static type of the object reference variable. If a narrowing cast is performed using an assignment in ABAP, the JavaScript object retains its own type and cannot access the added attributes of the dynamic type. Similarly, you can perform widening casts and have them checked in ABAP only. For this reason, in JavaScript, you can never have the problem where you try to access attributes that do not exist in the referenced object.

Process with care, if you want to assign properties of bound object reference variables in JavaScript to other variables. If the relevant object is deleted in ABAP by the Garbage Collector, and you then try to use the target variable, a runtime error occurs.

Example

report DEMO_JAVA_SCRIPT_BIND_ATTRIBUT.

class C1 definition.
  public section.
    data ATTR type STRING.
    methods CONSTRUCTOR.
endclass.

class C1 implementation.
  method CONSTRUCTOR.
    ATTR = 'Hello '.
  endmethod.
endclass.

data OREF type ref to C1.

data RETURN_VALUE type STRING.

data SOURCE type STRING.

data JS_PROCESSOR type ref to CL_JAVA_SCRIPT.

start-of-selection.

  JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ).

  JS_PROCESSOR->BIND(  EXPORTING
                        NAME_OBJ  = 'abap'
                        NAME_PROP = 'Ref'
                       CHANGING
                         DATA      = OREF ).

  create object OREF.

concatenate  'if ( abap.Dref.notInitial() )  '
             '{ abap.Ref.attr += " World!"; }'
             INTO source.

  JS_PROCESSOR->EVALUATE( JAVA_SCRIPT = SOURCE ).
  write OREF->ATTR..

In this example, JavaScript changes the attribute OREF->ATTR from 'Hello' to 'Hello World!'. If JavaScript tries to access 'oref.attr' before the CREATE OBJECT assignment, processing terminates.

Calling instance methods

To call the public instance methods of the reference object in ABAP from JavaScript, use the ‘invoke’ method of the relevant JavaScript object.

The ‘invoke’ method expects the name of the ABAP instance method in lower case as the first argument, following by the passed parameters. You must specify the parameter name and actual parameter as a pair separated by commas, for each non-optional interface parameter of the ABAP instance method. These pairs can be in any order. You do not have to specify optional parameters, or the usual ABAP additions EXPORTING, IMPORTING, CHANGING, or RETURNING.

Constraints

Passing values using the RETURNING parameter

The return value from ‘invoke’ is automatically filled by the RETURNING parameter of the called method. If the type of the RETURNING parameter is elementary, this is the actual return value of the ABAP method. Thus in this case, you need not necessarily specify an argument for the RETURNING parameter. If the type of the RETURNING parameter is complex or if there are no RETURNING parameters, the returning value of invoke is set to jsval_void. If you specify a complex RETURNING parameter, you must therefore specify an argument.

Example

report DEMO_JAVA_SCRIPT_BIND_METH_RET.

class COUNTER definition.
  public section.
    methods: SET importing VALUE(SET_VALUE) type I,
             INCREMENT,
             GET returning VALUE(GET_VALUE) type I.
  private section.
    data COUNT type I.
endclass.

class COUNTER implementation.
  method SET.
    COUNT = SET_VALUE.
  endmethod.
  method INCREMENT.
    COUNT = COUNT + 1.
  endmethod.
  method GET.
    GET_VALUE = COUNT.
  endmethod.
endclass.

data OREF type ref to COUNTER.
data RESULT type I.

data SOURCE type STRING.
data JS_PROCESSOR type ref to CL_JAVA_SCRIPT.

data GET_VALUE type STRING.

start-of-selection.

  JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ).

  JS_PROCESSOR->BIND( exporting NAME_OBJ  = 'abap'
                                NAME_PROP = 'Ref'
                      changing  DATA      = OREF ).

  create object OREF.

  concatenate
  'var start_value = 10 ;                                  '
  'var result = 0 ;                                        '
  'abap.Ref.invoke( "set", "set_value", start_value );       '
  'for (var i = 0; i < 5; i++)                              '
  '  {                                                     '
  '  abap.Ref.invoke( "increment" );                        '
  '  }                                                     '
  'result=abap.Ref.invoke( "get"  );                        '
* 'result=abap.Ref.invoke( "get", "get_value", result );     '
  into SOURCE separated by CL_ABAP_CHAR_UTILITIES=>CR_LF.

  JS_PROCESSOR->COMPILE(
                exporting
                  SCRIPT_NAME = 'COUNT.JS'
                  SCRIPT      = SOURCE ).

  JS_PROCESSOR->EXECUTE(
                exporting SCRIPT_NAME = 'COUNT.JS' ).

  GET_VALUE = JS_PROCESSOR->GET( NAME = 'result' ).

  RESULT = OREF->GET( ).

  write / GET_VALUE.
  write / RESULT.

In this example, an ABAP object of the local class COUNTER is bound to the JavaScript object abap.Ref using the OREF reference variable. The JavaScript calls the ABAP methods SET, INCREMENT (five times), and GET using the ‘invoke’ method. When it calls the (ABAP) GET method, the RESULTING parameter GET_VALUE is passed to the global variable result as the return value of invoke. The commented-out line specifying the arguments has the same effect. However, the argument list is superfluous, since the RETURNING parameter of the ABAP method.

result is read from the JavaScript context and passed to the ABAP variable GET_VALUE using the GET method of the class CL_JAVA_SCRIPT. Moreover, the program fills the ABAP variable RESULT in ABAP by calling the ABAP method GET. The values of result in JavaScript and RESULT in ABAP are identical.

Passing and receiving values using arguments

If you want to pass or receive parameters other than elementary RETURNING parameters – that is, complex RETURNING parameters, or IMPORTING EXPORTING, or CHANGING parameters – you must specify the appropriate arguments.

Note:

Example

report DEMO_JAVA_SCRIPT_BIND_METH_VAL.

class C_ABAP definition.
  public section.
    methods SET_VALUE exporting P_ABAP type I.
endclass.

class C_ABAP implementation.
  method SET_VALUE.
    P_ABAP = 111.
  endmethod.
endclass.

data OREF type ref to C_ABAP.
data RESULT type I.

data SOURCE type STRING.
data JS_PROCESSOR type ref to CL_JAVA_SCRIPT.

data GET_VALUE type STRING.

start-of-selection.

  JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ).

  JS_PROCESSOR->BIND( exporting NAME_OBJ  = 'abap'
                                NAME_PROP = 'Ref'
                      changing  DATA      = OREF ).

  create object OREF.

  concatenate
  'var result_abap_val  =  0;                                '
  'var result_js_val    =  0;                                '
  'var result_abap_ref   = new SAPAbapMethParam(0);          '
  'var result_js_ref     = new SAPAbapMethParam(0);          '
  'var result_abap_ref_prop   = 0                            '
  'var result_js_ref_prop     = 0                            '
  'function set_value_val(p_js) { p_js = 666 };              '
  'function set_value_ref(p_js) { p_js.value = 666 };        '
  'abap.Ref.invoke( "set_value", "p_abap", result_abap_val );'
  'set_value_val(result_js_val);                             '
  'abap.Ref.invoke( "set_value", "p_abap", result_abap_ref );'
  'set_value_ref(result_js_ref);                             '
  'result_abap_ref_prop   = result_abap_ref.value;       '
  'result_js_ref_prop     = result_js_ref.value;         '
   into SOURCE separated by CL_ABAP_CHAR_UTILITIES=>CR_LF.

  JS_PROCESSOR->COMPILE(
                exporting
                  SCRIPT_NAME = 'VALUES.JS'
                  SCRIPT      = SOURCE ).

  JS_PROCESSOR->EXECUTE(
                exporting SCRIPT_NAME = 'VALUES.JS' ).

  GET_VALUE = JS_PROCESSOR->GET( NAME = 'result_abap_val' ).
  write: /  'result_abap_val' , 40 GET_VALUE.

  GET_VALUE = JS_PROCESSOR->GET( NAME = 'result_js_val' ).
  write: /  'result_js_val' , 40 GET_VALUE.

  GET_VALUE = JS_PROCESSOR->GET(
                            NAME = 'result_abap_ref_prop' ).
  write: /  'result_abap_ref.value' , 40 GET_VALUE.

  GET_VALUE = JS_PROCESSOR->GET(
                            NAME = 'result_js_ref_prop' ).
  write: /  'result_js_ref.value' , 40 GET_VALUE.

In this example, an ABAP object of the local class C_ABAP is bound to the JavaScript object abap.Ref using the OREF reference variable. In JavaScript, two simple variables are defined – result_abap_val and js_abap_val – as well as two objects of the class SAPAbapMethParam – result_abap_ref and result_js_ref. Moreover, two JavaScript functions are defined – set_value_val and set_value_ref.

The ABAP method SET_VALUE and the JavaScript functions are called with different arguments. The values passed to the arguments are checked using the GET method in the ABAP program. Since GET cannot access the attributes of an object, the ‘value’ property of the objects from SAPAbapMethParam is assigned to two auxiliary variables.

The program shows that result_abap_val and js_abap_val are not affected by the method or function call, and that it is possible to pass a value to the ‘value‘ attribute of the SAPAbapMethParam class.

Handling classical exceptions

You can handle classical exceptions that are declared in the method definition using EXCEPTIONS and are raised in methods using RAISE in JavaScript. JavaScript does not then terminate. To handle exceptions in this way, you need to specify the optional parameter EXCEPTION (in uppercase and quotation marks) followed by an actual parameter, that is an instance of the predefined class SAPAbapMethParam.

Example

report DEMO_JAVA_SCRIPT_BIND_METH_EXC.

class C1 definition.
  public section.
    methods TEST exceptions EXC.
endclass.

class C1 implementation.
  method TEST.
    raise exc.
  endmethod.
endclass.

data OREF type ref to C1.

data SOURCE type STRING.
data JS_PROCESSOR type ref to CL_JAVA_SCRIPT.

data RESULT type STRING.

start-of-selection.

  JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ).

  JS_PROCESSOR->BIND( exporting NAME_OBJ  = 'abap'
                                NAME_PROP = 'Ref'
                      changing  DATA      = OREF ).

  create object OREF.

  concatenate
  'var except = new SAPAbapMethParam();           '
  'abap.Ref.invoke( "test", "EXCEPTION", except );'
  'except.value;                                  '
  into SOURCE separated by CL_ABAP_CHAR_UTILITIES=>CR_LF.

  JS_PROCESSOR->COMPILE(
                exporting
                  SCRIPT_NAME = 'TEST.JS'
                  SCRIPT      = SOURCE ).

  RESULT = JS_PROCESSOR->EXECUTE( 'TEST.JS' ).
  write / result.

In this example, an ABAP object of the local class C1 is bound to the JavaScript object abap.Ref using the OREF reference variable. In JavaScript, an object ‘except’ of the class SAPAbapMethParam is defined.

The ABAP method TEST is called in JavaScript and its exception EXC is handled. After the method call, the except.value property has the value EXC.

Handling class-based exceptions

You cannot handle class-based exceptions declared in the method definition using RAISING and are raised in methods using RAISE EXCEPTION in JavaScript. They cause JavaScript to terminate without filling the LAST_CONDITION_CODE and LAST_ERROR_MESSAGE attributes. Instead, the script can be executed in a TRY block so that you can handle the exceptions using CATCH.

Example

report DEMO_JAVA_SCRIPT_BIND_METH_CX.

class C1 definition.
  public section.
    data    ATTR type STRING.
    methods TEST raising CX_SY_ZERODIVIDE.
endclass.

class C1 implementation.
  method TEST.
    raise  exception type CX_SY_ZERODIVIDE.
    ATTR = 'Hello World!'.
  endmethod.
endclass.

data OREF type ref to C1.
data SOURCE type STRING.
data JS_PROCESSOR type ref to CL_JAVA_SCRIPT.
data RESULT type STRING.

data EXCREF type ref to CX_ROOT.
data TEXT   type STRING.

start-of-selection.

  JS_PROCESSOR = CL_JAVA_SCRIPT=>CREATE( ).

  JS_PROCESSOR->BIND( exporting NAME_OBJ  = 'abap'
                                NAME_PROP = 'Ref'
                      changing  DATA      = OREF ).

  create object OREF.

  concatenate
  'abap.Ref.invoke( "test" );'
  'abap.Ref.attr;            '
  into SOURCE separated by CL_ABAP_CHAR_UTILITIES=>CR_LF.

  JS_PROCESSOR->COMPILE(
                exporting
                  SCRIPT_NAME = 'TEST.JS'
                  SCRIPT      = SOURCE ).

  try.
      RESULT = JS_PROCESSOR->EXECUTE( 'TEST.JS' ).
      write / JS_PROCESSOR->LAST_ERROR_MESSAGE.
      write / RESULT.
    catch CX_ROOT into EXCREF.
      TEXT = EXCREF->GET_TEXT( ).
      message TEXT type 'I'.
  endtry.

If an exception occurs, JavaScript terminates and the exception is handled in the CATCH block.

 

 

 

Leaving content frame