INT-1727 renamed DefaultScriptVariableSource to DefaultScriptVariableGenerator, documented the new feature in reference manual

This commit is contained in:
Oleg Zhurakousky
2011-01-31 14:06:29 -05:00
parent da227f07a9
commit ae823fdb5d
10 changed files with 69 additions and 25 deletions

View File

@@ -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 &lt;variable&gt; 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 &lt;variable&gt; sub-element is mutually exclusive.
You can only use one of another. Also, the <code>script-variable-source</code> and/or &lt;variable&gt; 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">

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -24,7 +24,7 @@ import org.springframework.integration.Message;
* @author Oleg Zhurakousky
*
*/
public interface ScriptVariablesGenerator {
public interface ScriptVariableGenerator {
Map<String, Object> generateScriptVariables(Message<?> message);
}

View File

@@ -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){

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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());

View File

@@ -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");