As for Java scripting support according to JSR-223, here is some introductory documentation for you.
By default the Nashorn JavaScript engine is contained in the JRE, but since Java 11 you get a warning that it is deprecated and will be removed in the future. This is not a big problem because you will still be able to use it and there are also other JSR-223-compatible scripting languages available.
This example shows how to use
- JavaScript,
- Groovy and
- Lua
scripts from Java. Please make sure that you add the corresponding
libraries to your classpath if you want to use the additional two languages and not just the built-in JS engine.
The scripts in each language demonstrate the same basics things, i.e. how to
- call a method on a Java object (
File.getCanonicalPath()
) from the script,
- how to convert a string to upper case,
- how to repeat a string (in JS we have to define our own prototype method for that because Nashorn does not implement the
repeat(n)
method by itself).
package de.scrum_master.app;
import java.io.File;
import javax.script.*;
public class Application {
private static final ScriptEngineManager MANAGER = new ScriptEngineManager();
public static void main(String[] args) throws ScriptException {
listScriptingEngines();
System.out.println(runScript("JavaScript", "print(file.getCanonicalPath()); String.prototype.repeat = function(num) { return new Array(num + 1).join(this) }; (text.toUpperCase() + '_').repeat(2)"));
System.out.println(runScript("Groovy", "println file.canonicalPath; (text.toUpperCase() + '_') * 2"));
System.out.println(runScript("lua", "print(file:getCanonicalPath()); return string.rep(string.upper(text) .. '_', 2)"));
}
public static void listScriptingEngines() {
for (ScriptEngineFactory factory : MANAGER.getEngineFactories()) {
System.out.printf("Script Engine: %s (%s)%n", factory.getEngineName(), factory.getEngineVersion());
System.out.printf(" Language: %s (%s)%n", factory.getLanguageName(), factory.getLanguageVersion());
factory.getNames().stream().forEach(name -> System.out.printf(" Alias: %s%n", name));
}
}
public static String runScript(String language, String script) throws ScriptException {
ScriptEngine engine = MANAGER.getEngineByName(language);
// Expose Java objects as global variables to script engine
engine.put("file", new File("/my/" + language + "/test.txt"));
engine.put("text", language);
// Use script result for generating return value
return engine.eval(script) + "suffix";
}
}
If you run the program with groovy-all on the classpath, the output should look like this:
Script Engine: Groovy Scripting Engine (2.0)
Language: Groovy (2.4.13)
Alias: groovy
Alias: Groovy
Script Engine: Luaj (Luaj-jse 3.0.1)
Language: lua (5.2)
Alias: lua
Alias: luaj
Script Engine: Oracle Nashorn (1.8.0_211)
Language: ECMAScript (ECMA - 262 Edition 5.1)
Alias: nashorn
Alias: Nashorn
Alias: js
Alias: JS
Alias: JavaScript
Alias: javascript
Alias: ECMAScript
Alias: ecmascript
C:\my\JavaScript\test.txt
JAVASCRIPT_JAVASCRIPT_suffix
C:\my\Groovy\test.txt
GROOVY_GROOVY_suffix
C:\my\lua\test.txt
LUA_LUA_suffix
Of course in your own code you should replace the inline JS, Groovy or Lua code with something user-specific loaded from your code snippet database. You should also think about which variables you want to expose to the scripting engine and document it for your users.