On 11.08.2022 21:13, Rony G. Flatscher wrote:
In an ooRexx package there are the following statements:
... cut ...
::ROUTINE xBSF PUBLIC EXTERNAL "LIBRARY BSF4ooRexx BSF
"
... cut ...
::CLASS BSF
::ATTRIBUTE rBSF CLASS
::METHOD initCLASS
expose rBSF
rBSF =.routines["XBSF"] -- fetch and store routine object
... cut ...
::METHOD unknown UNGUARDED
... cut ...
signal on syntax
self~class~rBSF~callWith(arr) -- invoke external routine
return bsf.wrap(result)
syntax:
... cut ...
co=condition('o')
call ppJavaExceptionChain(co,.true)
raise propagate
So a native routine BSF() gets defined and named in the package as the public routine xBSF which
in the class constructor for the class BSF gets fetched from the .routines directory and stored as
a routine object with a class attribute named rBSF. In the BSF instance method unknown this
routine object gets fetched from the class attribute and using CALLWITH it gets invoked supplying
a Rexx array with arguments.
The native routine BSF() in this case may raise an exception using
rtc->RaiseException(Rexx_Error_Incorrect_call_user_defined, ra);
However, upon return from the native routine BSF the raised exception does not get trapped in the
ooRexx unknown method such that the code after the syntax label does not get executed.
Doing instead
res=xbsf("invoke", j4, "sendMessageScoped", "abc", "1", "2", "3")
traps the rtc->RaiseException() condition ("abc" in this test will not yield a
Rexx class object).
Sorry, the above statement is not equivalent, it needs to be rewritten as
jArgs=bsf.createJavaArrayOf("java.lang.Object", 1, 2, 3) -- with or without
quotes
res=xbsf("invoke", j4, "sendmessageScoped", "info", "abc", jArgs)
it then behaves as within the unknown method. In this variant a "Error 44.1: No data returned from
function "XBSF"." error will get raised.
Here the version that is equivalent to the one in the unknown method and does not trigger the syntax
handler on the Rexx code either:
call xbsf "invoke", j4, "sendmessageScoped", "info", "abc", jArgs
context->CheckCondition() immediately before returning to the calling Rexx program will be true in
the native code however the syntax handler does not get triggered.
For debugging purposes the native code defines context variables
[context->SetContextVariable("BSF_ERROR_MESSAGE",msg) and
context->SetContextVariable("BSF_ERROR_OBJECT",javaThrowable)] which are available and can be used
from the caller's context (which the test program does).
Tried to come up with a stand alone example that would exhibit this behaviour,
so far without success.
If there is anything I could do to become able to shed more light into this,
please let me know.
---rony
P.S.: Here the Rexx test program:
parse source s; say s
parse version v; say v
say .bsf4rexx~display.version
call test_plain_rexx
call test_rexx_proxy
::requires BSF.CLS
::class class_level1
::method info
return "info<< CLASS_LEVEL1 >>info <>"
::class class_level2 mixinclass class_level1
::method info
return "info<< CLASS_LEVEL2 >>info <>"
::class class_level3 mixinclass class_level1
::method info
return "info<< CLASS_LEVEL3 >>info <>"
::class class_level4 subclass class_level2 inherit class_level3
::method info
return "info<< CLASS_LEVEL4 >>info <>"
::routine test_plain_rexx
say .context~name":"
say
t4=.class_level4~new
say "t4~info:" t4~info
say "t4~info:" t4~info(1,2,3)
say "t4~info:class_level3:" t4~info:.class_level3
say "t4~info:class_level2:" t4~info:.class_level2
say "t4~info:class_level1:" t4~info:.class_level1
say "-"~copies(79)
::routine test_rexx_proxy -- via Java
say .context~name":"
say
t4=.class_level4~new
say "t4~info:" t4~info
j4=BsfCreateRexxProxy(t4) -- will box the Rexx object in a Java object
(of type RexxProxy which allows sending messages to the boxed Rexx object)
-- now send the boxed Rexx object various messages from the Java side
say "j4:" pp(j4) "j4~sendMessage0('info'):" j4~sendMessage0('info')
say "j4:" pp(j4) "j4~sendMessage3('info',1,2,3):"
j4~sendMessage3('info',1,2,3)
say "-"~copies(79)
say "j4:" pp(j4) "j4~sendMessageScoped('info',.class_level3,.nil):"
j4~sendMessageScoped('info', .class_level3, .nil)
say "j4:" pp(j4) "j4~sendMessageScoped('info',.class_level2,.nil):"
j4~sendMessageScoped('info', .class_level2, .nil)
say "j4:" pp(j4) "j4~sendMessageScoped('info',.class_level1,.nil):"
j4~sendMessageScoped('info', .class_level1, .nil)
jArgs=bsf.createJavaArrayOf("java.lang.Object", 1, 2, 3) -- arguments
must be boxed as a Java array object
say "j4:" pp(j4)