INT-1727 added namespace support for script-variable-source

This commit is contained in:
Oleg Zhurakousky
2011-01-27 16:46:59 -05:00
parent c3db043334
commit e9b85bca18
6 changed files with 129 additions and 29 deletions

View File

@@ -22,6 +22,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.integration.Message;
import org.springframework.util.CollectionUtils;
@@ -58,8 +59,9 @@ public class DefaultScriptVariableSource implements BeanFactoryAware, ScriptVari
if (!CollectionUtils.isEmpty(variableMap)){
for (String variableName : variableMap.keySet()) {
Object variableValue = variableMap.get(variableName);
if (variableValue == null){
scriptVariables.put(variableName, this.beanFactory.getBean(variableName));
if (variableValue instanceof RuntimeBeanReference){
String beanName = ((RuntimeBeanReference)variableValue).getBeanName();
scriptVariables.put(variableName, this.beanFactory.getBean(beanName));
}
else {
scriptVariables.put(variableName, variableValue);

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.w3c.dom.Element;
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.xml.AbstractSingleBeanDefinitionParser;
@@ -66,6 +67,13 @@ public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser {
return;
}
String scriptVariableSourceName = element.getAttribute("script-variable-source");
if (StringUtils.hasText(scriptVariableSourceName) && variableElements.size() > 0){
parserContext.getReaderContext().error("'script-variable-source' and 'variable' sub-element are mutualy exclusive. Must use one or the other.", element);
return;
}
if (StringUtils.hasText(scriptLocation)){
builder.addConstructorArgValue(this.resolveScriptLocation(element, parserContext.getReaderContext(), scriptLocation));
}
@@ -73,33 +81,34 @@ public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser {
builder.addConstructorArgValue(new StaticScriptSource(scriptText, "groovy.lang.Script"));
}
BeanDefinitionBuilder scriptVariableSource =
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.integration.groovy.DefaultScriptVariableSource");
String name =
BeanDefinitionReaderUtils.registerWithGeneratedName(scriptVariableSource.getBeanDefinition(), parserContext.getRegistry());
builder.addConstructorArgReference(name);
Map<String, Object> variableMap = new HashMap<String, Object>();
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(scriptVariableSourceName)){
BeanDefinitionBuilder scriptVariableSourceBuilder =
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.integration.groovy.DefaultScriptVariableSource");
Map<String, Object> variableMap = new HashMap<String, Object>();
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));
}
}
if (StringUtils.hasText(variableValue)){
variableMap.put(variableName, variableValue);
}
else {
// 'null' means that the value will be retrieved from the AC
variableMap.put(variableName, null);
if (!CollectionUtils.isEmpty(variableMap)){
scriptVariableSourceBuilder.addConstructorArgValue(variableMap);
}
scriptVariableSourceName =
BeanDefinitionReaderUtils.registerWithGeneratedName(scriptVariableSourceBuilder.getBeanDefinition(), parserContext.getRegistry());
}
if (!CollectionUtils.isEmpty(variableMap)){
scriptVariableSource.addConstructorArgValue(variableMap);
}
builder.addConstructorArgReference(scriptVariableSourceName);
}
private Object resolveScriptLocation(Element element, XmlReaderContext readerContext, String scriptLocation) {

View File

@@ -17,24 +17,30 @@
<xsd:sequence>
<xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Allows you to define custom Groovy variable bindings. The use of this sub-element is mutually
exclusive with 'script-variable-source' attribute
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Name of the groovy binding variable
Name of the Groovy binding variable
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="value" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Value of the groovy binding variable
Value of the Groovy binding variable
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Value of the groovy binding variable pointing to a bean reference
Value of the Groovy binding variable pointing to a bean reference
</xsd:documentation>
<xsd:appinfo>
<tool:expected-type type="java.lang.Object"/>
@@ -53,6 +59,17 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="script-variable-source">
<xsd:annotation>
<xsd:documentation>
Reference to the ScriptVariableSource bean. This attribute is mutually
exclusive with 'variable' sub-element
</xsd:documentation>
<xsd:appinfo>
<tool:expected-type type="rg.springframework.integration.groovy.ScriptVariableSource"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="refresh-check-delay">
<xsd:annotation>
<xsd:documentation>

View File

@@ -17,6 +17,15 @@
<groovy:variable name="date" ref="date"/>
</groovy:script>
</service-activator>
<service-activator input-channel="withScriptVariableSource">
<groovy:script location="org/springframework/integration/groovy/config/GroovyServiceActivatorTests.groovy"
script-variable-source="scriptVarSource"/>
</service-activator>
<beans:bean id="scriptVarSource"
class="org.springframework.integration.groovy.config.GroovyServiceActivatorTests.SampleScriptVariSource"/>
<service-activator input-channel="inlineScriptInput">
<groovy:script>

View File

@@ -0,0 +1,21 @@
<?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-2.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<service-activator input-channel="withScriptVariableSource">
<groovy:script location="org/springframework/integration/groovy/config/GroovyServiceActivatorTests.groovy"
script-variable-source="scriptVarSource">
<groovy:variable name="foo" value="foo"/>
<groovy:variable name="bar" value="bar"/>
</groovy:script>
</service-activator>
</beans:beans>

View File

@@ -21,6 +21,9 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Date;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,6 +33,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.DefaultScriptVariableSource;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -47,6 +51,9 @@ public class GroovyServiceActivatorTests {
@Autowired
private MessageChannel inlineScriptInput;
@Autowired
private MessageChannel withScriptVariableSource;
@Test
@@ -71,6 +78,29 @@ public class GroovyServiceActivatorTests {
assertNull(replyChannel.receive(0));
}
@Test
public void withScriptVariableSource() throws Exception{
QueueChannel replyChannel = new QueueChannel();
replyChannel.setBeanName("returnAddress");
for (int i = 1; i <= 3; i++) {
Message<?> message = MessageBuilder.withPayload("test-" + i).setReplyChannel(replyChannel).build();
this.withScriptVariableSource.send(message);
Thread.sleep(1000);
}
String value1 = (String) replyChannel.receive(0).getPayload();
String value2 = (String) replyChannel.receive(0).getPayload();
String value3 = (String) replyChannel.receive(0).getPayload();
assertTrue(value1.startsWith("groovy-test-1-foo - bar"));
assertTrue(value2.startsWith("groovy-test-2-foo - bar"));
assertTrue(value3.startsWith("groovy-test-3-foo - bar"));
// becouse 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)));
assertNull(replyChannel.receive(0));
}
@Test
public void inlineScript() throws Exception{
@@ -90,5 +120,17 @@ public class GroovyServiceActivatorTests {
public void inlineScriptAndVariables() throws Exception{
new ClassPathXmlApplicationContext("GroovyServiceActivatorTests-fail-context.xml", this.getClass());
}
@Test(expected=BeanDefinitionParsingException.class)
public void variablesAndScriptVariableSource() throws Exception{
new ClassPathXmlApplicationContext("GroovyServiceActivatorTests-fail-withsource-context.xml", this.getClass());
}
public static class SampleScriptVariSource extends DefaultScriptVariableSource{
protected void doResolveScriptVariables(Map<String, Object> variables){
variables.put("foo", "foo");
variables.put("bar", "bar");
variables.put("date", new Date());
}
}
}