You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mt...@apache.org on 2020/12/10 02:51:22 UTC

[nifi] branch main updated: NIFI-8080: Move script compilation to configurator init method

This is an automated email from the ASF dual-hosted git repository.

mthomsen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 1f8b4e4  NIFI-8080: Move script compilation to configurator init method
1f8b4e4 is described below

commit 1f8b4e477943eb5b7edadec8b30f3c8f123593c0
Author: Matthew Burgess <ma...@apache.org>
AuthorDate: Wed Dec 9 14:24:40 2020 -0500

    NIFI-8080: Move script compilation to configurator init method
    
    This closes #4718
    
    Signed-off-by: Mike Thomsen <mt...@apache.org>
---
 .../lookup/script/BaseScriptedLookupService.java   |  1 +
 .../nifi/processors/script/ExecuteScript.java      |  1 +
 .../processors/script/InvokeScriptedProcessor.java |  1 +
 .../script/ScriptEngineConfigurator.java           |  2 +-
 .../apache/nifi/record/script/ScriptedReader.java  |  1 +
 .../record/script/ScriptedRecordSetWriter.java     |  1 +
 .../record/sink/script/ScriptedRecordSink.java     |  1 +
 .../reporting/script/ScriptedReportingTask.java    |  1 +
 .../rules/engine/script/ScriptedRulesEngine.java   |  1 +
 .../handlers/script/ScriptedActionHandler.java     |  1 +
 .../nifi/script/ScriptingComponentHelper.java      | 16 +-------
 .../impl/ClojureScriptEngineConfigurator.java      |  2 +-
 .../impl/GroovyScriptEngineConfigurator.java       |  4 +-
 .../impl/JavascriptScriptEngineConfigurator.java   |  2 +-
 .../impl/JythonScriptEngineConfigurator.java       | 21 +++++-----
 ...est.groovy => ScriptedReportingTaskTest.groovy} | 48 +++++++++++++++++++++-
 .../src/test/resources/jython/test_log_vm_stats.py | 29 +++++++++++++
 17 files changed, 103 insertions(+), 30 deletions(-)

diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java
index c67e8e8..7d63724 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/lookup/script/BaseScriptedLookupService.java
@@ -273,6 +273,7 @@ public class BaseScriptedLookupService extends AbstractScriptedControllerService
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
index e05ec85..82ec3ad 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ExecuteScript.java
@@ -232,6 +232,7 @@ public class ExecuteScript extends AbstractSessionFactoryProcessor implements Se
 
                 // Evaluate the script with the configurator (if it exists) or the engine
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptToRun, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptToRun, scriptingComponentHelper.getModules());
                 } else {
                     scriptEngine.eval(scriptToRun);
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
index 196e78c..7600549 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/InvokeScriptedProcessor.java
@@ -349,6 +349,7 @@ public class InvokeScriptedProcessor extends AbstractSessionFactoryProcessor {
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java
index f30c7da..c734976 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/ScriptEngineConfigurator.java
@@ -33,7 +33,7 @@ public interface ScriptEngineConfigurator {
 
     URL[] getModuleURLsForClasspath(String[] modulePaths, ComponentLog log);
 
-    Object init(ScriptEngine engine, String[] modulePaths) throws ScriptException;
+    Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException;
 
     Object eval(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException;
 
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java
index ac9f2b7..25d0563 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedReader.java
@@ -91,6 +91,7 @@ public class ScriptedReader extends AbstractScriptedRecordFactory<RecordReaderFa
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedRecordSetWriter.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedRecordSetWriter.java
index f32141a..6a17f79 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedRecordSetWriter.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/script/ScriptedRecordSetWriter.java
@@ -95,6 +95,7 @@ public class ScriptedRecordSetWriter extends AbstractScriptedRecordFactory<Recor
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/sink/script/ScriptedRecordSink.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/sink/script/ScriptedRecordSink.java
index a5a481c..89f67a9 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/sink/script/ScriptedRecordSink.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/record/sink/script/ScriptedRecordSink.java
@@ -144,6 +144,7 @@ public class ScriptedRecordSink extends AbstractScriptedControllerService implem
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/reporting/script/ScriptedReportingTask.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/reporting/script/ScriptedReportingTask.java
index 189412e..8096498 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/reporting/script/ScriptedReportingTask.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/reporting/script/ScriptedReportingTask.java
@@ -189,6 +189,7 @@ public class ScriptedReportingTask extends AbstractReportingTask {
 
                 // Evaluate the script with the configurator (if it exists) or the engine
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptToRun, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptToRun, scriptingComponentHelper.getModules());
                 } else {
                     scriptEngine.eval(scriptToRun);
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/engine/script/ScriptedRulesEngine.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/engine/script/ScriptedRulesEngine.java
index 240c6c3..7118483 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/engine/script/ScriptedRulesEngine.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/engine/script/ScriptedRulesEngine.java
@@ -115,6 +115,7 @@ public class ScriptedRulesEngine extends AbstractScriptedControllerService imple
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/handlers/script/ScriptedActionHandler.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/handlers/script/ScriptedActionHandler.java
index 9d6145f..6138e98 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/handlers/script/ScriptedActionHandler.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/rules/handlers/script/ScriptedActionHandler.java
@@ -117,6 +117,7 @@ public class ScriptedActionHandler extends AbstractScriptedControllerService imp
                 // Find a custom configurator and invoke their eval() method
                 ScriptEngineConfigurator configurator = scriptingComponentHelper.scriptEngineConfiguratorMap.get(scriptingComponentHelper.getScriptEngineName().toLowerCase());
                 if (configurator != null) {
+                    configurator.init(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                     configurator.eval(scriptEngine, scriptBody, scriptingComponentHelper.getModules());
                 } else {
                     // evaluate the script
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/ScriptingComponentHelper.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/ScriptingComponentHelper.java
index 41b9bad..fce68fc 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/ScriptingComponentHelper.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/ScriptingComponentHelper.java
@@ -29,7 +29,6 @@ import org.apache.nifi.util.StringUtils;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
 import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -267,19 +266,8 @@ public class ScriptingComponentHelper {
 
             for (int i = 0; i < numberOfScriptEngines; i++) {
                 ScriptEngine scriptEngine = createScriptEngine();
-                try {
-                    if (configurator != null) {
-                        configurator.init(scriptEngine, modules);
-                    }
-                    if (!engineQ.offer(scriptEngine)) {
-                        log.error("Error adding script engine {}", new Object[]{scriptEngine.getFactory().getEngineName()});
-                    }
-
-                } catch (ScriptException se) {
-                    log.error("Error initializing script engine configurator {}", new Object[]{scriptEngineName});
-                    if (log.isDebugEnabled()) {
-                        log.error("Error initializing script engine configurator", se);
-                    }
+                if (!engineQ.offer(scriptEngine)) {
+                    log.error("Error adding script engine {}", new Object[]{scriptEngine.getFactory().getEngineName()});
                 }
             }
         } finally {
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ClojureScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ClojureScriptEngineConfigurator.java
index 85b3456..3754d4c 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ClojureScriptEngineConfigurator.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ClojureScriptEngineConfigurator.java
@@ -54,7 +54,7 @@ public class ClojureScriptEngineConfigurator extends AbstractModuleClassloaderCo
 
 
     @Override
-    public Object init(ScriptEngine engine, String[] modulePaths) throws ScriptException {
+    public Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
         scriptEngine = engine;
         return scriptEngine;
     }
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/GroovyScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/GroovyScriptEngineConfigurator.java
index db1240d..b86d356 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/GroovyScriptEngineConfigurator.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/GroovyScriptEngineConfigurator.java
@@ -44,7 +44,9 @@ public class GroovyScriptEngineConfigurator extends AbstractModuleClassloaderCon
 
 
     @Override
-    public Object init(ScriptEngine engine, String[] modulePaths) throws ScriptException {
+    public Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
+        // No need to compile the script here, Groovy does it under the hood and its CompiledScript object just
+        // calls engine.eval() the same as we do in the eval() method below
         scriptEngine = engine;
         return scriptEngine;
     }
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JavascriptScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JavascriptScriptEngineConfigurator.java
index fe64b4c..f89d06f 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JavascriptScriptEngineConfigurator.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JavascriptScriptEngineConfigurator.java
@@ -30,7 +30,7 @@ public class JavascriptScriptEngineConfigurator extends AbstractModuleClassloade
     }
 
     @Override
-    public Object init(ScriptEngine engine, String[] modulePaths) throws ScriptException {
+    public Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
         // No initialization methods needed at present
         return engine;
     }
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JythonScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JythonScriptEngineConfigurator.java
index 7dac7ba..30aeb43 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JythonScriptEngineConfigurator.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/JythonScriptEngineConfigurator.java
@@ -48,10 +48,17 @@ public class JythonScriptEngineConfigurator implements ScriptEngineConfigurator
     }
 
     @Override
-    public Object init(ScriptEngine engine, String[] modulePaths) {
+    public Object init(ScriptEngine engine, String scriptBody, String[] modulePaths) throws ScriptException {
         // Always compile when first run
-        compiledScriptRef.set(null);
-        return null;
+        if (engine != null && compiledScriptRef.get() == null) {
+                // Add prefix for import sys and all jython modules
+                String prefix = "import sys\n"
+                        + Arrays.stream(modulePaths).map((modulePath) -> "sys.path.append(" + PyString.encode_UnicodeEscape(modulePath, true) + ")")
+                        .collect(Collectors.joining("\n"));
+                final CompiledScript compiled = ((Compilable) engine).compile(prefix + scriptBody);
+                compiledScriptRef.set(compiled);
+        }
+        return compiledScriptRef.get();
     }
 
     @Override
@@ -60,13 +67,7 @@ public class JythonScriptEngineConfigurator implements ScriptEngineConfigurator
         if (engine != null) {
             final CompiledScript existing = compiledScriptRef.get();
             if (existing == null) {
-
-                // Add prefix for import sys and all jython modules
-                String prefix = "import sys\n"
-                        + Arrays.stream(modulePaths).map((modulePath) -> "sys.path.append(" + PyString.encode_UnicodeEscape(modulePath, true) + ")")
-                        .collect(Collectors.joining("\n"));
-                final CompiledScript compiled = ((Compilable) engine).compile(prefix + scriptBody);
-                compiledScriptRef.compareAndSet(null, compiled);
+                throw new ScriptException("Jython script has not been compiled, the processor must be restarted.");
             }
             returnValue = compiledScriptRef.get().eval();
         }
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy
similarity index 81%
rename from nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy
rename to nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy
index f9c6876..a77d4c7 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskGroovyTest.groovy
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/groovy/org/apache/nifi/reporting/script/ScriptedReportingTaskTest.groovy
@@ -58,8 +58,8 @@ import static org.mockito.Mockito.when
  * Unit tests for ScriptedReportingTask.
  */
 @RunWith(JUnit4.class)
-class ScriptedReportingTaskGroovyTest {
-    private static final Logger logger = LoggerFactory.getLogger(ScriptedReportingTaskGroovyTest)
+class ScriptedReportingTaskTest {
+    private static final Logger logger = LoggerFactory.getLogger(ScriptedReportingTaskTest)
     def task
     def runner
     def scriptingComponent
@@ -197,6 +197,50 @@ class ScriptedReportingTaskGroovyTest {
 
     }
 
+    @Test
+    void testVMEventsJythonScript() {
+
+        def properties = [:] as Map<PropertyDescriptor, String>
+        task.getSupportedPropertyDescriptors().each { PropertyDescriptor descriptor ->
+            properties.put(descriptor, descriptor.getDefaultValue())
+        }
+
+        // Mock the ConfigurationContext for setup(...)
+        def configurationContext = mock(ConfigurationContext)
+        when(configurationContext.getProperty(scriptingComponent.getScriptingComponentHelper().SCRIPT_ENGINE))
+                .thenReturn(new MockPropertyValue('python'))
+        when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_FILE))
+                .thenReturn(new MockPropertyValue('target/test/resources/jython/test_log_vm_stats.py'))
+        when(configurationContext.getProperty(ScriptingComponentUtils.SCRIPT_BODY))
+                .thenReturn(new MockPropertyValue(null))
+        when(configurationContext.getProperty(ScriptingComponentUtils.MODULES))
+                .thenReturn(new MockPropertyValue(null))
+
+        // Set up ReportingContext
+        def context = mock(ReportingContext)
+        when(context.getStateManager()).thenReturn(new MockStateManager(task))
+        doAnswer({ invocation ->
+            PropertyDescriptor descriptor = invocation.getArgumentAt(0, PropertyDescriptor)
+            return new MockPropertyValue(properties[descriptor])
+        } as Answer<PropertyValue>
+        ).when(context).getProperty(any(PropertyDescriptor))
+
+
+        def logger = mock(ComponentLog)
+        def initContext = mock(ReportingInitializationContext)
+        when(initContext.getIdentifier()).thenReturn(UUID.randomUUID().toString())
+        when(initContext.getLogger()).thenReturn(logger)
+
+        task.initialize initContext
+        task.setup configurationContext
+        task.onTrigger context
+        def se = task.scriptEngine
+        // This script should store a variable called x with a map of stats to values
+        assertTrue se.x?.uptime >= 0
+        task.offerScriptEngine(se)
+
+    }
+
     class MockScriptedReportingTask extends ScriptedReportingTask implements AccessibleScriptingComponentHelper {
         def getScriptEngine() {
             return scriptingComponentHelper.engineQ.poll()
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py
new file mode 100644
index 0000000..219dc44
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/test_log_vm_stats.py
@@ -0,0 +1,29 @@
+#! /usr/bin/python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+x = {
+    'uptime': vmMetrics.uptime(),
+    'heapUsed': vmMetrics.heapUsed(None),
+    'heapUsage': vmMetrics.heapUsage(),
+    'nonHeapUsage': vmMetrics.nonHeapUsage(),
+    'threadCount': vmMetrics.threadCount(),
+    'daemonThreadCount': vmMetrics.daemonThreadCount(),
+    'fileDescriptorUsage': vmMetrics.fileDescriptorUsage()
+}