INT-2491: Scripting: Variables Improvements
JIRA: https://jira.springsource.org/browse/INT-2491 * Add support variables for 'inline' scripts * Add convenient attribute `variables` for script tags * Introduce `BeanFactoryFallbackBinding` for groovy scripts. INT-2491: Polishing * Add check for duplication of provided variables * Tests and Docs Polishing
This commit is contained in:
committed by
Gary Russell
parent
a7cabc53b0
commit
87798b055f
@@ -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 <code>beanFactory</code>.
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,30 +10,38 @@
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<service-activator input-channel="referencedScriptInput">
|
||||
<groovy:script location="org/springframework/integration/groovy/config/GroovyServiceActivatorTests.groovy"
|
||||
<groovy:script location="org/springframework/integration/groovy/config/GroovyServiceActivatorTests.groovy"
|
||||
customizer="groovyCustomizer">
|
||||
<groovy:variable name="foo" value="foo"/>
|
||||
<groovy:variable name="bar" value="bar"/>
|
||||
<groovy:variable name="date" ref="date"/>
|
||||
</groovy:script>
|
||||
</service-activator>
|
||||
|
||||
|
||||
|
||||
|
||||
<service-activator input-channel="withScriptVariableGenerator">
|
||||
<groovy:script location="org/springframework/integration/groovy/config/GroovyServiceActivatorTests.groovy"
|
||||
script-variable-generator="scriptVarSource" customizer="groovyCustomizer"/>
|
||||
</service-activator>
|
||||
|
||||
<beans:bean id="groovyCustomizer"
|
||||
|
||||
<beans:bean id="groovyCustomizer"
|
||||
class="org.springframework.integration.groovy.config.GroovyServiceActivatorTests.MyGroovyCustomizer"/>
|
||||
|
||||
<beans:bean id="scriptVarSource"
|
||||
|
||||
<beans:bean id="scriptVarSource"
|
||||
class="org.springframework.integration.groovy.config.GroovyServiceActivatorTests.SampleScriptVariSource"/>
|
||||
|
||||
<service-activator input-channel="inlineScriptInput">
|
||||
<groovy:script customizer="groovyCustomizer">
|
||||
<groovy:script customizer="groovyCustomizer" variables="date-ref=date">
|
||||
<![CDATA[
|
||||
return "inline-$payload"
|
||||
return "inline-$payload : ${date.format('dd.mm.yyyy')}"
|
||||
]]>
|
||||
</groovy:script>
|
||||
</service-activator>
|
||||
|
||||
<service-activator input-channel="scriptWithoutVariablesInput">
|
||||
<groovy:script>
|
||||
<![CDATA[
|
||||
return "withoutVariables-$payload : ${date.format('dd.mm.yyyy')}"
|
||||
]]>
|
||||
</groovy:script>
|
||||
</service-activator>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:groovy="http://www.springframework.org/schema/integration/groovy"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/groovy http://www.springframework.org/schema/integration/groovy/spring-integration-groovy.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<service-activator input-channel="inlineScriptInput">
|
||||
<groovy:script>
|
||||
<![CDATA[
|
||||
return "inline-$payload-" + "$foo" + " - " + bar + " - " + date
|
||||
]]>
|
||||
<groovy:variable name="foo" value="foo"/>
|
||||
<groovy:variable name="bar" value="bar"/>
|
||||
</groovy:script>
|
||||
</service-activator>
|
||||
|
||||
</beans:beans>
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user