INT-1727 renamed DefaultScriptVariableSource to DefaultScriptVariableGenerator, documented the new feature in reference manual
This commit is contained in:
@@ -74,6 +74,50 @@
|
||||
In this case, the "dynamic" aspect of Groovy is not being used, but the syntax
|
||||
might be the primary reason that Groovy has been chosen in the first place.
|
||||
<important>Inline defined scripts can not be reloaded.</important></para>
|
||||
|
||||
<para><emphasis>Custom bindings</emphasis> </para>
|
||||
|
||||
<para>
|
||||
You already know that by default, 'payload' and 'headers' will be bound as Groovy binding variables.
|
||||
|
||||
However, some times in order to take the most out of Groovy you may want to customize Groovy bindings
|
||||
(e.g., include extra variables pointing to some scalar values or bind some beans as variables etc.)
|
||||
To support this requirement we have defined a simple strategy ScriptVariableGenerator.
|
||||
<programlisting language="java"><![CDATA[public interface ScriptVariableGenerator {
|
||||
|
||||
Map<String, Object> generateScriptVariables(Message<?> message);
|
||||
|
||||
}]]></programlisting>
|
||||
|
||||
As you can see the only method that needs to be implemented is <code>generateScriptVariables(Message)</code> which takes
|
||||
Message as an argument (allowing you to use data available in Message payload/headers) and returns the Map of variables
|
||||
that will be bound as Groovy bindings. This method will be called every time the script is executed. We also provide
|
||||
default implementation and namespace based configuration for simple bindings via <variable> sub-element (see below):
|
||||
<programlisting language="xml"><![CDATA[<groovy:script location="foo/bar/MyScript.groovy">
|
||||
<groovy:variable name="foo" value="foo"/>
|
||||
<groovy:variable name="bar" value="bar"/>
|
||||
<groovy:variable name="date" ref="date"/>
|
||||
</groovy:script>]]></programlisting>
|
||||
|
||||
As you can see similar to other constructs in Spring, when setting binding variables you can either set scalar values
|
||||
or reference another bean in the Application Context.
|
||||
</para>
|
||||
<para>
|
||||
However if you need more dynamics with regard to how a particular variable is generated then all you need to do is
|
||||
provide your own implementation of ScriptVariableGenerator and inject it via <code>script-variable-source</code> atribute:
|
||||
<programlisting language="xml"><![CDATA[<groovy:script location="foo/bar/MyScript.groovy"
|
||||
script-variable-source="scriptVarSource"/>
|
||||
<bean id="scriptVariabelSource" class="foo.bar.MyScriptVariableGeneratore"/>]]></programlisting>
|
||||
|
||||
<important>
|
||||
|
||||
Remember that <code>script-variable-source</code> and use of <variable> sub-element is mutually exclusive.
|
||||
You can only use one of another. Also, the <code>script-variable-source</code> and/or <variable> sub-elements can
|
||||
not be used when using inline script, only when pointing to the script via <code>location</code> attribute.
|
||||
|
||||
</important>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="groovy-control-bus">
|
||||
|
||||
@@ -29,17 +29,17 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0.2
|
||||
*/
|
||||
class DefaultScriptVariableSource implements BeanFactoryAware, ScriptVariablesGenerator {
|
||||
class DefaultScriptVariableGenerator implements BeanFactoryAware, ScriptVariableGenerator {
|
||||
|
||||
protected volatile ListableBeanFactory beanFactory;
|
||||
|
||||
private volatile Map<String, Object> variableMap;
|
||||
|
||||
public DefaultScriptVariableSource(){
|
||||
public DefaultScriptVariableGenerator(){
|
||||
this(null);
|
||||
}
|
||||
|
||||
public DefaultScriptVariableSource(Map<String, Object> variableMap){
|
||||
public DefaultScriptVariableGenerator(Map<String, Object> variableMap){
|
||||
this.variableMap = variableMap;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class GroovyCommandMessageProcessor extends AbstractScriptExecutingMessageProcessor<Object> {
|
||||
|
||||
private final ScriptVariablesGenerator scriptVariableSource;
|
||||
private final ScriptVariableGenerator scriptVariableSource;
|
||||
|
||||
public GroovyCommandMessageProcessor(ScriptVariablesGenerator scriptVariableSource) {
|
||||
public GroovyCommandMessageProcessor(ScriptVariableGenerator scriptVariableSource) {
|
||||
this.scriptVariableSource = scriptVariableSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,16 +38,16 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
|
||||
|
||||
private volatile ScriptSource scriptSource;
|
||||
|
||||
protected final ScriptVariablesGenerator scriptVariableSource;
|
||||
protected final ScriptVariableGenerator scriptVariableSource;
|
||||
|
||||
/**
|
||||
* Create a processor for the given {@link ScriptSource}.
|
||||
*/
|
||||
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource) {
|
||||
this(scriptSource, new DefaultScriptVariableSource());
|
||||
this(scriptSource, new DefaultScriptVariableGenerator());
|
||||
}
|
||||
|
||||
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource, ScriptVariablesGenerator scriptVariableSource) {
|
||||
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource, ScriptVariableGenerator scriptVariableSource) {
|
||||
this.scriptSource = scriptSource;
|
||||
this.scriptVariableSource = scriptVariableSource;
|
||||
this.scriptFactory = new GroovyScriptFactory(this.getClass().getSimpleName(), this.customizer);
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.integration.Message;
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public interface ScriptVariablesGenerator {
|
||||
public interface ScriptVariableGenerator {
|
||||
|
||||
Map<String, Object> generateScriptVariables(Message<?> message);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import org.springframework.integration.Message;
|
||||
import org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.groovy.GroovyCommandMessageProcessor;
|
||||
import org.springframework.integration.groovy.ScriptVariablesGenerator;
|
||||
import org.springframework.integration.groovy.ScriptVariableGenerator;
|
||||
import org.springframework.integration.handler.ServiceActivatingHandler;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.util.CustomizableThreadCreator;
|
||||
@@ -58,7 +58,7 @@ public class GroovyControlBusFactoryBean extends AbstractSimpleMessageHandlerFac
|
||||
return handler;
|
||||
}
|
||||
|
||||
private class ManagedBeansScriptVariableSource implements ScriptVariablesGenerator {
|
||||
private class ManagedBeansScriptVariableSource implements ScriptVariableGenerator {
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
public ManagedBeansScriptVariableSource(BeanFactory beanFactory){
|
||||
|
||||
@@ -81,7 +81,7 @@ public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
if (!StringUtils.hasText(scriptVariableSourceName)){
|
||||
BeanDefinitionBuilder scriptVariableSourceBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.integration.groovy.DefaultScriptVariableSource");
|
||||
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.integration.groovy.DefaultScriptVariableGenerator");
|
||||
|
||||
ManagedMap<String, Object> variableMap = new ManagedMap<String, Object>();
|
||||
for (Element childElement : variableElements) {
|
||||
|
||||
@@ -59,7 +59,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar"+count).build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableSource());
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableGenerator());
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("payload is foo, header is bar"+count, result.toString());
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
Object result = null;
|
||||
class CustomScriptVariableSource implements ScriptVariablesGenerator {
|
||||
class CustomScriptVariableSource implements ScriptVariableGenerator {
|
||||
public Map<String, Object> generateScriptVariables(Message<?> message) {
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
variables.put("date", System.nanoTime());
|
||||
@@ -82,7 +82,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ScriptVariablesGenerator scriptVariableSource = new CustomScriptVariableSource();
|
||||
ScriptVariableGenerator scriptVariableSource = new CustomScriptVariableSource();
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, scriptVariableSource);
|
||||
Object newResult = processor.processMessage(message);
|
||||
assertFalse(newResult.equals(result)); // make sure that we get different nanotime verifying that resolveScriptVariables() is invoked
|
||||
@@ -106,7 +106,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar").build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableSource());
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableGenerator());
|
||||
Thread.sleep(20L);
|
||||
resource.setScript("return \"payload is $payload\"");
|
||||
Object result = processor.processMessage(message);
|
||||
@@ -119,7 +119,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar").build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new RefreshableResourceScriptSource(resource, 1000L);
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableSource());
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableGenerator());
|
||||
// should be the original script
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("payload is foo, header is bar", result.toString());
|
||||
@@ -143,7 +143,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar").build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new RefreshableResourceScriptSource(resource, -1L);
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableSource());
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableGenerator());
|
||||
// process with the first script
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("payload is foo, header is bar", result.toString());
|
||||
@@ -160,7 +160,7 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar").build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new RefreshableResourceScriptSource(resource, 0);
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableSource());
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, new DefaultScriptVariableGenerator());
|
||||
// process with the first script
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("payload is foo, header is bar", result.toString());
|
||||
|
||||
@@ -44,14 +44,14 @@ public class GroovyScriptPayloadMessageProcessorTests {
|
||||
public void testSimpleExecution() throws Exception {
|
||||
int count = countHolder.getAndIncrement();
|
||||
Message<?> message = MessageBuilder.withPayload("headers.foo" + count).setHeader("foo" + count, "bar").build();
|
||||
processor = new GroovyCommandMessageProcessor(new DefaultScriptVariableSource());
|
||||
processor = new GroovyCommandMessageProcessor(new DefaultScriptVariableGenerator());
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("bar", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubleExecutionWithNewScript() throws Exception {
|
||||
processor = new GroovyCommandMessageProcessor(new DefaultScriptVariableSource());
|
||||
processor = new GroovyCommandMessageProcessor(new DefaultScriptVariableGenerator());
|
||||
Message<?> message = MessageBuilder.withPayload("headers.foo").setHeader("foo", "bar").build();
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("bar", result.toString());
|
||||
@@ -64,8 +64,8 @@ public class GroovyScriptPayloadMessageProcessorTests {
|
||||
public void testSimpleExecutionWithContext() throws Exception {
|
||||
Message<?> message = MessageBuilder.withPayload("\"spam is $spam foo is $headers.foo\"")
|
||||
.setHeader("foo", "bar").build();
|
||||
ScriptVariablesGenerator scriptVariableSource =
|
||||
new DefaultScriptVariableSource(Collections.singletonMap("spam",(Object)"bucket"));
|
||||
ScriptVariableGenerator scriptVariableSource =
|
||||
new DefaultScriptVariableGenerator(Collections.singletonMap("spam",(Object)"bucket"));
|
||||
MessageProcessor<Object> processor = new GroovyCommandMessageProcessor(scriptVariableSource);
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("spam is bucket foo is bar", result.toString());
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.groovy.ScriptVariablesGenerator;
|
||||
import org.springframework.integration.groovy.ScriptVariableGenerator;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -128,7 +128,7 @@ public class GroovyServiceActivatorTests {
|
||||
new ClassPathXmlApplicationContext("GroovyServiceActivatorTests-fail-withsource-context.xml", this.getClass());
|
||||
}
|
||||
|
||||
public static class SampleScriptVariSource implements ScriptVariablesGenerator{
|
||||
public static class SampleScriptVariSource implements ScriptVariableGenerator{
|
||||
public Map<String, Object> generateScriptVariables(Message<?> message) {
|
||||
Map<String, Object> variables = new HashMap<String, Object>();
|
||||
variables.put("foo", "foo");
|
||||
|
||||
Reference in New Issue
Block a user