INT-3166: Improve Groovy Processor Performance

Previously, there was a `synchronized` block in the `GroovyScriptExecutingMessageProcessor`
to achieve thread-safety around script variables.
In addition, the parsing and executing logic was delegated to `GroovyScriptFactory`, who, in turn,
has its own `synchronized` around script parsing.
This causes a bottleneck in a messaging architecture.

* Introduce `GroovyScriptExecutor implements ScriptExecutor`
to encapsulate Groovy parsing and executing logic
* synchronize via `ReentrantLock` only when script resource `isModified()`

JIRA: https://jira.springsource.org/browse/INT-3166

INT-3166: Fixes and Polishing

INT-3166: add synchronized double check

INT-3166: Remove `GroovyScriptExecutor`

Polishing tests and logic around exceptions

Fix up some white space issues in Groovy*Tests
This commit is contained in:
Artem Bilan
2013-10-07 13:04:27 +03:00
committed by Gary Russell
parent 9367928fd7
commit f0c4bdb756
13 changed files with 197 additions and 316 deletions

View File

@@ -13,9 +13,6 @@
package org.springframework.integration.groovy;
import groovy.lang.Binding;
import groovy.lang.GString;
import java.util.Map;
import org.springframework.integration.Message;
@@ -29,6 +26,9 @@ import org.springframework.scripting.support.StaticScriptSource;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import groovy.lang.Binding;
import groovy.lang.GString;
/**
* @author Dave Syer
* @author Mark Fisher
@@ -109,11 +109,11 @@ public class GroovyCommandMessageProcessor extends AbstractScriptExecutingMessag
customizerDecorator.setVariables(variables);
}
GroovyScriptFactory factory = new GroovyScriptFactory(this.getClass().getSimpleName(), customizerDecorator);
if (getBeanClassLoader() != null) {
factory.setBeanClassLoader(getBeanClassLoader());
if (this.beanClassLoader != null) {
factory.setBeanClassLoader(this.beanClassLoader);
}
if (getBeanFactory() != null) {
factory.setBeanFactory(getBeanFactory());
if (this.beanFactory != null) {
factory.setBeanFactory(this.beanFactory);
}
Object result = factory.getScriptedObject(scriptSource, null);
return (result instanceof GString) ? result.toString() : result;

View File

@@ -16,40 +16,52 @@
package org.springframework.integration.groovy;
import groovy.lang.GString;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.scripting.AbstractScriptExecutingMessageProcessor;
import org.springframework.integration.scripting.ScriptVariableGenerator;
import org.springframework.scripting.ScriptCompilationException;
import org.springframework.scripting.ScriptSource;
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
import org.springframework.scripting.groovy.GroovyScriptFactory;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ClassUtils;
import groovy.lang.Binding;
import groovy.lang.GString;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.lang.Script;
/**
* The {@link org.springframework.integration.handler.MessageProcessor} implementation
* to evaluate Groovy scripts.
*
* @author Dave Syer
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Stefan Reuter
* @author Artem Bilan
* @since 2.0
*/
public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecutingMessageProcessor<Object> implements InitializingBean {
public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecutingMessageProcessor<Object> {
private final GroovyScriptFactory scriptFactory;
private final VariableBindingGroovyObjectCustomizerDecorator customizerDecorator =
new VariableBindingGroovyObjectCustomizerDecorator();
private final VariableBindingGroovyObjectCustomizerDecorator
customizerDecorator = new VariableBindingGroovyObjectCustomizerDecorator();
private final Lock scriptLock = new ReentrantLock();
private volatile ScriptSource scriptSource;
private volatile GroovyClassLoader groovyClassLoader = new GroovyClassLoader(ClassUtils.getDefaultClassLoader());
private volatile Class<?> scriptClass;
/**
* Create a processor for the given {@link ScriptSource} that will use a
@@ -58,7 +70,6 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource) {
super();
this.scriptSource = scriptSource;
this.scriptFactory = new GroovyScriptFactory(this.getClass().getSimpleName(), this.customizerDecorator);
}
/**
@@ -68,9 +79,21 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource, ScriptVariableGenerator scriptVariableGenerator) {
super(scriptVariableGenerator);
this.scriptSource = scriptSource;
this.scriptFactory = new GroovyScriptFactory(this.getClass().getSimpleName(), this.customizerDecorator);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
super.setBeanClassLoader(classLoader);
this.groovyClassLoader = new GroovyClassLoader(classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
super.setBeanFactory(beanFactory);
if (beanFactory instanceof ConfigurableListableBeanFactory) {
((ConfigurableListableBeanFactory) beanFactory).ignoreDependencyType(MetaClass.class);
}
}
/**
* Sets a {@link GroovyObjectCustomizer} for this processor.
@@ -87,22 +110,58 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
@Override
protected Object executeScript(ScriptSource scriptSource, Map<String, Object> variables) throws Exception {
Assert.notNull(scriptSource, "scriptSource must not be null");
synchronized (this) {
if (!CollectionUtils.isEmpty(variables)) {
this.customizerDecorator.setVariables(variables);
this.parseScriptIfNecessary(scriptSource);
Object result = this.execute(variables);
return (result instanceof GString) ? result.toString() : result;
}
private void parseScriptIfNecessary(ScriptSource scriptSource) throws Exception {
if (this.scriptClass == null || scriptSource.isModified()) {
this.scriptLock.lockInterruptibly();
try {
// synchronized double check
if (this.scriptClass == null || scriptSource.isModified()) {
this.scriptClass = this.groovyClassLoader.parseClass(
scriptSource.getScriptAsString(), scriptSource.suggestedClassName());
}
}
finally {
this.scriptLock.unlock();
}
Object result = this.scriptFactory.getScriptedObject(scriptSource, null);
return (result instanceof GString) ? result.toString() : result;
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (getBeanClassLoader() != null) {
this.scriptFactory.setBeanClassLoader(getBeanClassLoader());
private Object execute(Map<String, Object> variables) throws ScriptCompilationException {
try {
GroovyObject goo = (GroovyObject) this.scriptClass.newInstance();
GroovyObjectCustomizer groovyObjectCustomizer = this.customizerDecorator;
if (variables != null) {
// Override empty Script.Binding with new one with 'variables'
groovyObjectCustomizer = new BindingOverwriteGroovyObjectCustomizerDecorator(new Binding(variables));
((VariableBindingGroovyObjectCustomizerDecorator) groovyObjectCustomizer).setCustomizer(this.customizerDecorator);
}
if (goo instanceof Script) {
// Allow metaclass and other customization.
groovyObjectCustomizer.customize(goo);
// A Groovy script, probably creating an instance: let's execute it.
return ((Script) goo).run();
}
else {
// An instance of the scripted class: let's return it as-is.
return goo;
}
}
if (getBeanFactory() != null) {
this.scriptFactory.setBeanFactory(getBeanFactory());
catch (InstantiationException ex) {
throw new ScriptCompilationException(
this.scriptSource, "Could not instantiate Groovy script class: " + this.scriptClass.getName(), ex);
}
catch (IllegalAccessException ex) {
throw new ScriptCompilationException(
this.scriptSource, "Could not access Groovy script constructor: " + this.scriptClass.getName(), ex);
}
}
}

View File

@@ -1,213 +0,0 @@
/*
* Copyright 2002-2010 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.groovy;
import static org.junit.Assert.assertEquals;
import groovy.lang.GroovyObject;
import groovy.lang.Script;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
import org.springframework.scripting.groovy.GroovyScriptFactory;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.util.Assert;
/**
* @author Dave Syer
*/
public class GroovyExpressionTests {
private static Log logger = LogFactory.getLog(GroovyExpressionTests.class);
@Before
public void setLogLevel() {
LogManager.getLogger(getClass()).setLevel(Level.DEBUG);
}
@After
public void resetLogLevel() {
LogManager.getLogger(getClass()).setLevel(Level.INFO);
}
@Test
public void testScriptFactoryCustomizer() throws Exception {
Customizer customizer = new Customizer(Collections.singletonMap("name", (Object) "foo"));
GroovyScriptFactory factory = new GroovyScriptFactory("Groovy Script", customizer);
ResourceScriptSource scriptSource = new ResourceScriptSource(new NamedByteArrayResource("\"name=${name}\"".getBytes(), "InlineScript"));
Object scriptedObject = factory.getScriptedObject(scriptSource, null);
assertEquals("name=foo", scriptedObject.toString());
customizer.setMap(Collections.singletonMap("name", (Object) "bar"));
scriptedObject = factory.getScriptedObject(scriptSource, null);
assertEquals("name=bar", scriptedObject.toString());
}
@Test
public void testScriptFactoryCustomizerThreadSafety() throws Exception {
final Customizer customizer = new Customizer(Collections.singletonMap("name", (Object) "foo"));
final GroovyScriptFactory factory = new GroovyScriptFactory("Groovy Script", customizer);
final ResourceScriptSource scriptSource = new ResourceScriptSource(new NamedByteArrayResource(
"\"name=${name}\"".getBytes(), "InlineScript"));
Object scriptedObject = factory.getScriptedObject(scriptSource, null);
assertEquals("name=foo", scriptedObject.toString());
CompletionService<String> completionService = new ExecutorCompletionService<String>(Executors.newFixedThreadPool(10));
for (int i = 0; i < 100; i++) {
final String name = "bar" + i;
completionService.submit(new Callable<String>() {
public String call() throws Exception {
Object scriptedObject;
synchronized (customizer) {
customizer.setMap(Collections.singletonMap("name", (Object) name));
scriptedObject = factory.getScriptedObject(scriptSource, null);
}
String result = scriptedObject.toString();
logger.debug("Result=" + result + " with name=" + name);
if (!("name=" + name).equals(result)) {
throw new IllegalStateException("Wrong value (" + result + ") for: " + name);
}
return name;
}
});
}
Set<String> set = new HashSet<String>();
for (int i = 0; i < 100; i++) {
set.add(completionService.take().get());
}
assertEquals(100, set.size());
}
@Test
public void testScriptFactoryCustomizerStatic() throws Exception {
final Customizer customizer = new Customizer(Collections.singletonMap("name", (Object) "foo"));
final GroovyScriptFactory factory = new GroovyScriptFactory("Groovy Script", customizer);
final ResourceScriptSource scriptSource = new ResourceScriptSource(new NamedByteArrayResource(
"\"name=${name}\"".getBytes(), "InlineScript"));
Object scriptedObject = factory.getScriptedObject(scriptSource, null);
assertEquals("name=foo", scriptedObject.toString());
CompletionService<String> completionService = new ExecutorCompletionService<String>(Executors.newFixedThreadPool(10));
for (int i = 0; i < 100; i++) {
final String name = "bar" + i;
completionService.submit(new Callable<String>() {
public String call() throws Exception {
Object scriptedObject = factory.getScriptedObject(scriptSource, null);
String result = scriptedObject.toString();
logger.debug("Result=" + result + " with name=" + name);
if (!("name=foo").equals(result)) {
throw new IllegalStateException("Wrong value (" + result + ") for: " + name);
}
return name;
}
});
}
Set<String> set = new HashSet<String>();
for (int i = 0; i < 100; i++) {
set.add(completionService.take().get());
}
assertEquals(100, set.size());
}
@Test
public void testScriptFactoryCustomizerThreadSafetyWithNewScript() throws Exception {
final Customizer customizer = new Customizer(Collections.singletonMap("name", (Object) "foo"));
final GroovyScriptFactory factory = new GroovyScriptFactory("Groovy Script", customizer);
CompletionService<String> completionService = new ExecutorCompletionService<String>(Executors.newFixedThreadPool(5));
for (int i = 0; i < 100; i++) {
final String name = "Bar" + i;
completionService.submit(new Callable<String>() {
public String call() throws Exception {
Object scriptedObject;
synchronized (customizer) {
customizer.setMap(Collections.singletonMap("name", (Object) name));
ResourceScriptSource scriptSource = new ResourceScriptSource(new NamedByteArrayResource(
"\"name=${name}\"".getBytes(), "InlineScript" + name));
scriptedObject = factory.getScriptedObject(scriptSource, null);
}
String result = scriptedObject.toString();
logger.debug("Result=" + result + " with name=" + name);
if (!("name=" + name).equals(result)) {
throw new IllegalStateException("Wrong value (" + result + ") for: " + name);
}
return name;
}
});
}
Set<String> set = new HashSet<String>();
for (int i = 0; i < 100; i++) {
set.add(completionService.take().get());
}
assertEquals(100, set.size());
}
private static class Customizer implements GroovyObjectCustomizer {
private Map<String, Object> map = new HashMap<String, Object>();
public Customizer(Map<String, Object> map) {
super();
this.map.putAll(map);
}
public void customize(GroovyObject goo) {
Assert.state(goo instanceof Script, "Expected a Script");
for (Map.Entry<String, Object> entry : map.entrySet()) {
((Script) goo).getBinding().setVariable(entry.getKey(), entry.getValue());
}
}
public void setMap(Map<String, Object> map) {
this.map.clear();
this.map.putAll(map);
}
}
private static class NamedByteArrayResource extends ByteArrayResource {
private final String fileName;
public NamedByteArrayResource(byte[] bytes, String fileName) {
super(bytes);
this.fileName = fileName;
}
@Override
public String getFilename() throws IllegalStateException {
return fileName;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -18,26 +18,35 @@ package org.springframework.integration.groovy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.core.io.AbstractResource;
import org.springframework.integration.Message;
import org.springframework.integration.handler.MessageProcessor;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.scripting.RefreshableResourceScriptSource;
import org.springframework.integration.scripting.ScriptVariableGenerator;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.scripting.ScriptSource;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.scripting.support.StaticScriptSource;
import org.springframework.test.annotation.Repeat;
import groovy.lang.Script;
/**
* @author Mark Fisher
* @author Dave Syer
@@ -176,6 +185,43 @@ public class GroovyScriptExecutingMessageProcessorTests {
assertEquals("payload is 'hello'", result.toString());
}
@Test
public void testInt3166GroovyScriptExecutingMessageProcessorPerformance() throws Exception {
final Message<?> message = new GenericMessage<Object>("test");
final AtomicInteger var1 = new AtomicInteger();
final AtomicInteger var2 = new AtomicInteger();
String script =
"var1.incrementAndGet(); Thread.sleep(100); var2.set(Math.max(var1.get(), var2.get())); var1.decrementAndGet()";
ScriptSource scriptSource = new StaticScriptSource(script, Script.class.getName());
final MessageProcessor<Object> processor =
new GroovyScriptExecutingMessageProcessor(scriptSource, new ScriptVariableGenerator() {
@Override
public Map<String, Object> generateScriptVariables(Message<?> message) {
Map<String, Object> variables = new HashMap<String, Object>(2);
variables.put("var1", var1);
variables.put("var2", var2);
return variables;
}
});
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
processor.processMessage(message);
}
});
}
executor.shutdown();
assertTrue(executor.awaitTermination(10, TimeUnit.SECONDS));
assertTrue(var2.get() > 1);
}
private static class TestResource extends AbstractResource {

View File

@@ -97,6 +97,7 @@ public class GroovyFilterTests {
assertTrue(this.groovyFilterMessageHandler instanceof MessageFilter);
MessageSelector selector = TestUtils.getPropertyValue(this.groovyFilterMessageHandler, "selector",
MethodInvokingSelector.class);
@SuppressWarnings("rawtypes")
MessageProcessor messageProcessor = TestUtils.getPropertyValue(selector, "messageProcessor", MessageProcessor.class);
//before it was MethodInvokingMessageProcessor
assertTrue(messageProcessor instanceof GroovyScriptExecutingMessageProcessor);

View File

@@ -107,6 +107,7 @@ public class GroovyRouterTests {
@Test
public void testInt2433VerifyRiddingOfMessageProcessorsWrapping() {
assertTrue(this.groovyRouterMessageHandler instanceof MethodInvokingRouter);
@SuppressWarnings("rawtypes")
MessageProcessor messageProcessor = TestUtils.getPropertyValue(this.groovyRouterMessageHandler,
"messageProcessor", MessageProcessor.class);
//before it was MethodInvokingMessageProcessor

View File

@@ -90,7 +90,6 @@ public class GroovyServiceActivatorTests {
String value1 = (String) replyChannel.receive(0).getPayload();
String value2 = (String) replyChannel.receive(0).getPayload();
String value3 = (String) replyChannel.receive(0).getPayload();
System.out.println(value1 + "\n" + value2 + "\n" + value3);
assertTrue(value1.startsWith("groovy-test-1-foo - bar"));
assertTrue(value2.startsWith("groovy-test-2-foo - bar"));
assertTrue(value3.startsWith("groovy-test-3-foo - bar"));

View File

@@ -82,10 +82,11 @@ public class GroovySplitterTests {
@Test
public void testInt2433VerifyRiddingOfMessageProcessorsWrapping() {
assertTrue(this.groovySplitterMessageHandler instanceof MethodInvokingSplitter);
MessageProcessor messageProcessor = TestUtils.getPropertyValue(this.groovySplitterMessageHandler,
assertTrue(this.groovySplitterMessageHandler instanceof MethodInvokingSplitter);
@SuppressWarnings("rawtypes")
MessageProcessor messageProcessor = TestUtils.getPropertyValue(this.groovySplitterMessageHandler,
"messageProcessor", MessageProcessor.class);
//before it was MethodInvokingMessageProcessor
//before it was MethodInvokingMessageProcessor
assertTrue(messageProcessor instanceof GroovyScriptExecutingMessageProcessor);
}

View File

@@ -88,11 +88,12 @@ public class GroovyTransformerTests {
@Test
public void testInt2433VerifyRiddingOfMessageProcessorsWrapping() {
assertTrue(this.groovyTransformerMessageHandler instanceof MessageTransformingHandler);
Transformer transformer = TestUtils.getPropertyValue(this.groovyTransformerMessageHandler, "transformer", Transformer.class);
assertTrue(transformer instanceof AbstractMessageProcessingTransformer);
MessageProcessor messageProcessor = TestUtils.getPropertyValue(transformer, "messageProcessor", MessageProcessor.class);
//before it was MethodInvokingMessageProcessor
assertTrue(this.groovyTransformerMessageHandler instanceof MessageTransformingHandler);
Transformer transformer = TestUtils.getPropertyValue(this.groovyTransformerMessageHandler, "transformer", Transformer.class);
assertTrue(transformer instanceof AbstractMessageProcessingTransformer);
@SuppressWarnings("rawtypes")
MessageProcessor messageProcessor = TestUtils.getPropertyValue(transformer, "messageProcessor", MessageProcessor.class);
//before it was MethodInvokingMessageProcessor
assertTrue(messageProcessor instanceof GroovyScriptExecutingMessageProcessor);
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2013 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.
@@ -27,7 +27,7 @@ import org.springframework.util.Assert;
/**
* Base {@link MessageProcessor} for scripting implementations to extend.
*
*
* @author Mark Fisher
* @author Stefan Reuter
* @since 2.0
@@ -36,9 +36,9 @@ public abstract class AbstractScriptExecutingMessageProcessor<T> implements Mess
private final ScriptVariableGenerator scriptVariableGenerator;
private volatile ClassLoader beanClassLoader;
protected volatile ClassLoader beanClassLoader;
private volatile BeanFactory beanFactory;
protected volatile BeanFactory beanFactory;
protected AbstractScriptExecutingMessageProcessor() {
this.scriptVariableGenerator = new DefaultScriptVariableGenerator();
@@ -48,7 +48,7 @@ public abstract class AbstractScriptExecutingMessageProcessor<T> implements Mess
Assert.notNull(scriptVariableGenerator, "scriptVariableGenerator must not be null");
this.scriptVariableGenerator = scriptVariableGenerator;
}
/**
* Executes the script and returns the result.
@@ -69,23 +69,15 @@ public abstract class AbstractScriptExecutingMessageProcessor<T> implements Mess
this.beanClassLoader = classLoader;
}
protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
protected BeanFactory getBeanFactory() {
return this.beanFactory;
}
/**
* Subclasses must implement this method to create a script source,
* optionally using the message to locate or create the script.
*
*
* @param message the message being processed
* @return a ScriptSource to use to create a script
*/

View File

@@ -72,7 +72,6 @@ public class Jsr223ServiceActivatorTests {
String value1 = (String) replyChannel.receive(0).getPayload();
String value2 = (String) replyChannel.receive(0).getPayload();
String value3 = (String) replyChannel.receive(0).getPayload();
System.out.println(value1 + "\n" + value2 + "\n" + value3);
assertTrue(value1.startsWith("python-test-1-foo - bar"));
assertTrue(value2.startsWith("python-test-2-foo - bar"));
assertTrue(value3.startsWith("python-test-3-foo - bar"));

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2011 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.
@@ -13,12 +13,12 @@
package org.springframework.integration.scripting.jsr223;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.scripting.ScriptExecutor;
import org.springframework.integration.scripting.ScriptingException;
@@ -30,28 +30,29 @@ import org.springframework.scripting.support.StaticScriptSource;
*
*/
public class Jsr223ScriptExecutorTests {
@Test
public void test(){
public void test() {
ScriptExecutor executor = ScriptExecutorFactory.getScriptExecutor("jruby");
executor.executeScript(new StaticScriptSource("puts 'hello, world'"));
executor.executeScript(new StaticScriptSource("puts 'hello, again'"));
executor.executeScript(new StaticScriptSource("'hello, world'"));
executor.executeScript(new StaticScriptSource("'hello, again'"));
Map<String,Object> variables = new HashMap<String,Object>();
Map<String,Object> headers = new HashMap<String,Object>();
headers.put("one",1);
headers.put("two","two");
headers.put("three", new Integer(3));
headers.put("one", 1);
headers.put("two", "two");
headers.put("three", 3);
variables.put("payload", "payload");
variables.put("headers", headers);
String result = (String)executor.executeScript(
new ResourceScriptSource(new ClassPathResource("/org/springframework/integration/scripting/jsr223/print_message.rb")),
variables
);
assertEquals("payload modified",result.substring(0,"payload modified".length()));
assertEquals("payload modified", result.substring(0, "payload modified".length()));
}
@Test
public void testJs(){
@@ -59,25 +60,20 @@ public class Jsr223ScriptExecutorTests {
Object obj = executor.executeScript(new StaticScriptSource("function js(){ return 'js';} js();"));
assertEquals("js",obj.toString());
}
@Test
@Test
public void testPython() {
ScriptExecutor executor = ScriptExecutorFactory.getScriptExecutor("python");
Object obj = executor.executeScript(new StaticScriptSource("x=2") );
assertEquals(2,obj);
obj = executor.executeScript(new StaticScriptSource("def foo(y):\n\tx=y\n\treturn y\nz=foo(2)") );
assertEquals(2,obj);
}
@Test
@Test(expected = ScriptingException.class)
public void testInvalidLanguageThrowsScriptingException() {
try {
ScriptExecutor executor = ScriptExecutorFactory.getScriptExecutor("foo");
executor.executeScript(new StaticScriptSource("x=2"));
fail("should throw Exception");
} catch (ScriptingException e) {
System.out.println(e.getMessage());
}
ScriptExecutor executor = ScriptExecutorFactory.getScriptExecutor("foo");
executor.executeScript(new StaticScriptSource("x=2"));
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Copyright 2002-2013 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.
@@ -36,39 +36,38 @@ public class PythonScriptExecutorTests {
public void init() {
executor = new PythonScriptExecutor();
}
@Test
@Test
public void testLiteral() {
Object obj = executor.executeScript(new StaticScriptSource("3+4") );
assertEquals(7,obj);
obj = executor.executeScript(new StaticScriptSource("'hello,world'") );
assertEquals("hello,world",obj);
}
@Test
@Test
public void test1() {
Object obj = executor.executeScript(new StaticScriptSource("x=2") );
assertEquals(2,obj);
}
@Test
@Test
public void test2() {
Object obj = executor.executeScript(new StaticScriptSource("def foo(y):\n\tx=y\n\treturn y\nz=foo(2)") );
assertEquals(2,obj);
}
@Test
@Test
public void test3() {
ScriptSource source =
ScriptSource source =
new ResourceScriptSource(new ClassPathResource("/org/springframework/integration/scripting/jsr223/test3.py"));
Object obj = executor.executeScript(source);
System.out.println(obj);
PyTuple tuple = (PyTuple) obj;
assertEquals(1, tuple.get(0));
}
@Test
public void testEmbeddedVariable() {
Map<String,Object> variables = new HashMap<String,Object>();