Until now I only know that it is an interface that has the following methods:
-
invokeMethod ()
-
invokeFunction ()
-
getInterface ()
But I do not understand what each of them is for and exactly where the Invocable interface is concerned.
Until now I only know that it is an interface that has the following methods:
invokeMethod ()
invokeFunction ()
getInterface ()
But I do not understand what each of them is for and exactly where the Invocable interface is concerned.
This interface is used in machines that interpret other programming languages like javascript
, which for example is done with Nashorn.
Imagine you have javascript like:
String javascript = "function multiplica(a, b) { return a * b; }\n"
+ "function divide(a, b) { return a / b; }"
With the script machine you implement the Invocable
interface to call functions from Java with invokeFunction () :
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
// cargemos el código para que la maquina lo evalua
engine.eval(javascript);
// la maquina implementa la interfaz Invocable
Invocable js = (Invocable) engine;
// podemos llamar a funciones así:
System.out.println(js.invokeFunction("multiplica",3,5)
// eso imprime 15
We can also create java interfaces with getInterface () to access the script:
interface Calculador{
multiplica(int a, int b);
divide(int a, int b);
}
// con eso podemos obtener una interfaz de Java del script
Calculador calc = js.getInterface(Calculador.class);
System.out.println(calc.multiplica(2,3));
// imprime 6
System.out.println(calc.divide(8,4));
// imprime 2
The last method invokeMethod () is similar to invokeFunction
but allows you to call methods of an object:
// cargemos un objeto en javascript
Object jsObjeto = engine.eval(new FileReader("Printer.js"));
// llamamos a Printer.print( nombre )
js.invokeMethod(jsObjeto, "print", "foo" );
When a scripts engine (which implements javax.script.ScriptEngine
) also implements, in turn, the interface javax.script.Invocable
, means that you can execute procedures, functions or methods that have previously been compiled .
That is, instead of using the eval
of javax.script.ScriptEngine
method, you can invoke the procedure or function or method directly from a Java program. It should be noted that the implementation of the interface Invocable
by a scripts engine is optional. Before invoking any procedure, function or method, you should check if the script engine is an instance of this interface, make a cast to Invocable
, and then execute the methods of this interface.
This interface contains four methods. The two versions of the method getInterface()
allow to obtain an instance of a Java interface which is implemented in a language of scripting (eg: factorial.js
). The invokeFunction()
method allows you to invoke a higher level function (eg: parseInt()
) written in a scripting language. The invokeMethod()
method allows invocation of object methods (eg: obj.toString()
) written in a scripting language.
If you want to make an invocation of this type, you can follow the following steps:
First check if the scripts engine is Invocable
:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
if (engine instanceof Invocable) {
// Es invocable :-)
} else {
// No es invocable :'(
}
Make a cast to the ScriptEngine
to Invocable
reference:
Invocable inv = (Invocable) engine;
Evaluate a script for the engine to compile it and save the compiled for future invocations:
String script = "def sumar(a, b)\n return a + b\nend";
engine.eval(script);
Invoking the procedure, function or method:
Object result = inv.invokeFunction("sumar", 1, 2);
A scripts engine can also implement the interface javax.script.Compilable
which allows you to compile scripts to execute it repeatedly.
References