INT-3751: Fix Python Scripting
JIRA: https://jira.spring.io/browse/INT-3751 Result was null when `executeScript()` was invoked with non-null variables. When variable are provided, the result variable is stored in the provided bindings.
This commit is contained in:
committed by
Artem Bilan
parent
bd62b4191d
commit
c51299b1b2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
@@ -15,6 +15,7 @@ package org.springframework.integration.scripting.jsr223;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.SimpleBindings;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
* @author David Turanski
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*/
|
||||
abstract class AbstractScriptExecutor implements ScriptExecutor {
|
||||
@@ -60,10 +62,12 @@ abstract class AbstractScriptExecutor implements ScriptExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeScript(ScriptSource scriptSource) {
|
||||
return this.executeScript(scriptSource, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object executeScript(ScriptSource scriptSource, Map<String, Object> variables) {
|
||||
Object result = null;
|
||||
|
||||
@@ -74,14 +78,16 @@ abstract class AbstractScriptExecutor implements ScriptExecutor {
|
||||
logger.debug("executing script: " + script);
|
||||
}
|
||||
|
||||
if (variables != null) {
|
||||
result = scriptEngine.eval(script, new SimpleBindings(variables));
|
||||
Bindings bindings = null;
|
||||
if (variables != null && variables.size() > 0) {
|
||||
bindings = new SimpleBindings(variables);
|
||||
result = scriptEngine.eval(script, bindings);
|
||||
}
|
||||
else {
|
||||
result = scriptEngine.eval(script);
|
||||
}
|
||||
|
||||
result = postProcess(result, scriptEngine, script);
|
||||
result = postProcess(result, scriptEngine, script, bindings);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("script executed in " + (new Date().getTime() - start.getTime()) + " ms");
|
||||
@@ -97,12 +103,13 @@ abstract class AbstractScriptExecutor implements ScriptExecutor {
|
||||
|
||||
/**
|
||||
* Subclasses may implement this to provide any special handling required
|
||||
* @param result
|
||||
* @param scriptEngine
|
||||
* @param script
|
||||
* @param result the result.
|
||||
* @param scriptEngine the engine.
|
||||
* @param script the script.
|
||||
* @param bindings the bindings.
|
||||
* @return modified result
|
||||
*/
|
||||
protected abstract Object postProcess(Object result, ScriptEngine scriptEngine, String script);
|
||||
protected abstract Object postProcess(Object result, ScriptEngine scriptEngine, String script, Bindings bindings);
|
||||
|
||||
private static String invlalidLanguageMessage(String language) {
|
||||
return new StringBuilder().append(ScriptEngineManager.class.getName())
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.scripting.jsr223;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
import org.springframework.integration.scripting.ScriptExecutor;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link ScriptExecutor}
|
||||
*
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*/
|
||||
class DefaultScriptExecutor extends AbstractScriptExecutor {
|
||||
@@ -32,16 +34,8 @@ import org.springframework.integration.scripting.ScriptExecutor;
|
||||
super(language);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.integration.scripting.jsr223.AbstractScriptExecutor
|
||||
* #postProcess(java.lang.Object, javax.script.ScriptEngine,
|
||||
* java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected Object postProcess(Object result, ScriptEngine scriptEngine, String script) {
|
||||
protected Object postProcess(Object result, ScriptEngine scriptEngine, String script, Bindings bindings) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.scripting.jsr223;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
import org.springframework.integration.scripting.ScriptExecutor;
|
||||
@@ -19,11 +20,12 @@ import org.springframework.integration.scripting.ScriptExecutor;
|
||||
/**
|
||||
* A {@link ScriptExecutor} that implements special handling required for Python to emulate behavior similar to other JSR223 scripting languages.
|
||||
* <p>
|
||||
* Script evaluation using the Jython implementation results in a <code>null</code> return value for normal variable expressions such as
|
||||
* Script evaluation using the Jython implementation results in a <code>null</code> return value for normal variable expressions such as
|
||||
* <code>x=2</code>. As a work around, it is necessary to get the value of 'x' explicitly following the script evaluation. This class performs
|
||||
* simple parsing on the last line of the script to obtain the variable name, if any, and return its value.
|
||||
*
|
||||
* simple parsing on the last line of the script to obtain the variable name, if any, and return its value.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author Gary Russell
|
||||
* @since 2.1
|
||||
*
|
||||
*/
|
||||
@@ -32,22 +34,24 @@ import org.springframework.integration.scripting.ScriptExecutor;
|
||||
* @param language
|
||||
*/
|
||||
public PythonScriptExecutor() {
|
||||
super("python");
|
||||
super("python");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.scripting.jsr223.AbstractScriptExecutor#postProcess(java.lang.Object, javax.script.ScriptEngine, java.lang.String)
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Object postProcess(Object result, ScriptEngine scriptEngine, String script) {
|
||||
protected Object postProcess(Object result, ScriptEngine scriptEngine, String script, Bindings bindings) {
|
||||
Object newResult= result;
|
||||
if (newResult == null) {
|
||||
String returnVariableName = PythonVariableParser.parseReturnVariable(script);
|
||||
newResult = scriptEngine.get(returnVariableName);
|
||||
if (bindings != null) {
|
||||
newResult = bindings.get(returnVariableName);
|
||||
}
|
||||
if (newResult == null) {
|
||||
newResult = scriptEngine.get(returnVariableName);
|
||||
}
|
||||
}
|
||||
return newResult;
|
||||
}
|
||||
|
||||
|
||||
public static class PythonVariableParser {
|
||||
public static String parseReturnVariable(String script){
|
||||
String[] lines = script.trim().split("\n");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
@@ -13,6 +13,7 @@
|
||||
package org.springframework.integration.scripting.jsr223;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -20,6 +21,7 @@ import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.python.core.PyTuple;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.scripting.ScriptExecutor;
|
||||
import org.springframework.scripting.ScriptSource;
|
||||
@@ -28,6 +30,7 @@ import org.springframework.scripting.support.StaticScriptSource;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class PythonScriptExecutorTests {
|
||||
@@ -62,12 +65,26 @@ public class PythonScriptExecutorTests {
|
||||
@Test
|
||||
public void test3() {
|
||||
ScriptSource source =
|
||||
new ResourceScriptSource(new ClassPathResource("/org/springframework/integration/scripting/jsr223/test3.py"));
|
||||
new ResourceScriptSource(
|
||||
new ClassPathResource("/org/springframework/integration/scripting/jsr223/test3.py"));
|
||||
Object obj = executor.executeScript(source);
|
||||
PyTuple tuple = (PyTuple) obj;
|
||||
assertEquals(1, tuple.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3WithVariables() {
|
||||
ScriptSource source =
|
||||
new ResourceScriptSource(
|
||||
new ClassPathResource("/org/springframework/integration/scripting/jsr223/test3.py"));
|
||||
HashMap<String, Object> variables = new HashMap<String, Object>();
|
||||
variables.put("foo", "bar");
|
||||
Object obj = executor.executeScript(source, variables);
|
||||
PyTuple tuple = (PyTuple) obj;
|
||||
assertNotNull(tuple);
|
||||
assertEquals(1, tuple.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbeddedVariable() {
|
||||
Map<String,Object> variables = new HashMap<String,Object>();
|
||||
|
||||
Reference in New Issue
Block a user