We are having problems calling recursively a function in the context of an EJB called function.
The problem relates to the usage of the ObFunction.getCaller() method.
Context:
In order to use the ObFunction.getUserDefinedMap() method, that retrieves an HashMap contained in the ObFunction object, we use (and have been using for several years) the following source code:
// The System.out lines have been added in order to explain what is happening
try {
ObFunction function = getFunction();
HashMap hm;
System.out.println("==========> Before While: calling <" + function + "> got caller <" + function.getCaller() + ">");
while (function.getCaller()!=null){
String calling = function.toString();
function = function.getCaller();
System.out.println("==========> Inside While: calling <" + calling + "> got caller <" + function.toString() + ">");
}
System.out.println("==========> After While: root function <" + function.toString() + ">");
if (function.getUserDefinedMap() == null) {
hm = new HashMap();
function.putUserDefinedMap(hm);
} else {
hm = function.getUserDefinedMap();
}
hm.put("DebugLevel", v.getVariable(m_strVarNcs0800_Debug).getAsObIntFldField(m_strVarDebug_Level).getValue());
hm.put("Logger", v.getVariable(m_strVarNcs0800_Debug).getAsObCharFldField(m_strVarLogger).getValue());
} catch (Exception e) {
PlexLogger.errorWithLogger(v.getVariable(m_strVarNcs0800_Debug).getAsObCharFldField(m_strVarLogger).getValue(), e);
}
What this does is that provides a simple and universal way to place gloval variables of any sort in a Java specific mechanism. This is really useful to share variables of any type between ObFunction objects. The key idea is that there can only be one HaskMap and, so, what is being made is to find the initial caller function and search for the HashMap variable exclusively in that function.
So far so good: this works like a treat. Up until the moment we try calling recursively function in the context of an EJB function call. Only in the context of an EJB call: the same function called directly doesn't miss behave.
We have this scenario:
Function "IMS8583.Ncs0800" is initialy called. In this call, the HashMap variable hm is created and placed in the ObFunction instance
Function "IMS8583.Ncs0800" calls itself. In this call, the ObFunction instance uses the getCaller() method and finds another "IMS8583.Ncs0800" instance as its parent. It gets the hm variable and reads from it whatever it needs.
The second "IMS8583.Ncs0800" terminates
The first "IMS8583.Ncs0800" also terminates
This is the log from the System out of this description:
==========> Before While: calling <[email protected]> got caller <null>
==========> After While: root function <[email protected]>
==========> Before While: calling <[email protected]> got caller <[email protected]>
==========> Inside While: calling <[email protected]> got caller <[email protected]>
==========> After While: root function <[email protected]>
The first two lines are from the first instance and the following three lines are from the second, called by the the first.
This exact same function called through an EJB behaves like this:
[28-11-2016 16:34:38:096 GMT] 0000009f SystemOut O ==========> Before While: calling <[email protected]> got caller <null>
[28-11-2016 16:34:38:096 GMT] 0000009f SystemOut O ==========> After While: root function <[email protected]>
[28-11-2016 16:34:38:557 GMT] 0000009f SystemOut O ==========> Before While: calling <[email protected]> got caller <[email protected]>
[28-11-2016 16:34:38:557 GMT] 0000009f SystemOut O ==========> Inside While: calling <[email protected]> got caller <[email protected]>
[28-11-2016 16:34:38:558 GMT] 0000009f SystemOut O ==========> Inside While: calling <[email protected]> got caller <[email protected]>
[28-11-2016 16:34:38:558 GMT] 0000009f SystemOut O ==========> Inside While: calling <[email protected]> got caller <[email protected]>
[28-11-2016 16:34:38:558 GMT] 0000009f SystemOut O ==========> Inside While: calling <[email protected]> got caller <[email protected]>
[28-11-2016 16:34:38:558 GMT] 0000009f SystemOut O ==========> Inside While: calling <[email protected]> got caller <[email protected]>
... and this loops forever
So, in short, it seems that in the context of an EJB recursive call, the recursive called function gets the parent as itself, making it impossible to find the root caller.
In case of a normal function call, separate function object gets created and this is the reason why the loop breaks when it identifies the root caller.
Same logic should work for EJB call as well. But here application server container is controlling the function instance, it is creating only one function object and makes recursive calls. In short all recursive calls are being made on only one function instance. This is why it is going into infinite loop.
At this moment same logic won’t work here. We need to change the logic in source code API so that it should work for both normal function call and EJB call.
Change the condition in while loop like below to break the infinite loop.
while (function.getCaller()!=null && function != function.getCaller())
With this if the caller and called functions both are pointing to same function object then loop terminates. Please change the logic accordingly in source code API and check once.