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 72f33ace8e..125b847bea 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,12 +16,21 @@
package org.springframework.integration.groovy;
+import groovy.lang.Binding;
+import groovy.lang.GString;
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyObject;
+import groovy.lang.MetaClass;
+import groovy.lang.MissingPropertyException;
+import groovy.lang.Script;
+
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.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.scripting.AbstractScriptExecutingMessageProcessor;
@@ -32,13 +41,6 @@ import org.springframework.scripting.groovy.GroovyObjectCustomizer;
import org.springframework.util.Assert;
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.
@@ -136,12 +138,9 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
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);
- }
+ VariableBindingGroovyObjectCustomizerDecorator groovyObjectCustomizer =
+ new BindingOverwriteGroovyObjectCustomizerDecorator(new BeanFactoryFallbackBinding(variables));
+ groovyObjectCustomizer.setCustomizer(this.customizerDecorator);
if (goo instanceof Script) {
// Allow metaclass and other customization.
@@ -164,4 +163,34 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
}
}
+ private class BeanFactoryFallbackBinding extends Binding {
+
+ private BeanFactoryFallbackBinding(Map, ?> variables) {
+ super(variables);
+ }
+
+ @Override
+ public Object getVariable(String name) {
+ try {
+ return super.getVariable(name);
+ }
+ catch (MissingPropertyException e) {
+ // Original {@link Binding} doesn't have 'variable' for the given 'name'.
+ // Try to resolve it as 'bean' from the given beanFactory.
+ }
+
+ if (GroovyScriptExecutingMessageProcessor.this.beanFactory == null) {
+ throw new MissingPropertyException(name, this.getClass());
+ }
+
+ try {
+ return GroovyScriptExecutingMessageProcessor.this.beanFactory.getBean(name);
+ }
+ catch (NoSuchBeanDefinitionException e) {
+ throw new MissingPropertyException(name, this.getClass(), e);
+ }
+ }
+
+ }
+
}
diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-context.xml b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-context.xml
index 4641ef303a..da3348f1e5 100644
--- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-context.xml
+++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-context.xml
@@ -10,30 +10,38 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-fail-context.xml b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-fail-context.xml
deleted file mode 100644
index e105a28471..0000000000
--- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyServiceActivatorTests-fail-context.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
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 86c3724da5..8615fcadbc 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
@@ -23,6 +23,8 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -38,6 +40,7 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.channel.QueueChannel;
+import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.handler.ReplyRequiredException;
import org.springframework.integration.message.ErrorMessage;
import org.springframework.integration.message.GenericMessage;
@@ -73,6 +76,9 @@ public class GroovyServiceActivatorTests {
@Autowired
private MessageChannel invalidInlineScript;
+ @Autowired
+ private MessageChannel scriptWithoutVariablesInput;
+
@Autowired
private MyGroovyCustomizer groovyCustomizer;
@@ -134,13 +140,38 @@ public class GroovyServiceActivatorTests {
Message> message = MessageBuilder.withPayload("test-" + i).setReplyChannel(replyChannel).build();
this.inlineScriptInput.send(message);
}
- assertEquals("inline-test-1", replyChannel.receive(0).getPayload());
- assertEquals("inline-test-2", replyChannel.receive(0).getPayload());
- assertEquals("inline-test-3", replyChannel.receive(0).getPayload());
+
+ DateFormat format = new SimpleDateFormat("dd.mm.yyyy");
+
+ String now = format.format(new Date());
+
+ assertEquals("inline-test-1 : " + now, replyChannel.receive(0).getPayload());
+ assertEquals("inline-test-2 : " + now, replyChannel.receive(0).getPayload());
+ assertEquals("inline-test-3 : " + now, replyChannel.receive(0).getPayload());
+
assertNull(replyChannel.receive(0));
assertTrue(groovyCustomizer.executed);
}
+ @Test
+ public void testScriptWithoutVariables() throws Exception{
+ PollableChannel replyChannel = new QueueChannel();
+ for (int i = 1; i <= 3; i++) {
+ Message> message = MessageBuilder.withPayload("test-" + i).setReplyChannel(replyChannel).build();
+ this.scriptWithoutVariablesInput.send(message);
+ }
+
+ DateFormat format = new SimpleDateFormat("dd.mm.yyyy");
+
+ String now = format.format(new Date());
+
+ assertEquals("withoutVariables-test-1 : " + now, replyChannel.receive(0).getPayload());
+ assertEquals("withoutVariables-test-2 : " + now, replyChannel.receive(0).getPayload());
+ assertEquals("withoutVariables-test-3 : " + now, replyChannel.receive(0).getPayload());
+
+ assertNull(replyChannel.receive(0));
+ }
+
//INT-2399
@Test(expected = MessageHandlingException.class)
public void invalidInlineScript() throws Exception {
@@ -158,11 +189,6 @@ public class GroovyServiceActivatorTests {
}
- @Test(expected=BeanDefinitionParsingException.class)
- public void inlineScriptAndVariables() throws Exception{
- new ClassPathXmlApplicationContext("GroovyServiceActivatorTests-fail-context.xml", this.getClass());
- }
-
@Test(expected=BeanDefinitionParsingException.class)
public void variablesAndScriptVariableGenerator() throws Exception{
new ClassPathXmlApplicationContext("GroovyServiceActivatorTests-fail-withgenerator-context.xml", this.getClass());
diff --git a/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/config/AbstractScriptParser.java b/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/config/AbstractScriptParser.java
index 8e02a81da2..5d8c7f0aa6 100644
--- a/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/config/AbstractScriptParser.java
+++ b/spring-integration-scripting/src/main/java/org/springframework/integration/scripting/config/AbstractScriptParser.java
@@ -16,14 +16,15 @@ import java.util.List;
import org.w3c.dom.Element;
+import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
+import org.springframework.integration.scripting.DefaultScriptVariableGenerator;
import org.springframework.integration.scripting.RefreshableResourceScriptSource;
import org.springframework.scripting.support.StaticScriptSource;
import org.springframework.util.CollectionUtils;
@@ -32,6 +33,7 @@ import org.springframework.util.xml.DomUtils;
/**
* @author David Turanski
+ * @author Artem Bilan
*
*/
public abstract class AbstractScriptParser extends AbstractSingleBeanDefinitionParser {
@@ -62,13 +64,6 @@ public abstract class AbstractScriptParser extends AbstractSingleBeanDefinitionP
List variableElements = DomUtils.getChildElementsByTagName(element, "variable");
String scriptVariableGeneratorName = element.getAttribute("script-variable-generator");
- if (StringUtils.hasText(scriptText)
- && (variableElements.size() > 0 || StringUtils.hasText(scriptVariableGeneratorName))) {
- parserContext.getReaderContext().error(
- "Variable bindings or custom ScriptVariableGenerator are not allowed when using an inline groovy script. "
- + "Specify location of the script via 'location' attribute instead", element);
- return;
- }
if (StringUtils.hasText(scriptVariableGeneratorName) && variableElements.size() > 0) {
parserContext.getReaderContext().error(
@@ -88,33 +83,23 @@ public abstract class AbstractScriptParser extends AbstractSingleBeanDefinitionP
builder.addConstructorArgValue(new StaticScriptSource(scriptText));
}
}
+
+ BeanMetadataElement scriptVariableGeneratorDef = null;
+
if (!StringUtils.hasText(scriptVariableGeneratorName)) {
BeanDefinitionBuilder scriptVariableGeneratorBuilder = BeanDefinitionBuilder
- .genericBeanDefinition("org.springframework.integration.scripting.DefaultScriptVariableGenerator");
- ManagedMap variableMap = new ManagedMap();
- for (Element childElement : variableElements) {
- String variableName = childElement.getAttribute("name");
- String variableValue = childElement.getAttribute("value");
- String variableRef = childElement.getAttribute("ref");
- if (!(StringUtils.hasText(variableValue) ^ StringUtils.hasText(variableRef))) {
- parserContext.getReaderContext().error(
- "Exactly one of the 'ref' attribute or 'value' attribute, " + " is required for element "
- + IntegrationNamespaceUtils.createElementDescription(element) + ".", element);
- }
- if (StringUtils.hasText(variableValue)) {
- variableMap.put(variableName, variableValue);
- }
- else {
- variableMap.put(variableName, new RuntimeBeanReference(variableRef));
- }
- }
+ .genericBeanDefinition(DefaultScriptVariableGenerator.class);
+ ManagedMap variableMap = buildVariablesMap(element, parserContext, variableElements);
if (!CollectionUtils.isEmpty(variableMap)) {
scriptVariableGeneratorBuilder.addConstructorArgValue(variableMap);
}
- scriptVariableGeneratorName = BeanDefinitionReaderUtils.registerWithGeneratedName(
- scriptVariableGeneratorBuilder.getBeanDefinition(), parserContext.getRegistry());
+ scriptVariableGeneratorDef = scriptVariableGeneratorBuilder.getBeanDefinition();
}
- builder.addConstructorArgReference(scriptVariableGeneratorName);
+ else {
+ scriptVariableGeneratorDef = new RuntimeBeanReference(scriptVariableGeneratorName);
+ }
+
+ builder.addConstructorArgValue(scriptVariableGeneratorDef);
postProcess(builder, element, parserContext);
}
@@ -138,4 +123,61 @@ public abstract class AbstractScriptParser extends AbstractSingleBeanDefinitionP
return resourceScriptSourceBuilder.getBeanDefinition();
}
+ private ManagedMap buildVariablesMap(final Element element, final ParserContext parserContext,
+ List variableElements) {
+ @SuppressWarnings("serial")
+ ManagedMap variableMap = new ManagedMap() {
+
+ @Override
+ public Object put(String key, Object value) {
+ if (this.containsKey(key)) {
+ parserContext.getReaderContext().error("Duplicated variable: " + key, element);
+ }
+ return super.put(key, value);
+ }
+
+ };
+
+ for (Element childElement : variableElements) {
+ String variableName = childElement.getAttribute("name");
+ String variableValue = childElement.getAttribute("value");
+ String variableRef = childElement.getAttribute("ref");
+ if (!(StringUtils.hasText(variableValue) ^ StringUtils.hasText(variableRef))) {
+ parserContext.getReaderContext().error(
+ "Exactly one of the 'ref' attribute or 'value' attribute, " + " is required for element "
+ + IntegrationNamespaceUtils.createElementDescription(element) + ".", element);
+ }
+ if (StringUtils.hasText(variableValue)) {
+ variableMap.put(variableName, variableValue);
+ }
+ else {
+ variableMap.put(variableName, new RuntimeBeanReference(variableRef));
+ }
+ }
+
+ String variables = element.getAttribute("variables");
+ if (StringUtils.hasText(variables)) {
+ String[] variablePairs = StringUtils.commaDelimitedListToStringArray(variables);
+ for (String variablePair : variablePairs) {
+ String[] variableValue = variablePair.split("=");
+ if (variableValue.length != 2) {
+ parserContext.getReaderContext().error(
+ "Variable declarations in the 'variable' attribute must have the "
+ + "form 'var=value'; found : '" + variablePair + "'", element);
+ }
+ String variable = variableValue[0].trim();
+ String value = variableValue[1];
+ if (variable.endsWith("-ref")) {
+ variable = variable.substring(0, variable.indexOf("-ref"));
+ variableMap.put(variable, new RuntimeBeanReference(value));
+ }
+ else {
+ variableMap.put(variable, value);
+ }
+ }
+ }
+
+ return variableMap;
+ }
+
}
diff --git a/spring-integration-scripting/src/main/resources/org/springframework/integration/scripting/config/spring-integration-scripting-core-3.0.xsd b/spring-integration-scripting/src/main/resources/org/springframework/integration/scripting/config/spring-integration-scripting-core-3.0.xsd
index b55e3bb317..f92337b667 100644
--- a/spring-integration-scripting/src/main/resources/org/springframework/integration/scripting/config/spring-integration-scripting-core-3.0.xsd
+++ b/spring-integration-scripting/src/main/resources/org/springframework/integration/scripting/config/spring-integration-scripting-core-3.0.xsd
@@ -61,7 +61,7 @@
Reference to the ScriptVariableGenerator bean. This attribute is mutually
- exclusive with any 'variable' sub-elements.
+ exclusive with any 'variable' sub-elements and 'variables' attribute.
+
+
+
+ Comma-delimited pairs of variables and their values.
+ the variable name can applies '-ref' suffix, which mean to determine
+ a variable value as a bean reference.
+ This attribute isn't mutually exclusive with 'variable' sub-elements
+ and all variables will be merged to one Map.
+ This attribute is mutually exclusive with 'script-variable-generator' attribute.
+
+
+
diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-context.xml b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-context.xml
index 6949921b6a..69dab9f3cc 100644
--- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-context.xml
+++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-context.xml
@@ -10,30 +10,31 @@
http://www.springframework.org/schema/integration/scripting http://www.springframework.org/schema/integration/scripting/spring-integration-scripting.xsd">
-
+ location="org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.py"
+ variables="foo2=#{'foo2'}, date2-ref=date">
-
-
+
+
-
-
-
-
+
+
+
+
-
+
@@ -41,5 +42,5 @@
-
+
diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-context.xml b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-duplicated-variable-context.xml
similarity index 80%
rename from spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-context.xml
rename to spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-duplicated-variable-context.xml
index 6eb04afa62..e79f3e6b04 100644
--- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-context.xml
+++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests-fail-duplicated-variable-context.xml
@@ -7,14 +7,13 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/scripting http://www.springframework.org/schema/integration/scripting/spring-integration-scripting.xsd">
-
-
-
+
+
-
+
-
+
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 b46cca2ad2..87c0a07d00 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
@@ -17,19 +17,21 @@
package org.springframework.integration.scripting.config.jsr223;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
@@ -72,14 +74,24 @@ public class Jsr223ServiceActivatorTests {
String value1 = (String) replyChannel.receive(0).getPayload();
String value2 = (String) replyChannel.receive(0).getPayload();
String value3 = (String) replyChannel.receive(0).getPayload();
- assertTrue(value1.startsWith("python-test-1-foo - bar"));
- assertTrue(value2.startsWith("python-test-2-foo - bar"));
- assertTrue(value3.startsWith("python-test-3-foo - bar"));
+ assertTrue(value1.startsWith("python-test-1-foo (foo2) - bar"));
+ assertTrue(value2.startsWith("python-test-2-foo (foo2) - bar"));
+ assertTrue(value3.startsWith("python-test-3-foo (foo2) - bar"));
// because we are using 'prototype bean the suffix date will be
// different
- assertFalse(value1.substring(26).equals(value2.substring(26)));
- assertFalse(value2.substring(26).equals(value3.substring(26)));
+ assertFalse(value1.substring(value1.indexOf(":") + 1, value1.lastIndexOf(":"))
+ .equals(value2.substring(value1.indexOf(":") + 1, value1.lastIndexOf(":"))));
+ assertFalse(value1.substring(value1.indexOf(":") +1, value1.lastIndexOf(":"))
+ .equals(value1.substring(value1.lastIndexOf(":"))));
+
+ assertFalse(value2.substring(value1.indexOf(":") + 1, value1.lastIndexOf(":"))
+ .equals(value3.substring(value1.indexOf(":") + 1, value1.lastIndexOf(":"))));
+
+ assertFalse(value1.substring(value1.lastIndexOf(":") + 1)
+ .equals(value2.substring(value1.lastIndexOf(":") + 1)));
+ assertFalse(value2.substring(value1.lastIndexOf(":") + 1)
+ .equals(value3.substring(value1.lastIndexOf(":") + 1)));
assertNull(replyChannel.receive(0));
}
@@ -118,22 +130,41 @@ public class Jsr223ServiceActivatorTests {
Message> message = MessageBuilder.withPayload("test-" + i).setReplyChannel(replyChannel).build();
this.inlineScriptInput.send(message);
}
- assertEquals("inline-test-1", replyChannel.receive(0).getPayload());
- assertEquals("inline-test-2", replyChannel.receive(0).getPayload());
- assertEquals("inline-test-3", replyChannel.receive(0).getPayload());
+ String payload = (String) replyChannel.receive(0).getPayload();
+
+ assertThat(payload, Matchers.startsWith("inline-test-1 - FOO"));
+
+ payload = (String) replyChannel.receive(0).getPayload();
+ assertThat(payload, Matchers.startsWith("inline-test-2 - FOO"));
+
+ payload = (String) replyChannel.receive(0).getPayload();
+ assertThat(payload, Matchers.startsWith("inline-test-3 - FOO"));
+ assertTrue(payload.substring(payload.indexOf(":") + 1).matches(".+\\d{2}:\\d{2}:\\d{2}.+"));
+
assertNull(replyChannel.receive(0));
}
- @Test(expected = BeanDefinitionParsingException.class)
- public void inlineScriptAndVariables() throws Exception {
- new ClassPathXmlApplicationContext("Jsr223ServiceActivatorTests-fail-context.xml", this.getClass());
+ @Test
+ public void variablesAndScriptVariableGenerator() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("Jsr223ServiceActivatorTests-fail-withgenerator-context.xml", this.getClass());
+ fail("BeansException expected.");
+ }
+ catch (BeansException e) {
+ assertThat(e.getMessage(), Matchers.containsString("'script-variable-generator' and 'variable' sub-elements are mutually exclusive."));
+ }
}
- @Test(expected = BeanDefinitionParsingException.class)
- public void variablesAndScriptVariableGenerator() throws Exception {
- new ClassPathXmlApplicationContext("Jsr223ServiceActivatorTests-fail-withgenerator-context.xml",
- this.getClass());
+ @Test
+ public void testDuplicateVariable() throws Exception {
+ try {
+ new ClassPathXmlApplicationContext("Jsr223ServiceActivatorTests-fail-duplicated-variable-context.xml", this.getClass());
+ fail("BeansException expected.");
+ }
+ catch (BeansException e) {
+ assertThat(e.getMessage(), Matchers.containsString("Duplicated variable: foo"));
+ }
}
public static class SampleScriptVariSource implements ScriptVariableGenerator {
diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.py b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.py
index 41aced873d..4617c17a74 100644
--- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.py
+++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/config/jsr223/Jsr223ServiceActivatorTests.py
@@ -1 +1 @@
-"python-%s-%s - %s - %s" %(payload,foo,bar,date)
\ No newline at end of file
+"python-%s-%s (%s) - %s - :%s:%s" %(payload,foo,foo2,bar,date,date2)
diff --git a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutingMessageProcessorTests.java b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutingMessageProcessorTests.java
index 691fb30d60..64ea7d6538 100644
--- a/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutingMessageProcessorTests.java
+++ b/spring-integration-scripting/src/test/java/org/springframework/integration/scripting/jsr223/Jsr223ScriptExecutingMessageProcessorTests.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.
@@ -19,6 +19,9 @@ import java.util.Map;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
+
+import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.Message;
import org.springframework.integration.message.GenericMessage;
@@ -31,42 +34,45 @@ import org.springframework.scripting.support.ResourceScriptSource;
*
*/
public class Jsr223ScriptExecutingMessageProcessorTests {
+
ScriptExecutor executor;
+
@Before
public void setUp() {
executor = ScriptExecutorFactory.getScriptExecutor("jruby");
}
@Test
public void testExecuteWithVariables(){
-
-
Map vars = new HashMap();
vars.put("one",1);
vars.put("two","two");
- vars.put("three", new Integer(3));
-
+ vars.put("three", 3);
+
ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("/org/springframework/integration/scripting/jsr223/print_message.rb"));
-
- ScriptExecutingMessageProcessor messageProcessor = new ScriptExecutingMessageProcessor(scriptSource,executor,vars);
-
+
+ ScriptExecutingMessageProcessor messageProcessor = new ScriptExecutingMessageProcessor(scriptSource, executor, vars);
+ messageProcessor.setBeanFactory(Mockito.mock(BeanFactory.class));
+
Message> message = new GenericMessage("hello");
-
+
Object obj = messageProcessor.processMessage(message);
-
+
assertEquals("hello modified",obj.toString().substring(0,"hello modified".length()));
}
-
+
@Test
public void testWithNoVars(){
ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("/org/springframework/integration/scripting/jsr223/print_message.rb"));
-
- ScriptExecutingMessageProcessor messageProcessor = new ScriptExecutingMessageProcessor(scriptSource,executor);
-
+
+ ScriptExecutingMessageProcessor messageProcessor = new ScriptExecutingMessageProcessor(scriptSource, executor);
+ messageProcessor.setBeanFactory(Mockito.mock(BeanFactory.class));
+
Message> message = new GenericMessage("hello");
-
+
Object obj = messageProcessor.processMessage(message);
-
+
assertEquals("hello modified",obj.toString().substring(0,"hello modified".length()));
}
-
+
}
+
diff --git a/src/reference/docbook/groovy.xml b/src/reference/docbook/groovy.xml
index 4845df307a..1011e016cc 100644
--- a/src/reference/docbook/groovy.xml
+++ b/src/reference/docbook/groovy.xml
@@ -57,9 +57,26 @@
Setting a custom GroovyObjectCustomizer is not mutually exclusive with <variable> sub-elements or
the script-variable-generator attribute. It can also be provided when defining an inline script.
- For more information regarding <variable> and script-variable-generator, see the
- paragraph 'Script variable bindings' of .
-
+
+
+ With Spring Integration 3.0, in addition to the variable sub-element,
+ the variables attribute has been introduced. Also, groovy scripts have the ability to resolve a
+ variable to a bean in the
+ BeanFactory, if a binding variable was not provided with
+ the name:
+ <int-groovy:script>
+ <![CDATA[
+ entityManager.persist(payload)
+ payload
+ ]]>
+</int-groovy:script>
+ where variable entityManager is an appropriate bean in the application context.
+
+
+ For more information regarding <variable>, variables,
+ and script-variable-generator, see the
+ paragraph 'Script variable bindings' of .
+
diff --git a/src/reference/docbook/scripting.xml b/src/reference/docbook/scripting.xml
index 559bd018ce..f79f807225 100644
--- a/src/reference/docbook/scripting.xml
+++ b/src/reference/docbook/scripting.xml
@@ -98,7 +98,32 @@
]]>
As shown in the above example, you can bind a script variable either to a scalar value or a Spring bean reference. Note that
payload and headers will still be included as binding variables.
-
+
+
+ With Spring Integration 3.0, in addition to the variable sub-element,
+ the variables attribute has been introduced. This attribute and variable sub-elements
+ aren't mutually exclusive and you can combine them within one script component. However variables must
+ be unique, regardless of where they are defined. Also, since Spring Integration 3.0,
+ variable bindings are allowed for inline scripts too:
+ <service-activator input-channel="input">
+ <script:script lang="ruby" variables="foo=FOO, date-ref=dateBean">
+ <script:variable name="bar" ref="barBean"/>
+ <script:variable name="baz" value="bar"/>
+ <![CDATA[
+ payload.foo = foo
+ payload.date = date
+ payload.bar = bar
+ payload.baz = baz
+ payload
+ ]]>
+ </script:script>
+</service-activator>
+ The example above shows a combination of an inline script, a variable sub-element and a variables attribute.
+ The variables attribute is a comma-separated value, where each segment contains an '=' separated pair
+ of the variable and its value. The variable name can be suffixed with -ref, as in the
+ date-ref variable above. That means that the binding variable
+ will have the name date, but the value will be a reference to the dateBean bean from the application context.
+ This may be useful when using Property Placeholder Configuration or command line arguments.
If you need more control over how variables are generated, you can implement your own Java class
@@ -115,7 +140,7 @@
provide an implementation of ScriptVariableGenerator and reference it with the script-variable-generator
attribute:
+ script-variable-generator="variableGenerator"/>
]]>
If a script-variable-generator is not provided, script components use
@@ -124,7 +149,7 @@
variables from the Message in its generateScriptVariables(Message) method.
You cannot provide both the script-variable-generator attribute and <variable> sub-element(s)
- as they are mutually exclusive. Also, custom variable bindings cannot be used with an inline script.
+ as they are mutually exclusive.
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml
index 3f32602196..174005f429 100644
--- a/src/reference/docbook/whats-new.xml
+++ b/src/reference/docbook/whats-new.xml
@@ -667,5 +667,13 @@
, , and for more information.
+
+ Scripting Support: Variables Changes
+
+ A new variables attribute has been introduced for scripting components.
+ In addition, variable bindings are now allowed for inline scripts.
+ See and for more information.
+
+