6525036 Super Contributor.
Super Contributor.
777 views

Dynamic namespace execution - is it possible?

Hi,

In my driver, I would like to call different java methods(or different ecma functions), dynamically, based on GCVs, because that way, I would only need one rule (to rule them all, and in the darkness bind them)

That means, that I iterate over a nodeset, and TRY to execute xpath("nexus:$lMethod").
$lMethod is in this instance GetActiveRoles().

The issue with this approach seems to be, that once a namespace is in use (be it java or excma script for example), I get errors like this:

Code(-9130) Error in vnd.nds.stream://META/dk/services/idm/Driver+Set/LB-NXRoles01/itp-GetActiveRoles#XmlData:239 : An invalid XPATH expression 'nexus:$lMethod' is specified: java.lang.IllegalArgumentException: DOMEvaluator parser error: ':' was unexpected

In other words, this works:
<token-xpath expression="nexus:GetActiveRoles()"/>

This does not work:
<token-xpath expression="nexus:$lMethod"/>

And $lMethod = "GetActiveRoles()"

Can anyone figure out a way to get this to work?
Labels (1)
0 Likes
12 Replies
Knowledge Partner
Knowledge Partner

Re: Dynamic namespace execution - is it possible?

6525036;2484880 wrote:
Hi,

In my driver, I would like to call different java methods(or different ecma functions), dynamically, based on GCVs, because that way, I would only need one rule (to rule them all, and in the darkness bind them)

That means, that I iterate over a nodeset, and TRY to execute xpath("nexus:$lMethod").
$lMethod is in this instance GetActiveRoles().

The issue with this approach seems to be, that once a namespace is in use (be it java or excma script for example), I get errors like this:

Code(-9130) Error in vnd.nds.stream://META/dk/services/idm/Driver+Set/LB-NXRoles01/itp-GetActiveRoles#XmlData:239 : An invalid XPATH expression 'nexus:$lMethod' is specified: java.lang.IllegalArgumentException: DOMEvaluator parser error: ':' was unexpected

In other words, this works:
<token-xpath expression="nexus:GetActiveRoles()"/>

This does not work:
<token-xpath expression="nexus:$lMethod"/>

And $lMethod = "GetActiveRoles()"

Can anyone figure out a way to get this to work?


What happens if you use ~ to reference the GCV?
0 Likes
6525036 Super Contributor.
Super Contributor.

Re: Dynamic namespace execution - is it possible?

dgersic;2484881 wrote:
What happens if you use ~ to reference the GCV?


Aha, a ~ gcv expression actually works in xpath java calls.

Now the issue is, that what I want to execute is based on what is in a list. It is a series of calls to be executed based on a structured GCV.
One instance looks like this:

					<definition display-name="Entity Name" name="name" type="string">
<description/>
<value>Active Roles</value>
</definition>
<definition display-name="Object Class" name="objclass" type="string">
<description>eDir object class</description>
<value>NEXUSRole</value>
</definition>
<definition display-name="GCV Name" name="gcv" type="string">
<description>Points to the "map" GCV to be used</description>
<value>map.nexus.attr</value>
</definition>
<definition display-name="Java Method to call" name="method" type="string">
<description/>
<value>GetActiveRoles()</value>
</definition>
<definition display-name="Do we want to process this one?" name="process" type="boolean">
<description/>
<value>true</value>
</definition>
</instance>


There are several of those, each with their own set of definitions.

Each definition set is looped over, and each definition is retrieved into local variables using xpath, like: $current-node/definition[@name='method']/value/text()


I tried to make the GCV refer to the local variable containing the value I want to call, that did of course not work.
I tried to redefine the GCV at runtime, and that was a bit to optimistic it seems.

So I wonder if there is any way that I can redefine the GCV at runtime, so I can use ~ notation to call my java method (since using $ notation does not work).
0 Likes
Knowledge Partner
Knowledge Partner

Re: Dynamic namespace execution - is it possible?

6525036;2484955 wrote:
Aha, a ~ gcv expression actually works in xpath java calls.

Now the issue is, that what I want to execute is based on what is in a list. It is a series of calls to be executed based on a structured GCV.
One instance looks like this:

					<definition display-name="Entity Name" name="name" type="string">
<description/>
<value>Active Roles</value>
</definition>
<definition display-name="Object Class" name="objclass" type="string">
<description>eDir object class</description>
<value>NEXUSRole</value>
</definition>
<definition display-name="GCV Name" name="gcv" type="string">
<description>Points to the "map" GCV to be used</description>
<value>map.nexus.attr</value>
</definition>
<definition display-name="Java Method to call" name="method" type="string">
<description/>
<value>GetActiveRoles()</value>
</definition>
<definition display-name="Do we want to process this one?" name="process" type="boolean">
<description/>
<value>true</value>
</definition>
</instance>


There are several of those, each with their own set of definitions.

Each definition set is looped over, and each definition is retrieved into local variables using xpath, like: $current-node/definition[@name='method']/value/text()


I tried to make the GCV refer to the local variable containing the value I want to call, that did of course not work.
I tried to redefine the GCV at runtime, and that was a bit to optimistic it seems.

So I wonder if there is any way that I can redefine the GCV at runtime, so I can use ~ notation to call my java method (since using $ notation does not work).


GCVs are, by their nature, not redefineable at runtime. You'd have to do this with local variables if you're going to change their values.
0 Likes
Knowledge Partner
Knowledge Partner

Re: Dynamic namespace execution - is it possible?


>> I tried to make the GCV refer to the local variable containing the
>> value I want to call, that did of course not work.
>> I tried to redefine the GCV at runtime, and that was a bit to
>> optimistic it seems.
>>
>> So I wonder if there is any way that I can redefine the GCV at
>> runtime, so I can use ~ notation to call my java method (since using $
>> notation does not work).

>
> GCVs are, by their nature, not redefineable at runtime. You'd have to do
> this with local variables if you're going to change their values.


Which is how he started and it did not work. 🙂



0 Likes
6525036 Super Contributor.
Super Contributor.

Re: Dynamic namespace execution - is it possible?

Indeed so.
Wonder how.
0 Likes
ffreitas Frequent Contributor.
Frequent Contributor.

Re: Dynamic namespace execution - is it possible?

add to your ECMA library:

function routecall( imethod ) {
var whattocall;
switch( String(imethod).toLowerCase() ) {
case 'getactiveroles':
whattocall = GetActiveRoles;
break;
case 'getotherstuff':
whattocall = GetOtherFunThings;
break;
// add more cases here as desired
default:
whattocall = function() {}; // default noop function
}
return whattocall();
}

call your router code from the DirXML-Script:

<token-xpath expression="nexus:routecall( $lMethod )"/>

$lMethod = "GetActiveRoles" <--- note that we don't add the ()

That should get you by. Bonus points that you could send more parameters and pass them to the next function, things can get pretty interesting at that point...
0 Likes
Knowledge Partner
Knowledge Partner

Re: Dynamic namespace execution - is it possible?

On 7/31/2018 7:14 PM, ffreitas wrote:
>
> add to your ECMA library:
>
> function routecall( imethod ) {
> var whattocall;
> switch( String(imethod).toLowerCase() ) {
> case 'getactiveroles':
> whattocall = GetActiveRoles;
> break;
> case 'getotherstuff':
> whattocall = GetOtherFunThings;
> break;
> // add more cases here as desired
> default:
> whattocall = function() {}; // default noop function
> }
> return whattocall();
> }
>
> call your router code from the DirXML-Script:
>
> <token-xpath expression="nexus:routecall( $lMethod )"/>
>
> $lMethod = "GetActiveRoles" <--- note that we don't add the ()
>
> That should get you by. Bonus points that you could send more parameters
> and pass them to the next function, things can get pretty interesting at
> that point...


That is fairly clever. Just requires predefining the functions in
advance. I think the OP was to define it in the policy itself, but I
think is probably the best he is going to get


0 Likes
6525036 Super Contributor.
Super Contributor.

Re: Dynamic namespace execution - is it possible?

Sweet, I'll try that ASAP.
Thanks a lot.
0 Likes
6525036 Super Contributor.
Super Contributor.

Re: Dynamic namespace execution - is it possible?

Hmmm..... nexus is a java namespace declaration. And this I cannot call an ecma script via the java namespace (nexus).

But following the idea you laid out.....
What I could do (and will try), is to make a java wrapper method, which I can call with parameters to call the other java methods.
That should work.

Anyway, I had never seen anything returned as what I suppose is a function call like this "return whattocall()"
Wonder if the same ecma routing could be done like this?

function routecall2( imethod ) {
return imethod();
}

And then just be called with parameters, that would be passed on and executed?
0 Likes
ffreitas Frequent Contributor.
Frequent Contributor.

Re: Dynamic namespace execution - is it possible?

apologies for the misread, assumed it was ECMA code. Two options then:

1 - make your routecall be a Java function that call other Java functions based on what you pass in as a string input

2 - Still use ECMA as the router, using the es: namespace to access, and call the java classes from it. Look at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java for some details on how to do so (by default IDM uses Rhino as the ECMA engine). Be mindful that since Java is strongly typed and Javascript/ECMAscript is not, only base primitive that can be safely passed is string. You may end up having to check input types and wrap them in their Java counterparts before passing them along.

on ECMA you cannot pass an name and run it, you have to pass a function reference for that to work. that is why I used a switch statement in my example so that we could map the Strings to actual function names.
0 Likes
6525036 Super Contributor.
Super Contributor.

Re: Dynamic namespace execution - is it possible?

ffreitas;2485026 wrote:
apologies for the misread, assumed it was ECMA code. Two options then:

1 - make your routecall be a Java function that call other Java functions based on what you pass in as a string input

2 - Still use ECMA as the router, using the es: namespace to access, and call the java classes from it. Look at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java for some details on how to do so (by default IDM uses Rhino as the ECMA engine). Be mindful that since Java is strongly typed and Javascript/ECMAscript is not, only base primitive that can be safely passed is string. You may end up having to check input types and wrap them in their Java counterparts before passing them along.

on ECMA you cannot pass an name and run it, you have to pass a function reference for that to work. that is why I used a switch statement in my example so that we could map the Strings to actual function names.


Thank you very much. Since I did not ever manage to convert a string to a java function, I ended up with this. It is not entirely as dynamic as I would like, but since it is in ecma, it will be adequate (read: I wont need to recompile java classes to change stuff).

function routecall( imethod ) {
var res;
var myObj = new Packages.pwc.KMDNexusPlugin();
switch( String(imethod).toLowerCase() ) {
case 'getactiveroles':
res = myObj.GetActiveRoles();
break;
case 'getinactiveroles':
res = myObj.GetInactiveRoles();
break;
case 'getorganisationalhierarchy':
res = myObj.GetOrganisationalHeirarchy();
break;
case 'getinactiveorganisations':
res = myObj.GetInactiveOrganisations();
break;
case 'getprofessional':
res = myObj.GetProfessional();
break;
case 'getprofessionals':
res = myObj.GetProfessionals();
break;

}

return res;
}
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.