Reputation: 9706
Consider the code:
Example 1
var Executors = java.util.concurrent.Executors;
var executor = Executors.newCachedThreadPool();
var fork = function (callable) {
// Clarify Runnable versus Callable overloaded methods
executor['submit(java.util.concurrent.Callable)'](callable);
};
fork(function(){ ... }); //ok
This works.
But this does not work:
Example 2
var Executors = java.util.concurrent.Executors;
var executor = Executors.newCachedThreadPool();
var fork = executor['submit(java.util.concurrent.Callable)'];
fork(function(){ ... }); //fails, NullPointerException
I assume, it is because fork
here is not a JS Function instance, it is actually an instance of jdk.internal.dynalink.beans.SimpleDynamicMethod
I tried to use fork.apply(executor,function() { ... });
but natrually, SimpleDynamicMethod has no apply
.
Why is it, actually, that Example 2 does not work, while Example 1 does?
Is it simply a perk of Nashorn? It there a better way to define fork() function than in Example 1?
Update
In example 2,
print(typeof fork);
reports function
print(fork)
reports [jdk.internal.dynalink.beans.SimpleDynamicMethod Future java.util.concurrent.AbstractExecutorService.submit(Callable)]
and exception is (with line 13 reading fork(function() {
)
Exception in thread "main" java.lang.NullPointerException
at jdk.nashorn.internal.scripts.Script$\^eval\_._L5(<eval>:13)
at jdk.nashorn.internal.scripts.Script$\^eval\_.runScript(<eval>:5)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:527)
Upvotes: 3
Views: 1398
Reputation: 4595
Unfortunately, currently you can't use bind
, apply
, and call
with POJO methods. I'd like to add that as a future enhancement. The best you can currently do in your above example is:
executor['submit(Callable)'](function() { ... })
Note that while in general indexed access to a property (using the []
operator) is less efficient than property name access (using the .
operator), Nashorn recognizes indexed access with a string literal and treats it just as efficiently as a property name access, so you don't suffer a slowdown here, just a bit of visual noise. In the case above, it will actually end up getting linked to the executor's virtual method directly.
Speaking of visual noise, you don't have to fully qualify java.util.concurrent.Callable
. When the non-qualified name of the parameter type is sufficient to disambiguate the overloads (which is pretty much always), you can just use the non-qualified name, regardless of what package it is in (works for your own classes too).
Upvotes: 3
Reputation: 1177
The problem is that you are missing the receiver 'executor' from the call. In general, 'fetching' Java functions is only practical with static Java functions. For example:
jjs> var abs = java.lang.Math.abs;
jjs> abs(-10);
10
In your example, we could have bound fork to executor and make it equivalently static. This support is currently not present. We should probably have support for adding the receiver as the first argument if 'fetched' from a class. Will file an enhancement request for a future release.
Upvotes: 1
Reputation: 5456
Alex,
In example 1, var fork
is a function that returns array executor
. In example 2, var fork
is an array. That is why you cant use ()
and apply
.
Does fork[0](function(){...})
work for you ?
Thanks
Upvotes: 0