nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From joew...@apache.org
Subject [2/3] nifi git commit: NIFI-210: This closes #185. Add ExecuteScript and InvokeScriptedProcessor
Date Tue, 02 Feb 2016 02:28:39 GMT
http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/GroovyScriptEngineConfigurator.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/GroovyScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/GroovyScriptEngineConfigurator.java
new file mode 100644
index 0000000..27b0fdc
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/GroovyScriptEngineConfigurator.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script.impl;
+
+import org.apache.nifi.processors.script.ScriptEngineConfigurator;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+public class GroovyScriptEngineConfigurator implements ScriptEngineConfigurator {
+
+    private static final String PRELOADS =
+            "import org.apache.nifi.components.*\n"
+                    + "import org.apache.nifi.flowfile.FlowFile\n"
+                    + "import org.apache.nifi.processor.*\n"
+                    + "import org.apache.nifi.processor.exception.*\n"
+                    + "import org.apache.nifi.processor.io.*\n"
+                    + "import org.apache.nifi.processor.util.*\n"
+                    + "import org.apache.nifi.processors.script.*\n"
+                    + "import org.apache.nifi.logging.ProcessorLog\n";
+
+
+    private ScriptEngine scriptEngine;
+
+    @Override
+    public String getScriptEngineName() {
+        return "Groovy";
+    }
+
+    @Override
+    public Object init(ScriptEngine engine, String modulePath) throws ScriptException {
+        scriptEngine = engine;
+        return scriptEngine;
+    }
+
+    @Override
+    public Object eval(ScriptEngine engine, String scriptBody, String modulePath) throws ScriptException {
+        scriptEngine = engine;
+        return engine.eval(PRELOADS + scriptBody);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/JythonScriptEngineConfigurator.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/JythonScriptEngineConfigurator.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/JythonScriptEngineConfigurator.java
new file mode 100644
index 0000000..d5c8bba
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/processors/script/impl/JythonScriptEngineConfigurator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script.impl;
+
+import org.apache.nifi.processors.script.ScriptEngineConfigurator;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+/**
+ * A helper class to configure the Jython engine with any specific requirements
+ */
+public class JythonScriptEngineConfigurator implements ScriptEngineConfigurator {
+
+    public String getScriptEngineName() {
+        return "python";
+    }
+
+    @Override
+    public Object init(ScriptEngine engine, String modulePath) throws ScriptException {
+        return null;
+    }
+
+    public Object eval(ScriptEngine engine, String scriptBody, String modulePath) throws ScriptException {
+        Object returnValue = null;
+        if (engine != null) {
+            // Need to import the module path inside the engine, in order to pick up
+            // other Python/Jython modules
+            engine.eval("import sys");
+            if (modulePath != null) {
+                engine.eval("sys.path.append('" + modulePath + "')");
+            }
+            returnValue = engine.eval(scriptBody);
+        }
+        return returnValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
new file mode 100644
index 0000000..f0c091c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processor.Processor
@@ -0,0 +1,16 @@
+# 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.
+org.apache.nifi.processors.script.InvokeScriptedProcessor
+org.apache.nifi.processors.script.ExecuteScript

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processors.script.ScriptEngineConfigurator
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processors.script.ScriptEngineConfigurator b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processors.script.ScriptEngineConfigurator
new file mode 100644
index 0000000..a7ae5a7
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/resources/META-INF/services/org.apache.nifi.processors.script.ScriptEngineConfigurator
@@ -0,0 +1,17 @@
+# 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.
+
+org.apache.nifi.processors.script.impl.JythonScriptEngineConfigurator
+org.apache.nifi.processors.script.impl.GroovyScriptEngineConfigurator

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/BaseScriptTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/BaseScriptTest.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/BaseScriptTest.java
new file mode 100644
index 0000000..eb83b48
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/BaseScriptTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.BeforeClass;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * An abstract class with common methods, variables, etc. used by scripting processor unit tests
+ */
+public abstract class BaseScriptTest {
+
+    public final String TEST_RESOURCE_LOCATION = "target/test/resources/";
+
+
+    protected TestRunner runner;
+
+    /**
+     * Copies all scripts to the target directory because when they are compiled they can leave unwanted .class files.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @BeforeClass
+    public static void setupBeforeClass() throws Exception {
+        FileUtils.copyDirectory(new File("src/test/resources"), new File("target/test/resources"));
+    }
+
+    public void setupExecuteScript() throws Exception {
+        final ExecuteScript executeScript = new ExecuteScript();
+        // Need to do something to initialize the properties, like retrieve the list of properties
+        assertNotNull(executeScript.getSupportedPropertyDescriptors());
+        runner = TestRunners.newTestRunner(executeScript);
+    }
+
+    public void setupInvokeScriptProcessor() throws Exception {
+        final InvokeScriptedProcessor invokeScriptedProcessor = new InvokeScriptedProcessor();
+        // Need to do something to initialize the properties, like retrieve the list of properties
+        assertNotNull(invokeScriptedProcessor.getSupportedPropertyDescriptors());
+        runner = TestRunners.newTestRunner(invokeScriptedProcessor);
+    }
+
+    public String getFileContentsAsString(String path) {
+        try {
+            return new String(Files.readAllBytes(Paths.get(path)));
+        } catch (IOException ioe) {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteGroovy.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteGroovy.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteGroovy.java
new file mode 100644
index 0000000..133a461
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteGroovy.java
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.util.MockFlowFile;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class TestExecuteGroovy extends BaseScriptTest {
+
+    public final String TEST_CSV_DATA = "gender,title,first,last\n"
+            + "female,miss,marlene,shaw\n"
+            + "male,mr,todd,graham";
+
+    @Before
+    public void setup() throws Exception {
+        super.setupExecuteScript();
+    }
+
+    /**
+     * Tests a script file that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptFile() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION + "groovy/test_onTrigger.groovy");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/groovy");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script file that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testNoIncomingFlowFile() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION + "groovy/test_onTrigger.groovy");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/groovy");
+
+        runner.assertValid();
+        runner.run();
+
+        runner.assertTransferCount(ExecuteScript.REL_SUCCESS, 0);
+        runner.assertTransferCount(ExecuteScript.REL_FAILURE, 0);
+    }
+
+    /**
+     * Tests a script file that creates and transfers a new flow file.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testInvalidConfiguration() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION);
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, "body");
+
+        runner.assertNotValid();
+    }
+
+    /**
+     * Tests a script file that creates and transfers a new flow file.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testCreateNewFlowFileWithScriptFile() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION + "groovy/test_onTrigger_newFlowFile.groovy");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/groovy");
+
+        runner.assertValid();
+        runner.enqueue(TEST_CSV_DATA.getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        // The script removes the original file and transfers only the new one
+        assertEquals(1, runner.getRemovedCount());
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("filename", "split_cols.txt");
+    }
+
+    /**
+     * Tests a script file that creates and transfers a new flow file.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testCreateNewFlowFileWithNoInputFile() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY,
+                getFileContentsAsString(TEST_RESOURCE_LOCATION + "groovy/testCreateNewFlowFileWithNoInputFile.groovy")
+        );
+
+        runner.assertValid();
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("filename", "newfile");
+    }
+
+    /**
+     * Tests a script file that creates and transfers a new flow file.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testDynamicProperties() throws Exception {
+        runner.setValidateExpressionUsage(true);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION + "groovy/test_dynamicProperties.groovy");
+        runner.setProperty("myProp", "${myAttr}");
+
+        runner.assertValid();
+        runner.enqueue(TEST_CSV_DATA.getBytes(StandardCharsets.UTF_8),
+                new HashMap<String, String>(1) {{
+                    put("myAttr", "testValue");
+                }});
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "testValue");
+    }
+
+    /**
+     * Tests a script file that changes the content of the incoming flowfile.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testChangeFlowFileWithScriptFile() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, "target/test/resources/groovy/test_onTrigger_changeContent.groovy");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/groovy");
+
+        runner.assertValid();
+        runner.enqueue(TEST_CSV_DATA.getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        MockFlowFile resultFile = result.get(0);
+        resultFile.assertAttributeEquals("selected.columns", "first,last");
+        resultFile.assertContentEquals("Marlene Shaw\nTodd Graham\n");
+    }
+
+
+    /**
+     * Tests a script that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody.groovy")
+        );
+        runner.setProperty(ExecuteScript.MODULES, TEST_RESOURCE_LOCATION + "groovy");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script that has provides the body of an onTrigger() function, where the ExecuteScript processor does
+     * not specify a modules path
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules.groovy")
+        );
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script that does not transfer or remove the original flow file, thereby causing an error during commit.
+     *
+     * @throws Exception Any error encountered while testing. Expecting
+     */
+    @Test(expected = AssertionError.class)
+    public void testScriptNoTransfer() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testScriptNoTransfer.groovy")
+        );
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+    }
+
+    /**
+     * Tests a script that uses a dynamic property to set a FlowFile attribute.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileCustomAttribute() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testReadFlowFileContentAndStoreInFlowFileCustomAttribute.groovy")
+        );
+        runner.setProperty("testprop", "test content");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script that throws an Exception within. The expected result is that the FlowFile will be routed to
+     * failure
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test(expected = AssertionError.class)
+    public void testScriptException() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, "throw new Exception()");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJRuby.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJRuby.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJRuby.java
new file mode 100644
index 0000000..90e8f85
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJRuby.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+
+public class TestExecuteJRuby extends BaseScriptTest {
+
+    @Before
+    public void setup() throws Exception {
+        super.setupExecuteScript();
+    }
+
+
+    /**
+     * Tests a script that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new ExecuteScript());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "ruby");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, "target/test/resources/jruby/test_onTrigger.rb");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/jruby");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship("success");
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJavascript.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJavascript.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJavascript.java
new file mode 100644
index 0000000..3f50348
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJavascript.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+
+public class TestExecuteJavascript extends BaseScriptTest {
+
+    @Before
+    public void setup() throws Exception {
+        super.setupExecuteScript();
+    }
+
+    /**
+     * Tests a script that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new ExecuteScript());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "ECMAScript");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, "target/test/resources/javascript/test_onTrigger.js");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/javascript");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship("success");
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJython.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJython.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJython.java
new file mode 100644
index 0000000..e1938e3
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteJython.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.util.MockFlowFile;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * Created by mburgess on 1/25/16.
+ */
+public class TestExecuteJython extends BaseScriptTest {
+
+    @Before
+    public void setup() throws Exception {
+        super.setupExecuteScript();
+    }
+
+    /**
+     * Tests a Jython script that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "python");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY,
+                "from org.apache.nifi.processors.script import ExecuteScript\n"
+                        + "flowFile = session.get()\n"
+                        + "flowFile = session.putAttribute(flowFile, \"from-content\", \"test content\")\n"
+                        + "session.transfer(flowFile, ExecuteScript.REL_SUCCESS)");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script that does not transfer or remove the original flow file, thereby causing an error during commit.
+     *
+     * @throws Exception Any error encountered while testing. Expecting
+     */
+    @Test(expected = AssertionError.class)
+    public void testScriptNoTransfer() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "python");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY,
+                "flowFile = session.putAttribute(flowFile, \"from-content\", \"test content\")\n");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteLua.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteLua.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteLua.java
new file mode 100644
index 0000000..e0415de
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestExecuteLua.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+
+public class TestExecuteLua extends BaseScriptTest {
+
+    @Before
+    public void setup() throws Exception {
+        super.setupExecuteScript();
+    }
+
+
+    /**
+     * Tests a script that has provides the body of an onTrigger() function.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new ExecuteScript());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "lua");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, "target/test/resources/lua/test_onTrigger.lua");
+        runner.setProperty(ExecuteScript.MODULES, "target/test/resources/lua");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ExecuteScript.REL_SUCCESS, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(ExecuteScript.REL_SUCCESS);
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeGroovy.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeGroovy.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeGroovy.java
new file mode 100644
index 0000000..349b25d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeGroovy.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.MockProcessContext;
+import org.apache.nifi.util.MockProcessorInitializationContext;
+import org.apache.nifi.util.MockValidationContext;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class TestInvokeGroovy extends BaseScriptTest {
+
+    @Before
+    public void setup() throws Exception {
+        super.setupInvokeScriptProcessor();
+    }
+
+    /**
+     * Tests a script that has a Groovy Processor that that reads the first line of text from the flowfiles content and stores the value in an attribute of the outgoing flowfile.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/groovy/test_reader.groovy");
+        runner.setProperty(InvokeScriptedProcessor.MODULES, "target/test/resources/groovy");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship("success");
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests a script that has a Groovy Processor that that reads the first line of text from the flowfiles content and
+     * stores the value in an attribute of the outgoing flowfile.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testScriptDefinedAttribute() throws Exception {
+        InvokeScriptedProcessor processor = new InvokeScriptedProcessor();
+        MockProcessContext context = new MockProcessContext(processor);
+        MockProcessorInitializationContext initContext = new MockProcessorInitializationContext(processor, context);
+
+        processor.initialize(initContext);
+
+        context.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "Groovy");
+        context.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/groovy/test_reader.groovy");
+        context.setProperty(InvokeScriptedProcessor.MODULES, "target/test/resources/groovy");
+        processor.customValidate(new MockValidationContext(context));
+        processor.setup(context);
+
+        List<PropertyDescriptor> descriptors = processor.getSupportedPropertyDescriptors();
+        assertNotNull(descriptors);
+        assertTrue(descriptors.size() > 0);
+        boolean found = false;
+        for (PropertyDescriptor descriptor : descriptors) {
+            if (descriptor.getName().equals("test-attribute")) {
+                found = true;
+                break;
+            }
+        }
+        assertTrue(found);
+    }
+
+    /**
+     * Tests a script that has a Groovy Processor that that reads the first line of text from the flowfiles content and
+     * stores the value in an attribute of the outgoing flowfile.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testScriptDefinedRelationship() throws Exception {
+        InvokeScriptedProcessor processor = new InvokeScriptedProcessor();
+        MockProcessContext context = new MockProcessContext(processor);
+        MockProcessorInitializationContext initContext = new MockProcessorInitializationContext(processor, context);
+
+        processor.initialize(initContext);
+
+        context.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "Groovy");
+        context.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/groovy/test_reader.groovy");
+        processor.customValidate(new MockValidationContext(context));
+        processor.setup(context);
+
+        Set<Relationship> relationships = processor.getRelationships();
+        assertNotNull(relationships);
+        assertTrue(relationships.size() > 0);
+        boolean found = false;
+        for (Relationship relationship : relationships) {
+            if (relationship.getName().equals("test")) {
+                found = true;
+                break;
+            }
+        }
+        assertTrue(found);
+    }
+
+    /**
+     * Tests a script that throws a ProcessException within. The expected result is that the exception will be
+     * propagated
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test(expected = AssertionError.class)
+    public void testInvokeScriptCausesException() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testInvokeScriptCausesException.groovy")
+        );
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+    }
+
+    /**
+     * Tests a script that routes the FlowFile to failure.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testScriptRoutesToFailure() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "Groovy");
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, getFileContentsAsString(
+                TEST_RESOURCE_LOCATION + "groovy/testScriptRoutesToFailure.groovy")
+        );
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(InvokeScriptedProcessor.REL_FAILURE, 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship(InvokeScriptedProcessor.REL_FAILURE);
+        assertFalse(result.isEmpty());
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeJython.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeJython.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeJython.java
new file mode 100755
index 0000000..b45c322
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/java/org/apache/nifi/processors/script/TestInvokeJython.java
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+package org.apache.nifi.processors.script;
+
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.MockProcessContext;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestInvokeJython extends BaseScriptTest {
+
+    /**
+     * Copies all scripts to the target directory because when they are compiled they can leave unwanted .class files.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Before
+    public void setup() throws Exception {
+        super.setupInvokeScriptProcessor();
+    }
+
+    /**
+     * Tests a script that has a Jython processor that is always invalid.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testAlwaysInvalid() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "python");
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/jython/test_invalid.py");
+
+        final Collection<ValidationResult> results = ((MockProcessContext) runner.getProcessContext()).validate();
+        Assert.assertEquals(1L, results.size());
+        Assert.assertEquals("Never valid.", results.iterator().next().getExplanation());
+    }
+
+    /**
+     * Test a script that has a Jython processor that reads a value from a processor property and another from a flowfile attribute then stores both in the attributes of the flowfile being routed.
+     * <p>
+     * This may seem contrived but it verifies that the Jython processors properties are being considered and are able to be set and validated. It verifies the processor is able to access the property
+     * values and flowfile attribute values during onTrigger. Lastly, it verifies the processor is able to route the flowfile to a relationship it specified.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testUpdateAttributeFromProcessorPropertyAndFlowFileAttribute() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "python");
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/jython/test_update_attribute.py");
+        runner.setProperty("for-attributes", "value-1");
+
+        final Map<String, String> attributes = new HashMap<>();
+        attributes.put("for-attributes", "value-2");
+
+        runner.assertValid();
+        runner.enqueue(new byte[0], attributes);
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship("success");
+
+        // verify reading a property value
+        result.get(0).assertAttributeEquals("from-property", "value-1");
+
+        // verify reading an attribute value
+        result.get(0).assertAttributeEquals("from-attribute", "value-2");
+    }
+
+    /**
+     * Tests a script that has a Jython Processor that that reads the first line of text from the flowfiles content and stores the value in an attribute of the outgoing flowfile.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testReadFlowFileContentAndStoreInFlowFileAttribute() throws Exception {
+        final TestRunner runner = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "python");
+        runner.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/jython/test_reader.py");
+        runner.setProperty(InvokeScriptedProcessor.MODULES, "target/test/resources/jython");
+
+        runner.assertValid();
+        runner.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> result = runner.getFlowFilesForRelationship("success");
+        result.get(0).assertAttributeEquals("from-content", "test content");
+    }
+
+    /**
+     * Tests compression and decompression using two different InvokeScriptedProcessor processor instances. A string is compressed and decompressed and compared.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testCompressor() throws Exception {
+        final TestRunner one = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        one.setValidateExpressionUsage(false);
+        one.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "python");
+        one.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/jython/test_compress.py");
+        one.setProperty(InvokeScriptedProcessor.MODULES, "target/test/resources/jython");
+        one.setProperty("mode", "compress");
+
+        one.assertValid();
+        one.enqueue("test content".getBytes(StandardCharsets.UTF_8));
+        one.run();
+
+        one.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> oneResult = one.getFlowFilesForRelationship("success");
+
+        final TestRunner two = TestRunners.newTestRunner(new InvokeScriptedProcessor());
+        two.setValidateExpressionUsage(false);
+        two.setProperty(InvokeScriptedProcessor.SCRIPT_ENGINE, "python");
+        two.setProperty(InvokeScriptedProcessor.MODULES, "target/test/resources/jython");
+        two.setProperty(InvokeScriptedProcessor.SCRIPT_FILE, "target/test/resources/jython/test_compress.py");
+        two.setProperty("mode", "decompress");
+
+        two.assertValid();
+        two.enqueue(oneResult.get(0));
+        two.run();
+
+        two.assertAllFlowFilesTransferred("success", 1);
+        final List<MockFlowFile> twoResult = two.getFlowFilesForRelationship("success");
+        Assert.assertEquals("test content", new String(twoResult.get(0).toByteArray(), StandardCharsets.UTF_8));
+    }
+
+    /**
+     * Tests a script file that creates and transfers a new flow file.
+     *
+     * @throws Exception Any error encountered while testing
+     */
+    @Test
+    public void testInvalidConfiguration() throws Exception {
+        runner.setValidateExpressionUsage(false);
+        runner.setProperty(ExecuteScript.SCRIPT_ENGINE, "python");
+        runner.setProperty(ExecuteScript.SCRIPT_FILE, TEST_RESOURCE_LOCATION);
+        runner.setProperty(ExecuteScript.SCRIPT_BODY, "body");
+
+        runner.assertNotValid();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testCreateNewFlowFileWithNoInputFile.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testCreateNewFlowFileWithNoInputFile.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testCreateNewFlowFileWithNoInputFile.groovy
new file mode 100644
index 0000000..e5344fa
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testCreateNewFlowFileWithNoInputFile.groovy
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+FlowFile flowFile = session.create()
+flowFile = session.putAttribute(flowFile, 'from-content', 'test content')
+flowFile = session.putAttribute(flowFile, 'filename', 'newfile')
+session.transfer(flowFile, REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testInvokeScriptCausesException.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testInvokeScriptCausesException.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testInvokeScriptCausesException.groovy
new file mode 100644
index 0000000..1b2922c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testInvokeScriptCausesException.groovy
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+class testInvokeScriptCausesException implements Processor {
+
+
+    def ProcessorLog log
+
+    @Override
+    void initialize(ProcessorInitializationContext context) {
+    }
+
+    @Override
+    Set<Relationship> getRelationships() {
+        return [] as Set
+    }
+
+    @Override
+    void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
+        throw new ProcessException();
+    }
+
+    @Override
+    Collection<ValidationResult> validate(ValidationContext context) {
+        return null
+    }
+
+    @Override
+    PropertyDescriptor getPropertyDescriptor(String name) {
+        return null
+    }
+
+    @Override
+    void onPropertyModified(PropertyDescriptor descriptor, String oldValue, String newValue) {
+
+    }
+
+    @Override
+    List<PropertyDescriptor> getPropertyDescriptors() {
+        return null
+    }
+
+    @Override
+    String getIdentifier() {
+        return null
+    }
+}
+
+processor = new testInvokeScriptCausesException()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody.groovy
new file mode 100644
index 0000000..efc2087
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBody.groovy
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+FlowFile flowFile = session.get()
+
+if (flowFile == null) {
+  return;
+}
+flowFile = session.putAttribute(flowFile, 'from-content', 'test content')
+session.transfer(flowFile, REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules.groovy
new file mode 100644
index 0000000..d9b476d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileAttributeWithScriptBodyNoModules.groovy
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+FlowFile flowFile = session.get()
+if (flowFile == null) return
+flowFile = session.putAttribute(flowFile, 'from-content', 'test content')
+session.transfer(flowFile, REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileCustomAttribute.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileCustomAttribute.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileCustomAttribute.groovy
new file mode 100644
index 0000000..87ef750
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testReadFlowFileContentAndStoreInFlowFileCustomAttribute.groovy
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+FlowFile flowFile = session.get()
+if (flowFile == null) return
+flowFile = session.putAttribute(flowFile, 'from-content', "${testprop}")
+session.transfer(flowFile, REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptNoTransfer.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptNoTransfer.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptNoTransfer.groovy
new file mode 100644
index 0000000..c428e4a
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptNoTransfer.groovy
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+FlowFile flowFile = session.get()
+if (flowFile == null) return
+flowFile = session.putAttribute(flowFile, "from-content", "test content")
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptRoutesToFailure.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptRoutesToFailure.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptRoutesToFailure.groovy
new file mode 100644
index 0000000..47074a2
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/testScriptRoutesToFailure.groovy
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+class testScriptRoutesToFailure implements Processor {
+
+  def ProcessorLog log
+
+  @Override
+  void initialize(ProcessorInitializationContext context) {
+  }
+
+  @Override
+  Set<Relationship> getRelationships() {
+      return [] as Set
+  }
+
+  @Override
+  void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
+      def session = sessionFactory.createSession()
+      def flowFile = session.get()
+      if(!flowFile) return
+      session.transfer(flowFile, InvokeScriptedProcessor.REL_FAILURE)
+  }
+
+  @Override
+  Collection<ValidationResult> validate(ValidationContext context) {
+      return null
+  }
+
+  @Override
+  PropertyDescriptor getPropertyDescriptor(String name) {
+      return null
+  }
+
+  @Override
+  void onPropertyModified(PropertyDescriptor descriptor, String oldValue, String newValue) {
+
+  }
+
+  @Override
+  List<PropertyDescriptor> getPropertyDescriptors() {
+      return null
+  }
+
+  @Override
+  String getIdentifier() {
+      return null
+  }
+}
+
+processor = new testScriptRoutesToFailure()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_dynamicProperties.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_dynamicProperties.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_dynamicProperties.groovy
new file mode 100644
index 0000000..48f1c2b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_dynamicProperties.groovy
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+def flowFile = session.get();
+if (flowFile == null) {
+    return;
+}
+flowFile = session.putAttribute(flowFile, "from-content", myProp.evaluateAttributeExpressions(flowFile).getValue())
+session.transfer(flowFile, REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger.groovy
new file mode 100644
index 0000000..e78307d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger.groovy
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+def flowFile = session.get();
+if (flowFile == null) {
+    context?.yield();
+}
+else {
+    flowFile = session.putAttribute(flowFile, "from-content", "test content")
+    session.transfer(flowFile, REL_SUCCESS)
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_changeContent.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_changeContent.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_changeContent.groovy
new file mode 100644
index 0000000..3a2a6bb
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_changeContent.groovy
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+def flowFile = session.get();
+if (flowFile == null) {
+    return;
+}
+def selectedColumns = ''
+
+flowFile = session.write(flowFile,
+        { inputStream, outputStream ->
+            String line
+
+            final BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, 'UTF-8'))
+            line = inReader.readLine()
+            String[] header = line?.split(',')
+            selectedColumns = "${header[2]},${header[3]}"
+
+            while (line = inReader.readLine()) {
+                String[] cols = line.split(',')
+                // Select/project cols
+                outputStream.write("${cols[2].capitalize()} ${cols[3].capitalize()}\n".getBytes('UTF-8'))
+            }
+        } as StreamCallback)
+
+flowFile = session?.putAttribute(flowFile, "selected.columns", selectedColumns)
+flowFile = session?.putAttribute(flowFile, "filename", "split_cols.txt")
+session.transfer(flowFile, ExecuteScript.REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_newFlowFile.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_newFlowFile.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_newFlowFile.groovy
new file mode 100644
index 0000000..fcec6a9
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_onTrigger_newFlowFile.groovy
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+def flowFile = session.get();
+if (flowFile == null) {
+    return;
+}
+FlowFile newFlowFile
+
+session.read(flowFile,
+        { inputStream ->
+            String line
+
+            final BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, 'UTF-8'))
+            line = inReader.readLine()
+            String[] header = line?.split(',')
+            newFlowFile = session?.create(flowFile)
+            newFlowFile = session?.putAttribute(newFlowFile, "selected.columns", "${header[1]},${header[2]}")
+            newFlowFile = session?.putAttribute(newFlowFile, "filename", "split_cols.txt")
+
+            newFlowFile = session.write(newFlowFile,
+                    { outStream ->
+                        while (line = inReader.readLine()) {
+                            String[] cols = line.split(',')
+                            // Select/project cols
+                            outStream.write("${cols[3].capitalize()}, ${cols[2].capitalize()}\n".getBytes('UTF-8'))
+                        }
+                    } as OutputStreamCallback)
+        } as InputStreamCallback)
+
+// transfer
+session.transfer(newFlowFile, ExecuteScript.REL_SUCCESS)
+session.remove((FlowFile) flowFile)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_reader.groovy
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_reader.groovy b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_reader.groovy
new file mode 100644
index 0000000..9778f87
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/groovy/test_reader.groovy
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+class GroovyProcessor implements Processor {
+
+    def REL_TEST = new Relationship.Builder()
+            .name("test")
+            .description("A test relationship")
+            .build();
+
+    def descriptor = new PropertyDescriptor.Builder()
+            .name("test-attribute").addValidator(StandardValidators.NON_EMPTY_VALIDATOR).build()
+
+    @Override
+    void initialize(ProcessorInitializationContext context) {
+
+    }
+
+    @Override
+    Set<Relationship> getRelationships() {
+        return [REL_TEST] as Set
+    }
+
+    @Override
+    void onTrigger(ProcessContext context, ProcessSessionFactory sessionFactory) throws ProcessException {
+        def session = sessionFactory.createSession()
+        def flowFile = session.get();
+        if (flowFile == null) {
+            return;
+        }
+        flowFile = session.putAttribute(flowFile, "from-content", "test content")
+        // transfer
+        session.transfer(flowFile, InvokeScriptedProcessor.REL_SUCCESS)
+        session.commit()
+    }
+
+    @Override
+    Collection<ValidationResult> validate(ValidationContext context) {
+        return null
+    }
+
+    @Override
+    PropertyDescriptor getPropertyDescriptor(String name) {
+        return (name?.equals("test-attribute") ? descriptor : null)
+    }
+
+    @Override
+    void onPropertyModified(PropertyDescriptor descriptor, String oldValue, String newValue) {
+
+    }
+
+    @Override
+    List<PropertyDescriptor> getPropertyDescriptors() {
+
+        return [descriptor] as List
+    }
+
+    @Override
+    String getIdentifier() {
+        return null
+    }
+}
+
+processor = new GroovyProcessor();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/javascript/test_onTrigger.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/javascript/test_onTrigger.js b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/javascript/test_onTrigger.js
new file mode 100644
index 0000000..b0418ca
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/javascript/test_onTrigger.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+flowFile = session.get();
+if (flowFile != null) {
+    flowFile = session.putAttribute(flowFile, "from-content", "test content")
+    session.transfer(flowFile, REL_SUCCESS)
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jruby/test_onTrigger.rb
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jruby/test_onTrigger.rb b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jruby/test_onTrigger.rb
new file mode 100644
index 0000000..d8a2b7b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jruby/test_onTrigger.rb
@@ -0,0 +1,22 @@
+# 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.
+
+java_import Java::org.apache.nifi.processors.script.ExecuteScript
+flowFile = session.get()
+if flowFile.nil?
+    return
+end
+flowFile = session.putAttribute(flowFile, "from-content", "test content")
+session.transfer(flowFile, ExecuteScript::REL_SUCCESS)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/77ab5d36/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/callbacks/__init__.py
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/callbacks/__init__.py b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/callbacks/__init__.py
new file mode 100755
index 0000000..cdfa6e1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/test/resources/jython/callbacks/__init__.py
@@ -0,0 +1,23 @@
+#! /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.
+#
+
+from read_first_line import ReadFirstLine
+from compress import Compress
+from decompress import Decompress
\ No newline at end of file


Mime
View raw message