From f0c4bdb75633372572b5ab979566c7ed947783dc Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 7 Oct 2013 13:04:27 +0300 Subject: [PATCH] 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 --- .../groovy/GroovyCommandMessageProcessor.java | 14 +- ...GroovyScriptExecutingMessageProcessor.java | 107 +++++++-- .../groovy/GroovyExpressionTests.java | 213 ------------------ ...yScriptExecutingMessageProcessorTests.java | 48 +++- .../groovy/config/GroovyFilterTests.java | 1 + .../groovy/config/GroovyRouterTests.java | 1 + .../config/GroovyServiceActivatorTests.java | 1 - .../groovy/config/GroovySplitterTests.java | 7 +- .../groovy/config/GroovyTransformerTests.java | 11 +- ...stractScriptExecutingMessageProcessor.java | 24 +- .../jsr223/Jsr223ServiceActivatorTests.java | 1 - .../jsr223/Jsr223ScriptExecutorTests.java | 52 ++--- .../jsr223/PythonScriptExecutorTests.java | 33 ++- 13 files changed, 197 insertions(+), 316 deletions(-) delete mode 100644 spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyExpressionTests.java diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyCommandMessageProcessor.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyCommandMessageProcessor.java index ce6196da45..08893a0bee 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyCommandMessageProcessor.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyCommandMessageProcessor.java @@ -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; diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java index eb79bc172e..72f33ace8e 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java @@ -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 implements InitializingBean { +public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecutingMessageProcessor { - 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 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 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); } } + } diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyExpressionTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyExpressionTests.java deleted file mode 100644 index db9f2abc65..0000000000 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyExpressionTests.java +++ /dev/null @@ -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 completionService = new ExecutorCompletionService(Executors.newFixedThreadPool(10)); - for (int i = 0; i < 100; i++) { - final String name = "bar" + i; - completionService.submit(new Callable() { - 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 set = new HashSet(); - 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 completionService = new ExecutorCompletionService(Executors.newFixedThreadPool(10)); - for (int i = 0; i < 100; i++) { - final String name = "bar" + i; - completionService.submit(new Callable() { - 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 set = new HashSet(); - 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 completionService = new ExecutorCompletionService(Executors.newFixedThreadPool(5)); - for (int i = 0; i < 100; i++) { - final String name = "Bar" + i; - completionService.submit(new Callable() { - 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 set = new HashSet(); - for (int i = 0; i < 100; i++) { - set.add(completionService.take().get()); - } - assertEquals(100, set.size()); - } - - - private static class Customizer implements GroovyObjectCustomizer { - - private Map map = new HashMap(); - - public Customizer(Map map) { - super(); - this.map.putAll(map); - } - - public void customize(GroovyObject goo) { - Assert.state(goo instanceof Script, "Expected a Script"); - for (Map.Entry entry : map.entrySet()) { - ((Script) goo).getBinding().setVariable(entry.getKey(), entry.getValue()); - } - } - - public void setMap(Map 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; - } - - } - -} diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessorTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessorTests.java index 7e04be5c68..039835c4d8 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessorTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessorTests.java @@ -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("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 processor = + new GroovyScriptExecutingMessageProcessor(scriptSource, new ScriptVariableGenerator() { + @Override + public Map generateScriptVariables(Message message) { + Map variables = new HashMap(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 { diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyFilterTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyFilterTests.java index b472eeabb5..54978959e3 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyFilterTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyFilterTests.java @@ -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); diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyRouterTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyRouterTests.java index 07b1c2fa6a..12bc99ba76 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyRouterTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyRouterTests.java @@ -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 diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests.java index c7bc6fd674..86c3724da5 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests.java @@ -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")); diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovySplitterTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovySplitterTests.java index 543831ec9f..7355ea75e5 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovySplitterTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovySplitterTests.java @@ -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); } diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyTransformerTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyTransformerTests.java index 5fafa41c7d..74d7725b42 100644 --- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyTransformerTests.java +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyTransformerTests.java @@ -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); } } diff --git a/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/AbstractScriptExecutingMessageProcessor.java b/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/AbstractScriptExecutingMessageProcessor.java index 06300b0554..de2443c5a7 100644 --- a/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/AbstractScriptExecutingMessageProcessor.java +++ b/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/AbstractScriptExecutingMessageProcessor.java @@ -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 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 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 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 */ diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.java b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.java index 964aadefb8..b46cca2ad2 100644 --- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.java +++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.java @@ -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")); diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutorTests.java b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutorTests.java index dcddde9582..039fac7099 100644 --- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutorTests.java +++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutorTests.java @@ -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 variables = new HashMap(); - + Map headers = new HashMap(); - 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")); } } diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/PythonScriptExecutorTests.java b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/PythonScriptExecutorTests.java index f30c04b549..41a34dcc47 100644 --- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/PythonScriptExecutorTests.java +++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/PythonScriptExecutorTests.java @@ -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 variables = new HashMap();