aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/plugins-executor/plugins-executor-javascript/src/main
diff options
context:
space:
mode:
authorliamfallon <liam.fallon@est.tech>2020-03-05 10:50:48 +0000
committerliamfallon <liam.fallon@est.tech>2020-03-09 18:30:13 +0000
commit6bda5d7e4e80d1aefb4f19203361b7199448e70f (patch)
treeb28a68625cec91c57f0383d185f73fdf165ab558 /plugins/plugins-executor/plugins-executor-javascript/src/main
parentf876b34ec297495df20394c248b899d610e1bcce (diff)
Use Rhino javascript executor in apex-pdp
Integation unit tests resultd in StackOverflowException errors in the Graal Javascript interpreter. Following extensive testing and trouobleshooting, it proved very difficult to fix these issues in Graal as the stck overflow errors were occurring in native class instantiation methods being invoked by Grall on the JVM. The alternative Rhino Javascript engine is developed by mozilla, and was incorporated into the Java 6 JVM and evolved into Nashorn in the Java 8 JVM. Oracle dropped Nashorn in Java 11. However, in parallel, Rhino development has continued. This review brings in the Rhino javascript engine into apex-pdp as the replacement for Nashorn and instead of Graal. Graal seems to be pretty unstable as yet so we may bring it in in future releases but for now Rhino is a more stable and reliable alternative. Issue-ID: POLICY-2106 Change-Id: I0edeff3b0bee404b38e3ebe22001a6e3375a44dc Signed-off-by: liamfallon <liam.fallon@est.tech>
Diffstat (limited to 'plugins/plugins-executor/plugins-executor-javascript/src/main')
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java82
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java16
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java17
-rw-r--r--plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java15
4 files changed, 86 insertions, 44 deletions
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
index 93f6216fc..c80f58fbe 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptExecutor.java
@@ -20,9 +20,10 @@
package org.onap.policy.apex.plugins.executor.javascript;
-import org.graalvm.polyglot.Context;
-import org.graalvm.polyglot.HostAccess;
-import org.graalvm.polyglot.Value;
+import org.apache.commons.lang3.StringUtils;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
@@ -32,35 +33,50 @@ import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
* @author Liam Fallon (liam.fallon@ericsson.com)
*/
public class JavascriptExecutor {
+ public static final int DEFAULT_OPTIMIZATION_LEVEL = 9;
+
+ // Recurring string constants
+ private static final String WITH_MESSAGE = " with message: ";
+
// The key of the subject that wants to execute Javascript code
final AxKey subjectKey;
- // The Javascript context
- private final Context jsContext;
+ private Context javascriptContext;
+ private Script script;
/**
- * Prepares the executor for processing.
+ * Initializes the Javascripe executor.
*
* @param subjectKey the key of the subject that is requesting Javascript execution
- * @throws StateMachineException thrown when instantiation of the executor fails
*/
- public JavascriptExecutor(final AxKey subjectKey) throws StateMachineException {
+ public JavascriptExecutor(final AxKey subjectKey) {
this.subjectKey = subjectKey;
+ }
- // @formatter:off
- jsContext =
- Context.newBuilder("js")
- .allowHostClassLookup(s -> true)
- .allowHostAccess(HostAccess.ALL)
- .build();
- // @formatter:on
+ /**
+ * Prepares the executor for processing and compiles the Javascript code.
+ *
+ * @param javascriptCode the Javascript code to execute
+ * @throws StateMachineException thrown when instantiation of the executor fails
+ */
+ public void init(final String javascriptCode) throws StateMachineException {
+ if (StringUtils.isEmpty(javascriptCode)) {
+ throw new StateMachineException("no logic specified for " + subjectKey.getId());
+ }
try {
- jsContext.getBindings("js");
+ // Create a Javascript context for this thread
+ javascriptContext = Context.enter();
+
+ // Set up the default values of the context
+ javascriptContext.setOptimizationLevel(DEFAULT_OPTIMIZATION_LEVEL);
+ javascriptContext.setLanguageVersion(Context.VERSION_1_8);
+
+ script = javascriptContext.compileString(javascriptCode, subjectKey.getId(), 1, null);
} catch (Exception e) {
- jsContext.close();
+ Context.exit();
throw new StateMachineException(
- "prepare: javascript engine failed to initialize properly for \"" + subjectKey.getId() + "\"", e);
+ "logic failed to compile for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
}
}
@@ -68,28 +84,30 @@ public class JavascriptExecutor {
* Executes the the Javascript code.
*
* @param executionContext the execution context of the subject to be passed to the Javascript context
- * @param javascriptCode the Javascript code to execute
* @return true if the Javascript executed properly
* @throws StateMachineException thrown when Javascript execution fails
*/
- public boolean execute(final Object executionContext, final String javascriptCode) throws StateMachineException {
+ public boolean execute(final Object executionContext) throws StateMachineException {
+ Object returnObject = null;
+
try {
- // Set up the Javascript engine context
- jsContext.getBindings("js").putMember("executor", executionContext);
- jsContext.eval("js", javascriptCode);
+ // Pass the subject context to the Javascript engine
+ Scriptable javascriptScope = javascriptContext.initStandardObjects();
+ javascriptScope.put("executor", javascriptScope, executionContext);
+ // Run the script
+ returnObject = script.exec(javascriptContext, javascriptScope);
} catch (final Exception e) {
- throw new StateMachineException("execute: logic failed to run for \"" + subjectKey.getId() + "\"", e);
+ throw new StateMachineException(
+ "logic failed to run for " + subjectKey.getId() + WITH_MESSAGE + e.getMessage(), e);
}
- Value returnValue = jsContext.getBindings("js").getMember("returnValue");
-
- if (returnValue == null || returnValue.isNull()) {
+ if (!(returnObject instanceof Boolean)) {
throw new StateMachineException(
- "execute: logic failed to set a return value for \"" + subjectKey.getId() + "\"");
+ "execute: logic for " + subjectKey.getId() + " returned a non-boolean value " + returnObject);
}
- return returnValue.asBoolean();
+ return (boolean) returnObject;
}
/**
@@ -99,10 +117,10 @@ public class JavascriptExecutor {
*/
public void cleanUp() throws StateMachineException {
try {
- jsContext.close();
+ Context.exit();
} catch (final Exception e) {
- throw new StateMachineException(
- "cleanUp: executor cleanup failed to close for \"" + subjectKey.getId() + "\"", e);
+ throw new StateMachineException("cleanUp: executor cleanup failed to close for " + subjectKey.getId()
+ + WITH_MESSAGE + e.getMessage(), e);
}
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
index 18a6ef58a..27e649fd3 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptStateFinalizerExecutor.java
@@ -52,7 +52,12 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
// Call generic prepare logic
super.prepare();
+ // Create the executor
javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
+
+ // Initialize and cleanup the executor to check the Javascript code
+ javascriptExecutor.init(getSubject().getLogic());
+ javascriptExecutor.cleanUp();
}
/**
@@ -71,8 +76,13 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
// Do execution pre work
executePre(executionId, executionProperties, incomingFields);
- // Execute the Javascript and do post processing
- executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getLogic()));
+ // Execute the Javascript executor
+ javascriptExecutor.init(getSubject().getLogic());
+ boolean result = javascriptExecutor.execute(getExecutionContext());
+ javascriptExecutor.cleanUp();
+
+ // Execute the Javascript
+ executePost(result);
return getOutgoing();
}
@@ -86,7 +96,5 @@ public class JavascriptStateFinalizerExecutor extends StateFinalizerExecutor {
public void cleanUp() throws StateMachineException {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getLogicFlavour() + ","
+ getSubject().getLogic());
-
- javascriptExecutor.cleanUp();
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
index 29fae193e..bec5670c5 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java
@@ -52,7 +52,12 @@ public class JavascriptTaskExecutor extends TaskExecutor {
// Call generic prepare logic
super.prepare();
+ // Create the executor
javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
+
+ // Initialize and cleanup the executor to check the Javascript code
+ javascriptExecutor.init(getSubject().getTaskLogic().getLogic());
+ javascriptExecutor.cleanUp();
}
/**
@@ -68,11 +73,17 @@ public class JavascriptTaskExecutor extends TaskExecutor {
@Override
public Map<String, Object> execute(final long executionId, final Properties executionProperties,
final Map<String, Object> incomingFields) throws StateMachineException, ContextException {
+
// Do execution pre work
executePre(executionId, executionProperties, incomingFields);
- // Execute the Javascript and do post processing
- executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getTaskLogic().getLogic()));
+ // Execute the Javascript executor
+ javascriptExecutor.init(getSubject().getTaskLogic().getLogic());
+ boolean result = javascriptExecutor.execute(getExecutionContext());
+ javascriptExecutor.cleanUp();
+
+ // Execute the Javascript
+ executePost(result);
return getOutgoing();
}
@@ -86,7 +97,5 @@ public class JavascriptTaskExecutor extends TaskExecutor {
public void cleanUp() throws StateMachineException {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogicFlavour()
+ "," + getSubject().getTaskLogic().getLogic());
-
- javascriptExecutor.cleanUp();
}
}
diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
index 41585fbd0..c32b70991 100644
--- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
+++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskSelectExecutor.java
@@ -53,7 +53,11 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
// Call generic prepare logic
super.prepare();
+ // Create the executor
javascriptExecutor = new JavascriptExecutor(getSubject().getKey());
+
+ // Initialize and cleanup the executor to check the Javascript code
+ javascriptExecutor.init(getSubject().getTaskSelectionLogic().getLogic());
}
/**
@@ -72,8 +76,13 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
// Do execution pre work
executePre(executionId, executionProperties, incomingEvent);
- // Execute the Javascript and do post processing
- executePost(javascriptExecutor.execute(getExecutionContext(), getSubject().getTaskSelectionLogic().getLogic()));
+ // Execute the Javascript executor
+ javascriptExecutor.init(getSubject().getTaskSelectionLogic().getLogic());
+ boolean result = javascriptExecutor.execute(getExecutionContext());
+ javascriptExecutor.cleanUp();
+
+ // Execute the Javascript
+ executePost(result);
return getOutgoing();
}
@@ -88,7 +97,5 @@ public class JavascriptTaskSelectExecutor extends TaskSelectExecutor {
LOGGER.debug("cleanUp:" + getSubject().getKey().getId() + ","
+ getSubject().getTaskSelectionLogic().getLogicFlavour() + ","
+ getSubject().getTaskSelectionLogic().getLogic());
-
- javascriptExecutor.cleanUp();
}
}