This is a personal memo as a result of investigating "Can some Java processing be injected from the outside?"
When I looked it up, there was a ** JavaScript scripting engine (Nashorn) ** on Java, so I tried using it. Nashorn can be called from the Java SE 8 javax.script package.
This is a sample code that delegates the filtering process of List
to JavaScript.
Main.java
public class Main {
public static void main(String[] args) throws Exception {
List<Person> list = Arrays.asList(new Person("a", 1), new Person("b", 2), new Person("c", 3));
//Delegate JavaScript filtering
List<Person> resultList = list.stream().filter(e -> eval(e)).collect(Collectors.toList());
//Show list before filter
System.out.println("Before filter: " + list);
//Show filtered list
System.out.println("After filtering: " + resultList);
}
/**
*Evaluate JavaScript execution results
* @param person
* @return true/false
*/
public static boolean eval(Person person) {
boolean result = false;
try {
ScriptEngineManager manager = new ScriptEngineManager();
//Create a JavaScript engine
ScriptEngine engine = manager.getEngineByName("javascript");
//Set Java object to JavaScript variable
engine.put("person", person);
//Read a JavaScript file from a file
Reader script = new InputStreamReader(Main.class.getResourceAsStream("sample.js"));
//Execute JavaScript
result = Boolean.valueOf(true).equals(engine.eval(script));
} catch(ScriptException ex) {
ex.printStackTrace();
}
return result;
}
}
A Java object that is an element in the list.
We have defined a public
getter so that we can access field variables from JavaScript.
Person.java
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public String toString() {
return "{ name: " + this.name + ", age: " + this.age + "}";
}
}
The following sample.js is processing the filter
method on the Java side.
I was also able to access the fields of the person
object passed by Java.
sample.js
//person is an element of the list passed from the Java side
//Access the name field and use it in the judgment formula
person.name === 'a' || person.name === 'b';
The processing result of the above sample code is as follows.
From the evaluation result of sample.js, you can see that the contents of List
have been filtered.
Before filter: [{ name: a, age: 1}, { name: b, age: 2}, { name: c, age: 3}]
After filtering: [{ name: a, age: 1}, { name: b, age: 2}]
If you use it like this case, For example, I found it convenient to create a list on the screen where the user can change the filtering conditions each time.
Below is a reference link. Basics of JavaScript engine Nashorn on Java OpenJDK wiki >> Nashorn
Recommended Posts