INT-1507: add control bus to core and groovy
This commit is contained in:
@@ -18,7 +18,6 @@ package org.springframework.integration.aggregator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
@@ -52,7 +51,6 @@ public class ExpressionEvaluatingMessageListProcessor extends AbstractExpression
|
||||
public ExpressionEvaluatingMessageListProcessor(String expression) {
|
||||
try {
|
||||
this.expression = parser.parseExpression(expression);
|
||||
this.getEvaluationContext().addPropertyAccessor(new MapAccessor());
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Failed to parse expression.", e);
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.context.Orderable;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for FactoryBeans that create MessageHandler instances.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Alexander Peters
|
||||
*/
|
||||
abstract class AbstractMessageHandlerFactoryBean implements FactoryBean<MessageHandler>, BeanFactoryAware {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
private volatile MessageHandler handler;
|
||||
|
||||
private volatile Object targetObject;
|
||||
|
||||
private volatile String targetMethodName;
|
||||
|
||||
private volatile Expression expression;
|
||||
|
||||
private volatile MessageChannel outputChannel;
|
||||
|
||||
private volatile Integer order;
|
||||
|
||||
private volatile boolean initialized;
|
||||
|
||||
private final Object initializationMonitor = new Object();
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
public void setTargetObject(Object targetObject) {
|
||||
this.targetObject = targetObject;
|
||||
}
|
||||
|
||||
public void setTargetMethodName(String targetMethodName) {
|
||||
this.targetMethodName = targetMethodName;
|
||||
}
|
||||
|
||||
public void setExpressionString(String expressionString) {
|
||||
this.expression = expressionParser.parseExpression(expressionString);
|
||||
}
|
||||
|
||||
public void setExpression(Expression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public void setOutputChannel(MessageChannel outputChannel) {
|
||||
this.outputChannel = outputChannel;
|
||||
}
|
||||
|
||||
public void setOrder(Integer order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
public MessageHandler getObject() throws Exception {
|
||||
if (this.handler == null) {
|
||||
this.initializeHandler();
|
||||
Assert.notNull(this.handler, "failed to create MessageHandler");
|
||||
if (this.handler instanceof MessageProducer && this.outputChannel != null) {
|
||||
((MessageProducer) this.handler).setOutputChannel(this.outputChannel);
|
||||
}
|
||||
if (this.handler instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handler).setBeanFactory(beanFactory);
|
||||
}
|
||||
if (this.handler instanceof Orderable && this.order != null) {
|
||||
((Orderable) this.handler).setOrder(this.order.intValue());
|
||||
}
|
||||
}
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
public Class<? extends MessageHandler> getObjectType() {
|
||||
if (this.handler != null) {
|
||||
return this.handler.getClass();
|
||||
}
|
||||
return MessageHandler.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initializeHandler() {
|
||||
synchronized (this.initializationMonitor) {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
if (this.targetObject == null) {
|
||||
Assert.isTrue(!StringUtils.hasText(this.targetMethodName),
|
||||
"The target method is only allowed when a target object (ref or inner bean) is also provided.");
|
||||
}
|
||||
if (this.targetObject != null) {
|
||||
Assert.state(this.expression == null,
|
||||
"The 'targetObject' and 'expression' properties are mutually exclusive.");
|
||||
if (this.targetObject instanceof MessageProcessor<?>) {
|
||||
this.handler = this.createMessageProcessingHandler((MessageProcessor<?>) this.targetObject);
|
||||
}
|
||||
else {
|
||||
this.handler = this.createMethodInvokingHandler(this.targetObject, this.targetMethodName);
|
||||
}
|
||||
}
|
||||
else if (this.expression != null) {
|
||||
this.handler = this.createExpressionEvaluatingHandler(this.expression);
|
||||
}
|
||||
else {
|
||||
this.handler = this.createDefaultHandler();
|
||||
}
|
||||
if (this.handler instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handler).setBeanFactory(beanFactory);
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
if (this.handler instanceof InitializingBean) {
|
||||
try {
|
||||
((InitializingBean) this.handler).afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new BeanInitializationException("failed to initialize MessageHandler", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to create the MessageHandler.
|
||||
*/
|
||||
abstract MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName);
|
||||
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support expressions.");
|
||||
}
|
||||
|
||||
<T> MessageHandler createMessageProcessingHandler(MessageProcessor<T> processor) {
|
||||
return this.createMethodInvokingHandler(processor, "processMessage");
|
||||
}
|
||||
|
||||
MessageHandler createDefaultHandler() {
|
||||
throw new IllegalArgumentException(
|
||||
"Exactly one of the 'targetObject' or 'expression' property is required.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T extractTypeIfPossible(Object targetObject, Class<T> expectedType) {
|
||||
if (targetObject == null) {
|
||||
return null;
|
||||
}
|
||||
if (expectedType.isAssignableFrom(targetObject.getClass())) {
|
||||
return (T) targetObject;
|
||||
}
|
||||
if (targetObject instanceof Advised) {
|
||||
TargetSource targetSource = ((Advised) targetObject).getTargetSource();
|
||||
if (targetSource == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return extractTypeIfPossible(targetSource.getTarget(), expectedType);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.context.Orderable;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSimpleMessageHandlerFactoryBean implements
|
||||
FactoryBean<MessageHandler>, BeanFactoryAware {
|
||||
|
||||
private volatile boolean initialized;
|
||||
private final Object initializationMonitor = new Object();
|
||||
private volatile MessageHandler handler;
|
||||
private volatile MessageChannel outputChannel;
|
||||
private volatile Integer order;
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public AbstractSimpleMessageHandlerFactoryBean() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setOutputChannel(MessageChannel outputChannel) {
|
||||
this.outputChannel = outputChannel;
|
||||
}
|
||||
|
||||
public void setOrder(Integer order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
public MessageHandler getObject() throws Exception {
|
||||
if (this.handler == null) {
|
||||
this.handler = this.createHandlerInternal();
|
||||
Assert.notNull(this.handler, "failed to create MessageHandler");
|
||||
if (this.handler instanceof MessageProducer && this.outputChannel != null) {
|
||||
((MessageProducer) this.handler).setOutputChannel(this.outputChannel);
|
||||
}
|
||||
if (this.handler instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.handler).setBeanFactory(beanFactory);
|
||||
}
|
||||
if (this.handler instanceof Orderable && this.order != null) {
|
||||
((Orderable) this.handler).setOrder(this.order.intValue());
|
||||
}
|
||||
}
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
protected final MessageHandler createHandlerInternal() {
|
||||
synchronized (this.initializationMonitor) {
|
||||
if (this.initialized) {
|
||||
// There was a problem when this method was called already
|
||||
return null;
|
||||
}
|
||||
handler = createHandler();
|
||||
if (handler instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) handler).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
if (handler instanceof InitializingBean) {
|
||||
try {
|
||||
((InitializingBean) handler).afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new BeanInitializationException("failed to initialize MessageHandler", e);
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
protected abstract MessageHandler createHandler();
|
||||
|
||||
public Class<? extends MessageHandler> getObjectType() {
|
||||
if (this.handler != null) {
|
||||
return this.handler.getClass();
|
||||
}
|
||||
return MessageHandler.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for FactoryBeans that create MessageHandler instances.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Alexander Peters
|
||||
*/
|
||||
abstract class AbstractStandardMessageHandlerFactoryBean extends AbstractSimpleMessageHandlerFactoryBean {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true,
|
||||
true));
|
||||
|
||||
private volatile Object targetObject;
|
||||
|
||||
private volatile String targetMethodName;
|
||||
|
||||
private volatile Expression expression;
|
||||
|
||||
public void setTargetObject(Object targetObject) {
|
||||
this.targetObject = targetObject;
|
||||
}
|
||||
|
||||
public void setTargetMethodName(String targetMethodName) {
|
||||
this.targetMethodName = targetMethodName;
|
||||
}
|
||||
|
||||
public void setExpressionString(String expressionString) {
|
||||
this.expression = expressionParser.parseExpression(expressionString);
|
||||
}
|
||||
|
||||
public void setExpression(Expression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
protected MessageHandler createHandler() {
|
||||
MessageHandler handler;
|
||||
if (this.targetObject == null) {
|
||||
Assert.isTrue(!StringUtils.hasText(this.targetMethodName),
|
||||
"The target method is only allowed when a target object (ref or inner bean) is also provided.");
|
||||
}
|
||||
if (this.targetObject != null) {
|
||||
Assert.state(this.expression == null,
|
||||
"The 'targetObject' and 'expression' properties are mutually exclusive.");
|
||||
if (this.targetObject instanceof MessageProcessor<?>) {
|
||||
handler = this.createMessageProcessingHandler((MessageProcessor<?>) this.targetObject);
|
||||
} else {
|
||||
handler = this.createMethodInvokingHandler(this.targetObject, this.targetMethodName);
|
||||
}
|
||||
} else if (this.expression != null) {
|
||||
handler = this.createExpressionEvaluatingHandler(this.expression);
|
||||
} else {
|
||||
handler = this.createDefaultHandler();
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to create the MessageHandler.
|
||||
*/
|
||||
abstract MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName);
|
||||
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support expressions.");
|
||||
}
|
||||
|
||||
<T> MessageHandler createMessageProcessingHandler(MessageProcessor<T> processor) {
|
||||
return this.createMethodInvokingHandler(processor, "processMessage");
|
||||
}
|
||||
|
||||
MessageHandler createDefaultHandler() {
|
||||
throw new IllegalArgumentException("Exactly one of the 'targetObject' or 'expression' property is required.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T extractTypeIfPossible(Object targetObject, Class<T> expectedType) {
|
||||
if (targetObject == null) {
|
||||
return null;
|
||||
}
|
||||
if (expectedType.isAssignableFrom(targetObject.getClass())) {
|
||||
return (T) targetObject;
|
||||
}
|
||||
if (targetObject instanceof Advised) {
|
||||
TargetSource targetSource = ((Advised) targetObject).getTargetSource();
|
||||
if (targetSource == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return extractTypeIfPossible(targetSource.getTarget(), expectedType);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FilterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public class FilterFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
|
||||
|
||||
private volatile MessageChannel discardChannel;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ServiceActivatorFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public class ServiceActivatorFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
*/
|
||||
public class SplitterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public class SplitterFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class TransformerFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public class TransformerFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.control.ExpressionPayloadMessageProcessor;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ControlBusParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ExpressionControlBusFactoryBean.class);
|
||||
builder.addConstructorArgValue(getMessageProcessorBeanDefinition(element, parserContext));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "order");
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected BeanMetadataElement getMessageProcessorBeanDefinition(Element element, ParserContext parserContext) {
|
||||
return new RootBeanDefinition(ExpressionPayloadMessageProcessor.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean;
|
||||
import org.springframework.integration.control.ExpressionPayloadMessageProcessor;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.handler.ServiceActivatingHandler;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating {@link MessageHandler} instances to handle a message as a Groovy Script.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ExpressionControlBusFactoryBean extends AbstractSimpleMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
private final ExpressionPayloadMessageProcessor processor;
|
||||
|
||||
public ExpressionControlBusFactoryBean(ExpressionPayloadMessageProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public void setSendTimeout(Long sendTimeout) {
|
||||
this.sendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
protected MessageHandler createHandler() {
|
||||
ServiceActivatingHandler handler = new ServiceActivatingHandler(processor);
|
||||
if (this.sendTimeout != null) {
|
||||
handler.setSendTimeout(this.sendTimeout);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -65,6 +65,7 @@ public class IntegrationNamespaceHandler extends AbstractIntegrationNamespaceHan
|
||||
registerBeanDefinitionParser("channel-interceptor", new GlobalChannelInterceptorParser());
|
||||
registerBeanDefinitionParser("converter", new ConverterParser());
|
||||
registerBeanDefinitionParser("message-history", new MessageHistoryParser());
|
||||
registerBeanDefinitionParser("control-bus", new ControlBusParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.control;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.AbstractMessageProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class ExpressionPayloadMessageProcessor extends AbstractMessageProcessor<Object> {
|
||||
|
||||
public Object processMessage(Message<?> message) {
|
||||
Assert.state(message.getPayload() instanceof String, "Message payload must be a String expression");
|
||||
String expression = (String) message.getPayload();
|
||||
return evaluateExpression(expression, message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.integration.handler;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.integration.Message;
|
||||
@@ -52,7 +51,6 @@ public class ExpressionEvaluatingMessageProcessor<T> extends AbstractMessageProc
|
||||
Assert.notNull(expression, "The expression must not be null");
|
||||
try {
|
||||
this.expression = expression;
|
||||
this.getEvaluationContext().addPropertyAccessor(new MapAccessor());
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
catch (ParseException e) {
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.util;
|
||||
@@ -42,20 +39,18 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware {
|
||||
|
||||
private final BeanFactoryTypeConverter typeConverter = new BeanFactoryTypeConverter();
|
||||
|
||||
|
||||
public AbstractExpressionEvaluator() {
|
||||
this.evaluationContext.setTypeConverter(this.typeConverter);
|
||||
this.evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify a BeanFactory in order to enable resolution via <code>@beanName</code> in the expression.
|
||||
*/
|
||||
public void setBeanFactory(final BeanFactory beanFactory) {
|
||||
if (beanFactory != null) {
|
||||
this.typeConverter.setBeanFactory(beanFactory);
|
||||
this.getEvaluationContext().setBeanResolver(new SimpleBeanResolver(beanFactory));
|
||||
this.evaluationContext.setBeanResolver(new SimpleBeanResolver(beanFactory));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +67,11 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware {
|
||||
protected <T> T evaluateExpression(Expression expression, Message<?> message, Class<T> expectedType) {
|
||||
try {
|
||||
return evaluateExpression(expression, (Object) message, expectedType);
|
||||
}
|
||||
catch (EvaluationException e) {
|
||||
} catch (EvaluationException e) {
|
||||
Throwable cause = e.getCause();
|
||||
throw new MessageHandlingException(message, "Expression evaluation failed: "
|
||||
+ expression.getExpressionString(), cause == null ? e : cause);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
throw new MessageHandlingException(message, "Expression evaluation failed: "
|
||||
+ expression.getExpressionString(), e);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -54,9 +53,9 @@ import org.springframework.integration.annotation.Payload;
|
||||
import org.springframework.integration.annotation.Payloads;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A helper class for processors that invoke a method on a target Object using a combination of message payload(s) and
|
||||
@@ -192,7 +191,6 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
|
||||
"Cannot convert to expected type (" + expectedType + ") from " + method);
|
||||
context.registerMethodFilter(targetType, filter);
|
||||
}
|
||||
context.addPropertyAccessor(new MapAccessor());
|
||||
context.setVariable("target", targetObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -675,10 +675,10 @@
|
||||
<xsd:element name="poller" type="innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
</xsd:choice>
|
||||
<xsd:element name="header" type="headerSubElementType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element name="header" type="headerSubElementType" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="methodInvokingOrExpressionEvaluatingAttributes"/>
|
||||
<xsd:attributeGroup ref="channelAdapterAttributes"/>
|
||||
<xsd:attributeGroup ref="methodInvokingOrExpressionEvaluatingAttributes" />
|
||||
<xsd:attributeGroup ref="channelAdapterAttributes" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -777,7 +777,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression to be evaluated for each triggered execution.
|
||||
The result of the evaluation will be passed as the payload of
|
||||
The result of the evaluation will be
|
||||
passed as the payload of
|
||||
the Message that is sent to the MessageChannel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
@@ -801,7 +802,7 @@
|
||||
<xsd:complexType name="methodInvokingChannelAdapterType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="channelAdapterType">
|
||||
<xsd:attributeGroup ref="methodInvokingOrExpressionEvaluatingAttributes"/>
|
||||
<xsd:attributeGroup ref="methodInvokingOrExpressionEvaluatingAttributes" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -811,7 +812,7 @@
|
||||
<xsd:element name="poller" type="innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element ref="beans:bean" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attributeGroup ref="channelAdapterAttributes"/>
|
||||
<xsd:attributeGroup ref="channelAdapterAttributes" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="service-activator">
|
||||
@@ -835,9 +836,11 @@
|
||||
<xsd:attribute name="requires-reply" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether the service method must return a non-null value. This value will be
|
||||
FALSE by default, but if set to TRUE, a MessageHandlingException will be thrown when
|
||||
the underlying service method (or expression) returns a NULL value.
|
||||
Specify whether the service method must return a non-null value. This value will be
|
||||
FALSE by
|
||||
default, but if set to TRUE, a MessageHandlingException will be thrown when
|
||||
the underlying service method (or
|
||||
expression) returns a NULL value.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -958,7 +961,8 @@
|
||||
delegate when scheduling the sending of delayed Messages. If not
|
||||
provided, the default
|
||||
will use a thread pool of
|
||||
size 1.
|
||||
size
|
||||
1.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -986,7 +990,7 @@
|
||||
<xsd:documentation>
|
||||
Specify whether tasks should be able to complete on shutdown. By
|
||||
default this is 'false'.
|
||||
</xsd:documentation>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
@@ -1089,16 +1093,19 @@
|
||||
<xsd:element name="interval-trigger" type="intervalTriggerType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
NOTE: The 'interval-trigger' sub-element is deprecated as of Spring Integration 2.0 and will be removed in version 2.1.
|
||||
Use one of the interval trigger attributes instead ('fixed-delay' or 'fixed-rate').
|
||||
NOTE: The 'interval-trigger' sub-element is deprecated as of Spring Integration 2.0 and will be
|
||||
removed in version
|
||||
2.1.
|
||||
Use one of the interval trigger attributes instead ('fixed-delay' or 'fixed-rate').
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="cron-trigger" type="cronTriggerType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
NOTE: The 'cron-trigger' sub-element is deprecated as of Spring Integration 2.0 and will be removed in version 2.1.
|
||||
Use the 'cron' attribute instead.
|
||||
NOTE: The 'cron-trigger' sub-element is deprecated as of Spring Integration 2.0 and will be
|
||||
removed in version 2.1.
|
||||
Use the 'cron' attribute instead.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
@@ -1304,7 +1311,8 @@
|
||||
<xsd:documentation>
|
||||
Boolean value to indicate whether this header value should overwrite
|
||||
an existing header
|
||||
value for the same name.
|
||||
value
|
||||
for the same name.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
@@ -1327,13 +1335,15 @@
|
||||
<xsd:documentation>
|
||||
Specify the default boolean value for whether to overwrite existing
|
||||
header values. This will
|
||||
only take effect for
|
||||
only
|
||||
take effect for
|
||||
sub-elements that do not provide their own 'overwrite' attribute. If the
|
||||
'default-overwrite'
|
||||
attribute is not
|
||||
provided, then the specified header values will NOT overwrite any
|
||||
existing ones with the same
|
||||
header names.
|
||||
header
|
||||
names.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
@@ -1359,7 +1369,8 @@
|
||||
<xsd:documentation>
|
||||
Reference to an Object to be invoked for header values.
|
||||
The 'method' attribute is required
|
||||
along with this.
|
||||
along
|
||||
with this.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref" />
|
||||
@@ -1423,7 +1434,7 @@
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="referenceHeaderType">
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="expression" type="innerExpressionType"/>
|
||||
<xsd:element name="expression" type="innerExpressionType" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="value" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
@@ -1628,7 +1639,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a Jackson ObjectMapper instance to be provided optionally
|
||||
if the default ObjectMapper configuration is not desirable.
|
||||
if the default ObjectMapper
|
||||
configuration is not desirable.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -1669,7 +1681,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a Jackson ObjectMapper instance to be provided optionally
|
||||
if the default ObjectMapper configuration is not desirable.
|
||||
if the default ObjectMapper
|
||||
configuration is not desirable.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -1703,7 +1716,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a Serializer instance to convert from an object to a byte array.
|
||||
This is optional. The default will use standard Java serialization.
|
||||
This is optional.
|
||||
The default will use standard Java serialization.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -1737,7 +1751,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a Deserializer instance to convert from a byte array to an object.
|
||||
This is optional. The default will use standard Java deserialization.
|
||||
This is optional.
|
||||
The default will use standard Java deserialization.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -1752,7 +1767,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a Transformer that stores a Message and returns a new Message whose
|
||||
payload is the id of the stored Message.
|
||||
payload is the id of
|
||||
the stored Message.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
@@ -1761,7 +1777,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a Transformer that accepts a Message whose payload is a UUID and
|
||||
retrieves the Message associated with that id from a MessageStore if
|
||||
retrieves the Message
|
||||
associated with that id from a MessageStore if
|
||||
available (else null).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
@@ -1775,7 +1792,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to the MessageStore to be used by this Claim Check transformer.
|
||||
If not specified, the default reference will be to a bean named 'messageStore'.
|
||||
If not specified, the
|
||||
default reference will be to a bean named 'messageStore'.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -1882,9 +1900,11 @@ Name of the header whose value to use.
|
||||
<xsd:attribute name="selector-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
An expression to be evaluated to determine if this recipient should be included in the recipient
|
||||
An expression to be evaluated to determine if this recipient should be included in the
|
||||
recipient
|
||||
list for a given input Message. The evaluation result of the expression must be a boolean.
|
||||
If this attribute is not defined, the channel will always be among the list of recipients.
|
||||
If this
|
||||
attribute is not defined, the channel will always be among the list of recipients.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -2112,18 +2132,21 @@ Name of the header whose value to use.
|
||||
<xsd:attribute name="requires-reply" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether the splitter method must return a non-null value. This value will be
|
||||
FALSE by default, but if set to TRUE, a MessageHandlingException will be thrown when
|
||||
the underlying service method (or expression) returns a NULL value.
|
||||
Specify whether the splitter method must return a non-null value. This value will be
|
||||
FALSE by
|
||||
default, but if set to TRUE, a MessageHandlingException will be thrown when
|
||||
the underlying service method (or
|
||||
expression) returns a NULL value.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="apply-sequence" type="xsd:boolean" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Set this flag to false to prevent adding sequence related headers in this splitter. This
|
||||
can be convenient in cases where the set sequence numbers conflict with downstream custom
|
||||
aggregations.
|
||||
Set this flag to false to prevent adding sequence related headers in this splitter. This
|
||||
can be
|
||||
convenient in cases where the set sequence numbers conflict with downstream custom
|
||||
aggregations.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -2154,7 +2177,7 @@ Name of the header whose value to use.
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
A SpEL expression to be evaluated against the input message list as its root object.
|
||||
</xsd:documentation>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
@@ -2224,11 +2247,13 @@ Name of the header whose value to use.
|
||||
<xsd:documentation>
|
||||
Reference to a MessageGroupStore for holding
|
||||
state in between message processing. The default
|
||||
is to use a
|
||||
is
|
||||
to use a
|
||||
volatile in-memory store, which means that unprocessed messages
|
||||
will be lost if the
|
||||
JVM exits. To
|
||||
customize the expiry of incomplete message groups
|
||||
customize
|
||||
the expiry of incomplete message groups
|
||||
configure the message store.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
@@ -2264,8 +2289,9 @@ Name of the header whose value to use.
|
||||
<xsd:attribute name="comparator" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Comparator for messages used to sort the sequence when released. Defaults to comparing
|
||||
the sequence number header.
|
||||
Comparator for messages used to sort the sequence when released. Defaults to comparing
|
||||
the
|
||||
sequence number header.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
@@ -2405,7 +2431,7 @@ Name of the header whose value to use.
|
||||
<xsd:extension base="handlerEndpointType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="2">
|
||||
<xsd:element name="poller" type="innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="expression" type="innerExpressionType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="expression" type="innerExpressionType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="expression" type="xsd:string">
|
||||
@@ -2435,7 +2461,7 @@ Name of the header whose value to use.
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.expression.ExpressionSource" />
|
||||
</tool:annotation>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -2582,14 +2608,31 @@ only be one Message History writer per ApplicationContext hierarchy.
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="tracked-components" type="xsd:string" default="*">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The list of component name patterns you want to track (e.g., tracked-components="inputChannel, out*, *Channel, *Service")
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="control-bus">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Control bus that accepts messages in the form of Groovy scripts. The scripts should be provided as
|
||||
String payloads
|
||||
in incoming messages. Scripts can refer to beans in the context using the standard @beanName
|
||||
convention.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:all minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="poller" type="innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attributeGroup ref="inputOutputChannelGroup" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<channel id="input">
|
||||
<queue />
|
||||
</channel>
|
||||
|
||||
<channel id="output">
|
||||
<queue />
|
||||
</channel>
|
||||
|
||||
<control-bus input-channel="input" output-channel="output">
|
||||
<poller fixed-rate="100" />
|
||||
</control-bus>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.config.xml.ControlBusTests$Service" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ControlBusExplicitPollerTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
@Test
|
||||
public void testDefaultEvaluationContext() {
|
||||
Message<?> message = MessageBuilder.withPayload("@service.convert('aardvark')+headers.foo").setHeader("foo", "bar").build();
|
||||
this.input.send(message);
|
||||
assertEquals("catbar", output.receive(1000).getPayload());
|
||||
assertNull(output.receive(0));
|
||||
}
|
||||
|
||||
public static class Service {
|
||||
public String convert(String input) {
|
||||
return "cat";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<channel id="input">
|
||||
<queue />
|
||||
</channel>
|
||||
|
||||
<channel id="output">
|
||||
<queue />
|
||||
</channel>
|
||||
|
||||
<control-bus input-channel="input" output-channel="output"/>
|
||||
|
||||
<poller default="true" fixed-rate="100"/>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.config.xml.ControlBusTests$Service" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ControlBusPollerTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
@Test
|
||||
public void testDefaultEvaluationContext() {
|
||||
Message<?> message = MessageBuilder.withPayload("@service.convert('aardvark')+headers.foo").setHeader("foo", "bar").build();
|
||||
this.input.send(message);
|
||||
assertEquals("catbar", output.receive(1000).getPayload());
|
||||
assertNull(output.receive(0));
|
||||
}
|
||||
|
||||
public static class Service {
|
||||
public String convert(String input) {
|
||||
return "cat";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<channel id="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<control-bus input-channel="input" output-channel="output" send-timeout="100" order="1" auto-startup="true"/>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.config.xml.ControlBusTests$Service" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ControlBusTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
@Test
|
||||
public void testDefaultEvaluationContext() {
|
||||
Message<?> message = MessageBuilder.withPayload("@service.convert('aardvark')+headers.foo").setHeader("foo", "bar").build();
|
||||
this.input.send(message);
|
||||
assertEquals("catbar", output.receive(0).getPayload());
|
||||
assertNull(output.receive(0));
|
||||
}
|
||||
|
||||
public static class Service {
|
||||
public String convert(String input) {
|
||||
return "cat";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.groovy;
|
||||
|
||||
import groovy.lang.Binding;
|
||||
import groovy.lang.GroovyObject;
|
||||
import groovy.lang.Script;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
|
||||
|
||||
public class BeanFactoryContextBindingCustomizer implements GroovyObjectCustomizer, BeanFactoryAware {
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
public BeanFactoryContextBindingCustomizer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BeanFactoryContextBindingCustomizer(BeanFactory beanFactory) {
|
||||
setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory instanceof ListableBeanFactory ? (ListableBeanFactory) beanFactory : null;
|
||||
}
|
||||
|
||||
public void customize(GroovyObject goo) {
|
||||
if (beanFactory != null) {
|
||||
Binding binding = ((Script) goo).getBinding();
|
||||
for (String name : beanFactory.getBeanDefinitionNames()) {
|
||||
binding.setVariable(name, beanFactory.getBean(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import java.util.Map;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.AbstractScriptExecutingMessageProcessor;
|
||||
import org.springframework.scripting.ScriptSource;
|
||||
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
|
||||
import org.springframework.scripting.groovy.GroovyScriptFactory;
|
||||
import org.springframework.scripting.support.StaticScriptSource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -31,14 +32,18 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class GroovyScriptPayloadMessageProcessor extends AbstractScriptExecutingMessageProcessor<Object> {
|
||||
|
||||
private final Map<String, ?> map;
|
||||
private final GroovyObjectCustomizer customizer;
|
||||
|
||||
public GroovyScriptPayloadMessageProcessor() {
|
||||
this(null);
|
||||
this((GroovyObjectCustomizer)null);
|
||||
}
|
||||
|
||||
public GroovyScriptPayloadMessageProcessor(Map<String, ?> map) {
|
||||
this.map = map;
|
||||
this(new MapContextBindingCustomizer(map));
|
||||
}
|
||||
|
||||
public GroovyScriptPayloadMessageProcessor(GroovyObjectCustomizer customizer) {
|
||||
this.customizer = customizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,7 +57,7 @@ public class GroovyScriptPayloadMessageProcessor extends AbstractScriptExecuting
|
||||
@Override
|
||||
protected Object executeScript(ScriptSource scriptSource, Message<?> message) throws Exception {
|
||||
// Keeping everything local prevents PermGen (class instances) leaks...
|
||||
MessageContextBindingCustomizer bindingCustomizer = new MessageContextBindingCustomizer(this.map);
|
||||
MessageContextBindingCustomizer bindingCustomizer = new MessageContextBindingCustomizer(this.customizer);
|
||||
bindingCustomizer.setMessage(message);
|
||||
GroovyScriptFactory scriptFactory = new GroovyScriptFactory(this.getClass().getSimpleName(), bindingCustomizer);
|
||||
Object result = scriptFactory.getScriptedObject(scriptSource, null);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.groovy;
|
||||
|
||||
import groovy.lang.Binding;
|
||||
import groovy.lang.GroovyObject;
|
||||
import groovy.lang.Script;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class MapContextBindingCustomizer implements GroovyObjectCustomizer {
|
||||
|
||||
private final Map<String, ?> map;
|
||||
|
||||
public MapContextBindingCustomizer(Map<String, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void customize(GroovyObject goo) {
|
||||
Assert.state(goo instanceof Script, "Expected a Script");
|
||||
if (this.map != null) {
|
||||
Binding binding = ((Script) goo).getBinding();
|
||||
for (String key : map.keySet()) {
|
||||
binding.setVariable(key, map.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,25 +63,4 @@ class MessageContextBindingCustomizer implements GroovyObjectCustomizer {
|
||||
binding.setVariable("headers", this.message.getHeaders());
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapContextBindingCustomizer implements GroovyObjectCustomizer {
|
||||
|
||||
private final Map<String, ?> map;
|
||||
|
||||
public MapContextBindingCustomizer(Map<String, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void customize(GroovyObject goo) {
|
||||
Assert.state(goo instanceof Script, "Expected a Script");
|
||||
if (this.map != null) {
|
||||
Binding binding = ((Script) goo).getBinding();
|
||||
for (String key : map.keySet()) {
|
||||
binding.setVariable(key, map.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.groovy.config;
|
||||
|
||||
import org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.groovy.GroovyScriptPayloadMessageProcessor;
|
||||
import org.springframework.integration.handler.ServiceActivatingHandler;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating {@link MessageHandler} instances to handle a message as a Groovy Script.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class GroovyControlBusFactoryBean extends AbstractSimpleMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
private final GroovyScriptPayloadMessageProcessor processor;
|
||||
|
||||
public GroovyControlBusFactoryBean(GroovyScriptPayloadMessageProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
public void setSendTimeout(Long sendTimeout) {
|
||||
this.sendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
protected MessageHandler createHandler() {
|
||||
return this.configureHandler(new ServiceActivatingHandler(processor));
|
||||
}
|
||||
|
||||
private ServiceActivatingHandler configureHandler(ServiceActivatingHandler handler) {
|
||||
if (this.sendTimeout != null) {
|
||||
handler.setSendTimeout(this.sendTimeout);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.groovy.config;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.groovy.BeanFactoryContextBindingCustomizer;
|
||||
import org.springframework.integration.groovy.GroovyScriptPayloadMessageProcessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class GroovyControlBusParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
private static final String CUSTOMIZER_ATTRIBUTE = "customizer";
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(GroovyControlBusFactoryBean.class);
|
||||
builder.addConstructorArgValue(getMessageProcessorBeanDefinition(element, parserContext));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "order");
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected BeanMetadataElement getMessageProcessorBeanDefinition(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(GroovyScriptPayloadMessageProcessor.class);
|
||||
String customizerAttr = element.getAttribute(CUSTOMIZER_ATTRIBUTE);
|
||||
if (StringUtils.hasText(customizerAttr)) {
|
||||
builder.addConstructorArgReference(customizerAttr.trim());
|
||||
} else {
|
||||
builder.addConstructorArgValue(new RootBeanDefinition(BeanFactoryContextBindingCustomizer.class));
|
||||
}
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public class GroovyNamespaceHandler extends AbstractIntegrationNamespaceHandler
|
||||
|
||||
public void init() {
|
||||
this.registerBeanDefinitionParser("script", new GroovyScriptParser());
|
||||
this.registerBeanDefinitionParser("control-bus", new GroovyControlBusParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/groovy"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/groovy"
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/groovy" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration" targetNamespace="http://www.springframework.org/schema/integration/groovy"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration" schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
|
||||
|
||||
<xsd:element name="script">
|
||||
<xsd:annotation>
|
||||
@@ -23,7 +20,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Resource location path for the Script. Either this or an inline script
|
||||
as body text should be provided, but not both.
|
||||
as body text should be
|
||||
provided, but not both.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -31,7 +29,8 @@
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Refresh delay for the script contents if specified as a resource
|
||||
location (defaults to never refresh).
|
||||
location (defaults to never
|
||||
refresh).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -40,4 +39,34 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="control-bus">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Control bus that accepts messages in the form of Groovy scripts. The scripts should be provided as
|
||||
String payloads
|
||||
in incoming messages
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:all minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="poller" type="integration:innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attribute name="customizer" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
A reference to a static GroovyObjectCustomizer that will be used to modify the Groovy scripts
|
||||
sent to the control channel. By default a customizer is used that simply exposes all beans in the application
|
||||
context by name in the scripts.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:expected-type type="org.springframework.scripting.groovy.GroovyObjectCustomizer" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:inputOutputChannelGroup" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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">
|
||||
|
||||
<channel id="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<groovy:control-bus input-channel="input" output-channel="output" send-timeout="100" order="1" auto-startup="true"/>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.groovy.config.GroovyControlBusTests$Service" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.groovy.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class GroovyControlBusTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
@Test
|
||||
public void testOperationOfControlBus() { // long is > 3
|
||||
Message<?> message = MessageBuilder.withPayload("def result = service.convert('aardvark'); def foo = headers.foo; result+foo").setHeader("foo", "bar").build();
|
||||
this.input.send(message);
|
||||
assertEquals("catbar", output.receive(0).getPayload());
|
||||
assertNull(output.receive(0));
|
||||
}
|
||||
|
||||
public static class Service {
|
||||
public String convert(String input) {
|
||||
return "cat";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user