diff --git a/build.gradle b/build.gradle
index 79e81a0f62..6b6e68e5fa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -57,6 +57,7 @@ subprojects { subproject ->
springSecurityVersion = '3.1.0.RELEASE'
springSocialTwitterVersion = '1.0.1.RELEASE'
springWsVersion = '2.1.0.RELEASE'
+ springRetryVersion = '1.0.2.RELEASE'
}
eclipse {
@@ -176,6 +177,7 @@ project('spring-integration-core') {
compile "org.springframework:spring-aop:$springVersion"
compile "org.springframework:spring-context:$springVersion"
compile "org.springframework:spring-tx:$springVersion"
+ compile "org.springframework.retry:spring-retry:$springRetryVersion"
compile("org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion", optional)
testCompile "org.aspectj:aspectjrt:$aspectjVersion"
testCompile "org.aspectj:aspectjweaver:$aspectjVersion"
@@ -185,6 +187,7 @@ project('spring-integration-core') {
importTemplate += [
'org.springframework.*;version="[3.1.1, 4.0.0)"',
'org.springframework.transaction;version="[3.1.1, 4.0.0)";resolution:=optional',
+ 'org.springframework.retry;version="[1.0.2, 2.0.0)"',
'org.apache.commons.logging;version="[1.1.1, 2.0.0)"',
'org.aopalliance.*;version="[1.0.0, 2.0.0)"',
'org.codehaus.jackson.*;version="[1.0.0, 2.0.0)";resolution:=optional',
diff --git a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.2.xsd b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.2.xsd
index 9871a16ea4..67612af0e8 100644
--- a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.2.xsd
+++ b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-2.2.xsd
@@ -368,6 +368,9 @@
Base type for the 'outbound-channel-adapter' and 'outbound-gateway' elements.
+
+
+
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml
index 056f6c7bdd..ceaa5e15f4 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests-context.xml
@@ -9,7 +9,11 @@
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
+
+
+
+
+
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java
index c9673f071d..9cad51a2c6 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundChannelAdapterParserTests.java
@@ -20,12 +20,13 @@ import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
-import java.util.List;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.junit.Test;
@@ -48,10 +49,12 @@ import org.springframework.integration.amqp.AmqpHeaders;
import org.springframework.integration.amqp.outbound.AmqpOutboundEndpoint;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.NullChannel;
+import org.springframework.integration.context.NamedComponent;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
-import org.springframework.integration.handler.MessageHandlerChain;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
@@ -72,6 +75,8 @@ import com.rabbitmq.client.Channel;
@RunWith(SpringJUnit4ClassRunner.class)
public class AmqpOutboundChannelAdapterParserTests {
+ private static volatile int adviceCalled;
+
@Autowired
private ApplicationContext context;
@@ -82,16 +87,18 @@ public class AmqpOutboundChannelAdapterParserTests {
assertEquals(DirectChannel.class, channel.getClass());
assertEquals(EventDrivenConsumer.class, adapter.getClass());
MessageHandler handler = TestUtils.getPropertyValue(adapter, "handler", MessageHandler.class);
- assertEquals(AmqpOutboundEndpoint.class, handler.getClass());
- assertEquals("amqp:outbound-channel-adapter", ((AmqpOutboundEndpoint) handler).getComponentType());
+ assertTrue(handler instanceof NamedComponent);
+ assertEquals("amqp:outbound-channel-adapter", ((NamedComponent) handler).getComponentType());
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
}
-
+
@Test
public void withHeaderMapperCustomHeaders() {
Object eventDrivenConsumer = context.getBean("withHeaderMapperCustomHeaders");
-
+
AmqpOutboundEndpoint endpoint = TestUtils.getPropertyValue(eventDrivenConsumer, "handler", AmqpOutboundEndpoint.class);
-
+
Field amqpTemplateField = ReflectionUtils.findField(AmqpOutboundEndpoint.class, "amqpTemplate");
amqpTemplateField.setAccessible(true);
RabbitTemplate amqpTemplate = TestUtils.getPropertyValue(endpoint, "amqpTemplate", RabbitTemplate.class);
@@ -110,8 +117,8 @@ public class AmqpOutboundChannelAdapterParserTests {
.when(amqpTemplate).send(Mockito.any(String.class), Mockito.any(String.class),
Mockito.any(org.springframework.amqp.core.Message.class), Mockito.any(CorrelationData.class));
ReflectionUtils.setField(amqpTemplateField, endpoint, amqpTemplate);
-
-
+
+
MessageChannel requestChannel = context.getBean("requestChannel", MessageChannel.class);
Message> message = MessageBuilder.withPayload("hello").setHeader("foo", "foo").setHeader("bar", "bar").setHeader("foobar", "foobar").build();
requestChannel.send(message);
@@ -214,4 +221,14 @@ public class AmqpOutboundChannelAdapterParserTests {
assertEquals("bar", returned.getHeaders().get(AmqpHeaders.RETURN_ROUTING_KEY));
assertEquals("hello", returned.getPayload());
}
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
index db2ed30102..7b1e716385 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
@@ -55,7 +55,11 @@
amqp-template="amqpTemplate"
order="5"
mapped-request-headers=""
- mapped-reply-headers=""/>
+ mapped-reply-headers="">
+
+
+
+
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
index d029f26bf2..ba8d596f60 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
@@ -15,6 +15,12 @@
*/
package org.springframework.integration.amqp.config;
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
import java.lang.reflect.Field;
import java.util.List;
@@ -31,17 +37,11 @@ import org.springframework.integration.MessageChannel;
import org.springframework.integration.amqp.AmqpHeaders;
import org.springframework.integration.amqp.outbound.AmqpOutboundEndpoint;
import org.springframework.integration.channel.QueueChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.util.ReflectionUtils;
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
/**
* @author Oleg Zhurakousky
* @author Gary Russell
@@ -53,6 +53,8 @@ import static org.junit.Assert.assertTrue;
*/
public class AmqpOutboundGatewayParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void testGatewayConfig(){
ApplicationContext context = new ClassPathXmlApplicationContext("AmqpOutboundGatewayParserTests-context.xml", this.getClass());
@@ -209,6 +211,7 @@ public class AmqpOutboundGatewayParserTests {
assertNull(replyMessage.getHeaders().get(AmqpHeaders.DELIVERY_MODE));
assertNull(replyMessage.getHeaders().get(AmqpHeaders.CONTENT_TYPE));
assertNull(replyMessage.getHeaders().get(AmqpHeaders.APP_ID));
+ assertEquals(1, adviceCalled);
}
@Test //INT-1029
@@ -261,4 +264,13 @@ public class AmqpOutboundGatewayParserTests {
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java
index 170df014d8..d6d38e18de 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java
@@ -91,6 +91,8 @@ public final class MessageHeaders implements Map, Serializable {
public static final String DISPOSITION_RESULT = "dispositionResult";
+ public static final String POSTPROCESS_RESULT = "postProcessResult";
+
private final Map headers;
@@ -164,12 +166,12 @@ public final class MessageHeaders implements Map, Serializable {
}
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
+ public boolean equals(Object object) {
+ if (this == object) {
return true;
}
- if (obj != null && obj instanceof MessageHeaders) {
- MessageHeaders other = (MessageHeaders) obj;
+ if (object != null && object instanceof MessageHeaders) {
+ MessageHeaders other = (MessageHeaders) object;
return this.headers.equals(other.headers);
}
return false;
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java
index 3012642196..92e6bba117 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2002-2011 the original author or authors.
- *
+ * Copyright 2002-2012 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.
@@ -13,6 +13,9 @@
package org.springframework.integration.config;
+import java.util.List;
+
+import org.aopalliance.aop.Advice;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@@ -23,11 +26,14 @@ 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.AbstractReplyProducingMessageHandler;
import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
/**
* @author Dave Syer
* @author Oleg Zhurakousky
+ * @author Gary Russell
*/
public abstract class AbstractSimpleMessageHandlerFactoryBean implements FactoryBean, BeanFactoryAware {
@@ -43,6 +49,8 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean adviceChain;
+
public AbstractSimpleMessageHandlerFactoryBean() {
super();
@@ -64,6 +72,10 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean adviceChain) {
+ this.adviceChain = adviceChain;
+ }
+
public H getObject() throws Exception {
if (this.handler == null) {
this.handler = this.createHandlerInternal();
@@ -71,9 +83,6 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean adviceChain;
+
public void setHandler(MessageHandler handler) {
Assert.notNull(handler, "handler must not be null");
synchronized (this.handlerMonitor) {
@@ -94,7 +103,7 @@ public class ConsumerEndpointFactoryBean
public void setPollerMetadata(PollerMetadata pollerMetadata) {
this.pollerMetadata = pollerMetadata;
}
-
+
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@@ -112,6 +121,11 @@ public class ConsumerEndpointFactoryBean
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
}
+ public void setAdviceChain(List adviceChain) {
+ Assert.notNull(adviceChain, "adviceChain must not be null");
+ this.adviceChain = adviceChain;
+ }
+
public void afterPropertiesSet() throws Exception {
try {
if (!this.beanName.startsWith("org.springframework")) {
@@ -132,6 +146,32 @@ public class ConsumerEndpointFactoryBean
+ this.handler + " for " + this.beanName + " :" + e.getMessage());
}
}
+ if (!CollectionUtils.isEmpty(this.adviceChain)) {
+ /*
+ * ARPMHs advise the handleRequesMessage method internally and already have the advice chain injected.
+ * So we only advise handlers that are not reply-producing. If the handler is already advised,
+ * add the configured advices to its chain, otherwise create a proxy.
+ */
+ if (!(this.handler instanceof AbstractReplyProducingMessageHandler)) {
+ if (AopUtils.isAopProxy(this.handler) && this.handler instanceof Advised) {
+ Class> targetClass = AopUtils.getTargetClass(this.handler);
+ for (Advice advice : this.adviceChain) {
+ NameMatchMethodPointcutAdvisor handlerAdvice = new NameMatchMethodPointcutAdvisor(advice);
+ handlerAdvice.addMethodName("handleMessage");
+ if (AopUtils.canApply(handlerAdvice.getPointcut(), targetClass)) {
+ ((Advised) this.handler).addAdvice(advice);
+ }
+ }
+ }
+ else {
+ ProxyFactory proxyFactory = new ProxyFactory(this.handler);
+ for (Advice advice : this.adviceChain) {
+ proxyFactory.addAdvice(advice);
+ }
+ this.handler = (MessageHandler) proxyFactory.getProxy(this.beanClassLoader);
+ }
+ }
+ }
this.initializeEndpoint();
}
@@ -184,9 +224,9 @@ public class ConsumerEndpointFactoryBean
pollingConsumer.setTrigger(this.pollerMetadata.getTrigger());
pollingConsumer.setAdviceChain(this.pollerMetadata.getAdviceChain());
pollingConsumer.setMaxMessagesPerPoll(this.pollerMetadata.getMaxMessagesPerPoll());
-
+
pollingConsumer.setErrorHandler(this.pollerMetadata.getErrorHandler());
-
+
pollingConsumer.setReceiveTimeout(this.pollerMetadata.getReceiveTimeout());
pollingConsumer.setBeanClassLoader(beanClassLoader);
pollingConsumer.setBeanFactory(beanFactory);
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
index 88995538c8..4629ff3874 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
@@ -19,8 +19,7 @@ package org.springframework.integration.config.xml;
import java.util.Collection;
import java.util.List;
-import org.w3c.dom.Element;
-
+import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
@@ -32,10 +31,10 @@ import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
-import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
/**
* Base class parser for elements that create Message Endpoints.
@@ -92,6 +91,11 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
return handlerBeanDefinition;
}
+ Element adviceChainElement = DomUtils.getChildElementByTagName(element,
+ IntegrationNamespaceUtils.REQUEST_HANDLER_ADVICE_CHAIN);
+ IntegrationNamespaceUtils.configureAndSetAdviceChainIfPresent(adviceChainElement, null,
+ handlerBuilder, parserContext);
+
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class);
String handlerBeanName = BeanDefinitionReaderUtils.generateBeanName(handlerBeanDefinition, parserContext.getRegistry());
@@ -99,6 +103,7 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
parserContext.registerBeanComponent(new BeanComponentDefinition(handlerBeanDefinition, handlerBeanName, handlerAlias));
builder.addPropertyReference("handler", handlerBeanName);
+
String inputChannelName = element.getAttribute(inputChannelAttributeName);
if (!parserContext.getRegistry().containsBeanDefinition(inputChannelName)){
@@ -136,4 +141,5 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDefinition, beanName));
return null;
}
+
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java
index 00386f3b7d..6d77f21953 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java
@@ -16,16 +16,18 @@
package org.springframework.integration.config.xml;
-import org.w3c.dom.Element;
-
+import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
+import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
+import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
/**
* Base class for outbound Channel Adapter parsers.
@@ -34,7 +36,7 @@ import org.springframework.util.xml.DomUtils;
* an {@link org.springframework.integration.endpoint.AbstractEndpoint} depending on the channel type.
* If this component is defined as nested element (e.g., inside of the chain) it will produce
* a {@link org.springframework.integration.core.MessageHandler}.
- *
+ *
* @author Mark Fisher
* @author Gary Russell
* @author Artem Bilan
@@ -48,7 +50,8 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
}
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class);
Element pollerElement = DomUtils.getChildElementByTagName(element, "poller");
- builder.addPropertyReference("handler", this.parseAndRegisterConsumer(element, parserContext));
+ BeanComponentDefinition handlerBeanComponentDefinition = this.doParseAndRegisterConsumer(element, parserContext);
+ builder.addPropertyReference("handler", handlerBeanComponentDefinition.getBeanName());
if (pollerElement != null) {
if (!StringUtils.hasText(channelName)) {
parserContext.getReaderContext().error(
@@ -58,6 +61,40 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
}
builder.addPropertyValue("inputChannelName", channelName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
+
+ Element adviceChainElement = DomUtils.getChildElementByTagName(element,
+ IntegrationNamespaceUtils.REQUEST_HANDLER_ADVICE_CHAIN);
+ @SuppressWarnings("rawtypes")
+ ManagedList adviceChain = IntegrationNamespaceUtils.configureAdviceChain(adviceChainElement, null,
+ builder, parserContext);
+ if (adviceChain != null) {
+ BeanDefinition handlerBeanDefinition = handlerBeanComponentDefinition.getBeanDefinition();
+ /*
+ * For ARPMH, the advice chain is injected so just the handleRequestMessage method is advised.
+ * Sometime ARPMHs do double duty as a gateway and a channel adapter. The parser subclass
+ * can indicate this by overriding isUsingReplyProducer(), or we can try to determine it from
+ * the bean class.
+ */
+ boolean isReplyProducer = this.isUsingReplyProducer();
+ if (!isReplyProducer) {
+ Class> beanClass = null;
+ if (handlerBeanDefinition instanceof AbstractBeanDefinition) {
+ AbstractBeanDefinition abstractBeanDefinition = (AbstractBeanDefinition) handlerBeanDefinition;
+ if (abstractBeanDefinition.hasBeanClass()) {
+ beanClass = abstractBeanDefinition.getBeanClass();
+ }
+ }
+ isReplyProducer = beanClass != null && AbstractReplyProducingMessageHandler.class.isAssignableFrom(beanClass);
+ }
+
+ if (isReplyProducer) {
+ handlerBeanDefinition.getPropertyValues().add("adviceChain", adviceChain);
+ }
+ else {
+ builder.addPropertyValue("adviceChain", adviceChain);
+ }
+ }
+
return builder.getBeanDefinition();
}
@@ -65,8 +102,19 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
* Override this method to control the registration process and return the bean name.
* If parsing a bean definition whose name can be auto-generated, consider using
* {@link #parseConsumer(Element, ParserContext)} instead.
+ * @deprecated Use {@link #doParseAndRegisterConsumer(Element, ParserContext)}
*/
+ @Deprecated
protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) {
+ return doParseAndRegisterConsumer(element, parserContext).getBeanName();
+ }
+
+ /**
+ * Override this method to control the registration process and return the bean name.
+ * If parsing a bean definition whose name can be auto-generated, consider using
+ * {@link #parseConsumer(Element, ParserContext)} instead.
+ */
+ protected BeanComponentDefinition doParseAndRegisterConsumer(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = this.parseConsumer(element, parserContext);
if (definition == null) {
parserContext.getReaderContext().error("Consumer parsing must return an AbstractBeanDefinition.", element);
@@ -77,8 +125,9 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
}
String beanName = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());
String[] handlerAlias = IntegrationNamespaceUtils.generateAlias(element);
- parserContext.registerBeanComponent(new BeanComponentDefinition(definition, beanName, handlerAlias));
- return beanName;
+ BeanComponentDefinition beanComponentDefinition = new BeanComponentDefinition(definition, beanName, handlerAlias);
+ parserContext.registerBeanComponent(beanComponentDefinition);
+ return beanComponentDefinition;
}
/**
@@ -87,4 +136,13 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann
*/
protected abstract AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext);
+ /**
+ * Override this to signal that this channel adapter is actually using a AbstractReplyProducingMessageHandler
+ * while it is not possible for this parser to determine that because, say, a FactoryBean is being used.
+ * @return false, unless overridden.
+ */
+ protected boolean isUsingReplyProducer() {
+ return false;
+ }
+
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java
index eb86a327ad..2c2fe14fe9 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java
@@ -19,9 +19,11 @@ import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
@@ -33,6 +35,8 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* Shared utility methods for integration namespace parsers.
@@ -54,6 +58,7 @@ public abstract class IntegrationNamespaceUtils {
static final String ORDER = "order";
static final String EXPRESSION_ATTRIBUTE = "expression";
public static final String HANDLER_ALIAS_SUFFIX = ".handler";
+ public static final String REQUEST_HANDLER_ADVICE_CHAIN = "request-handler-advice-chain";
/**
* Property name on ChannelInitializer used to configure the default max subscribers for
@@ -308,4 +313,56 @@ public abstract class IntegrationNamespaceUtils {
}
return handlerAlias;
}
+
+ @SuppressWarnings({ "rawtypes" })
+ public static void configureAndSetAdviceChainIfPresent(Element adviceChainElement, Element txElement,
+ BeanDefinitionBuilder parentBuilder, ParserContext parserContext) {
+ ManagedList adviceChain = configureAdviceChain(adviceChainElement, txElement, parentBuilder, parserContext);
+ if (adviceChain != null) {
+ parentBuilder.addPropertyValue("adviceChain", adviceChain);
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static ManagedList configureAdviceChain(Element adviceChainElement, Element txElement,
+ BeanDefinitionBuilder parentBuilder, ParserContext parserContext) {
+ ManagedList adviceChain = null;
+ // Schema validation ensures txElement and adviceChainElement are mutually exclusive
+ if (txElement != null) {
+ adviceChain = new ManagedList();
+ adviceChain.add(IntegrationNamespaceUtils.configureTransactionAttributes(txElement));
+ }
+ if (adviceChainElement != null) {
+ adviceChain = new ManagedList();
+ NodeList childNodes = adviceChainElement.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ Element childElement = (Element) child;
+ String localName = child.getLocalName();
+ if ("bean".equals(localName)) {
+ BeanDefinitionHolder holder = parserContext.getDelegate().parseBeanDefinitionElement(
+ childElement, parentBuilder.getBeanDefinition());
+ parserContext.registerBeanComponent(new BeanComponentDefinition(holder));
+ adviceChain.add(new RuntimeBeanReference(holder.getBeanName()));
+ }
+ else if ("ref".equals(localName)) {
+ String ref = childElement.getAttribute("bean");
+ adviceChain.add(new RuntimeBeanReference(ref));
+ }
+ else {
+ BeanDefinition customBeanDefinition = parserContext.getDelegate().parseCustomElement(
+ childElement, parentBuilder.getBeanDefinition());
+ if (customBeanDefinition == null) {
+ parserContext.getReaderContext().error(
+ "failed to parse custom element '" + localName + "'", childElement);
+ }
+ adviceChain.add(customBeanDefinition);
+ }
+ }
+ }
+ }
+ return adviceChain;
+ }
+
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/PollerParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/PollerParser.java
index 19bc9d56a9..9d609eada3 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/PollerParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/PollerParser.java
@@ -20,14 +20,9 @@ import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanDefinitionHolder;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
-import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
@@ -40,8 +35,6 @@ import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
/**
* Parser for the <poller> element.
@@ -94,7 +87,8 @@ public class PollerParser extends AbstractBeanDefinitionParser {
Element txElement = DomUtils.getChildElementByTagName(element, "transactional");
Element adviceChainElement = DomUtils.getChildElementByTagName(element, "advice-chain");
- configureAdviceChain(adviceChainElement, txElement, metadataBuilder, parserContext);
+ IntegrationNamespaceUtils.configureAndSetAdviceChainIfPresent(adviceChainElement, txElement,
+ metadataBuilder, parserContext);
Element pseudoTxElement = DomUtils.getChildElementByTagName(element, "psuedo-transactional");
if (pseudoTxElement != null && txElement != null) {
@@ -174,48 +168,6 @@ public class PollerParser extends AbstractBeanDefinitionParser {
targetBuilder.addPropertyReference("trigger", triggerBeanNames.get(0));
}
- /**
- * Parses the 'advice-chain' element's sub-elements.
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private void configureAdviceChain(Element adviceChainElement, Element txElement, BeanDefinitionBuilder targetBuilder, ParserContext parserContext) {
- ManagedList adviceChain = new ManagedList();
- // Schema validation ensures txElement and adviceChainElement are mutually exclusive
- if (txElement != null) {
- adviceChain.add(IntegrationNamespaceUtils.configureTransactionAttributes(txElement));
- }
- if (adviceChainElement != null) {
- NodeList childNodes = adviceChainElement.getChildNodes();
- for (int i = 0; i < childNodes.getLength(); i++) {
- Node child = childNodes.item(i);
- if (child.getNodeType() == Node.ELEMENT_NODE) {
- Element childElement = (Element) child;
- String localName = child.getLocalName();
- if ("bean".equals(localName)) {
- BeanDefinitionHolder holder = parserContext.getDelegate().parseBeanDefinitionElement(
- childElement, targetBuilder.getBeanDefinition());
- parserContext.registerBeanComponent(new BeanComponentDefinition(holder));
- adviceChain.add(new RuntimeBeanReference(holder.getBeanName()));
- }
- else if ("ref".equals(localName)) {
- String ref = childElement.getAttribute("bean");
- adviceChain.add(new RuntimeBeanReference(ref));
- }
- else {
- BeanDefinition customBeanDefinition = parserContext.getDelegate().parseCustomElement(
- childElement, targetBuilder.getBeanDefinition());
- if (customBeanDefinition == null) {
- parserContext.getReaderContext().error(
- "failed to parse custom element '" + localName + "'", childElement);
- }
- adviceChain.add(customBeanDefinition);
- }
- }
- }
- }
- targetBuilder.addPropertyValue("adviceChain", adviceChain);
- }
-
private void configureTransactionSync(Element element, BeanDefinitionBuilder metadataBuilder,
ParserContext parserContext) {
if (element != null) {
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java
index 75307c73cd..80a304a448 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2011 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -16,6 +16,11 @@
package org.springframework.integration.handler;
+import java.util.List;
+
+import org.aopalliance.aop.Advice;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageDeliveryException;
@@ -26,6 +31,8 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.support.channel.ChannelResolutionException;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.CollectionUtils;
/**
* Base class for MessageHandlers that are capable of producing replies.
@@ -33,8 +40,10 @@ import org.springframework.util.Assert;
* @author Mark Fisher
* @author Iwein Fuld
* @author Oleg Zhurakousky
+ * @author Gary Russell
*/
-public abstract class AbstractReplyProducingMessageHandler extends AbstractMessageHandler implements MessageProducer {
+public abstract class AbstractReplyProducingMessageHandler extends AbstractMessageHandler
+ implements MessageProducer, BeanClassLoaderAware {
private MessageChannel outputChannel;
@@ -42,6 +51,13 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
private final MessagingTemplate messagingTemplate;
+ private volatile RequestHandler advisedRequestHandler;
+
+ private volatile List adviceChain;
+
+ private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
+
+
public AbstractReplyProducingMessageHandler() {
this.messagingTemplate = new MessagingTemplate();
@@ -82,11 +98,30 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
return this.messagingTemplate;
}
+
+ public void setAdviceChain(List adviceChain) {
+ Assert.notNull(adviceChain, "adviceChain cannot be null");
+ this.adviceChain = adviceChain;
+ }
+
+
+ public void setBeanClassLoader(ClassLoader beanClassLoader) {
+ this.beanClassLoader = beanClassLoader;
+ }
+
+
@Override
protected void onInit() {
if (this.getBeanFactory() != null) {
this.messagingTemplate.setBeanFactory(getBeanFactory());
}
+ if (!CollectionUtils.isEmpty(this.adviceChain)) {
+ ProxyFactory proxyFactory = new ProxyFactory(new AdvisedRequestHandler());
+ for (Advice advice : this.adviceChain) {
+ proxyFactory.addAdvice(advice);
+ }
+ this.advisedRequestHandler = (RequestHandler) proxyFactory.getProxy(this.beanClassLoader);
+ }
}
/**
@@ -94,7 +129,13 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
*/
@Override
protected final void handleMessageInternal(Message> message) {
- Object result = this.handleRequestMessage(message);
+ Object result;
+ if (this.advisedRequestHandler == null) {
+ result = this.handleRequestMessage(message);
+ }
+ else {
+ result = this.advisedRequestHandler.handleRequestMessage(message);
+ }
if (result != null) {
MessageHeaders requestHeaders = message.getHeaders();
this.handleResult(result, requestHeaders);
@@ -149,7 +190,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
* 'outputChannel' is null. In that case, the header value must not also be
* null, and it must be an instance of either String or {@link MessageChannel}.
* @param replyMessage the reply Message to send
- * @param replyChannelHeaderValue the 'replyChannel' header value from the original request
+ * @param replyChannelHeaderValue the 'replyChannel' header value from the original request
*/
private final void sendReplyMessage(Message> replyMessage, final Object replyChannelHeaderValue) {
if (logger.isDebugEnabled()) {
@@ -207,4 +248,26 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
*/
protected abstract Object handleRequestMessage(Message> requestMessage);
+
+ private interface RequestHandler {
+
+ Object handleRequestMessage(Message> requestMessage);
+
+ String toString();
+ }
+
+ private class AdvisedRequestHandler implements RequestHandler {
+
+ public Object handleRequestMessage(Message> requestMessage) {
+ return AbstractReplyProducingMessageHandler.this.handleRequestMessage(requestMessage);
+ }
+
+ @Override
+ public String toString() {
+ return AbstractReplyProducingMessageHandler.this.toString();
+ }
+
+
+ }
+
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/RetryStateGenerator.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/RetryStateGenerator.java
new file mode 100644
index 0000000000..e8430d8d62
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/RetryStateGenerator.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2012 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.handler;
+
+import org.springframework.integration.Message;
+import org.springframework.retry.RetryState;
+
+/**
+ * Strategy interface for generating a {@link RetryState} instance
+ * based on a message.
+ * @author Gary Russell
+ * @since 2.2
+ *
+ */
+public interface RetryStateGenerator {
+
+ RetryState determineRetryState(Message> message);
+}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractRequestHandlerAdvice.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractRequestHandlerAdvice.java
new file mode 100644
index 0000000000..4f17c89d7f
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractRequestHandlerAdvice.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002-2012 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.handler.advice;
+
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
+
+/**
+ * Base class for {@link MessageHandler} advice classes.
+ * @author Gary Russell
+ * @since 2.2
+ *
+ */
+public abstract class AbstractRequestHandlerAdvice implements MethodInterceptor {
+
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
+ public final Object invoke(final MethodInvocation invocation) throws Throwable {
+
+ Method method = invocation.getMethod();
+ Object[] arguments = invocation.getArguments();
+ boolean isMessageMethod = (method.getName().equals("handleRequestMessage") || method.getName().equals("handleMessage"))
+ && (arguments.length == 1 && arguments[0] instanceof Message);
+
+ if (!isMessageMethod) {
+ return invocation.proceed();
+ }
+ else {
+ Message> message = (Message>) arguments[0];
+ try {
+ return doInvoke(new ExecutionCallback(){
+
+ public Object execute() throws Exception {
+ try {
+ return invocation.proceed();
+ }
+ catch (Throwable e) {
+ throw new ThrowableHolderException(e);
+ }
+ }
+ }, invocation.getThis(), message);
+ }
+ catch (Exception e) {
+ if (e instanceof ThrowableHolderException) {
+ throw e.getCause();
+ }
+ else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ protected abstract Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception;
+
+ protected interface ExecutionCallback {
+
+ Object execute() throws Exception;
+ }
+
+ @SuppressWarnings("serial")
+ private class ThrowableHolderException extends RuntimeException {
+
+ public ThrowableHolderException(Throwable cause) {
+ super(cause);
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/ExpressionEvaluatingRequestHandlerAdvice.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/ExpressionEvaluatingRequestHandlerAdvice.java
new file mode 100644
index 0000000000..72a56825af
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/ExpressionEvaluatingRequestHandlerAdvice.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2002-2012 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.handler.advice;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.expression.Expression;
+import org.springframework.integration.Message;
+import org.springframework.integration.MessageChannel;
+import org.springframework.integration.MessageHeaders;
+import org.springframework.integration.core.MessageHandler;
+import org.springframework.integration.core.MessagingTemplate;
+import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
+import org.springframework.integration.support.MessageBuilder;
+
+/**
+ * Used to advise {@link MessageHandler}s.
+ * Two expressions 'onSuccessExpression' and 'onFailureExpression' are evaluated when
+ * appropriate. If the evaluation returns a result, a message is sent to the onSuccessChannel
+ * or onFailureChannel as appropriate; the message is the input message with a header
+ * {@link MessageHeaders#POSTPROCESS_RESULT} containing the evaluation result.
+ * The failure expression is NOT evaluated if the success expression throws an exception.
+ * @author Gary Russell
+ * @since 2.2
+ *
+ */
+public class ExpressionEvaluatingRequestHandlerAdvice extends AbstractRequestHandlerAdvice
+ implements BeanFactoryAware {
+
+ private final ExpressionEvaluatingMessageProcessor
+
@@ -1481,28 +1482,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -3422,12 +3402,34 @@ is provided, the return value is expected to match a channel name exactly.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests-context.xml
index 79fa610dfc..90b06b9931 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests-context.xml
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests-context.xml
@@ -23,7 +23,11 @@
-
+
+
+
+
+
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests.java
index 95b95ced8b..6ac12485c8 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/FilterParserTests.java
@@ -22,7 +22,6 @@ 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.beans.factory.annotation.Qualifier;
import org.springframework.integration.Message;
@@ -30,6 +29,7 @@ import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.core.MessageSelector;
import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -69,13 +69,16 @@ public class FilterParserTests {
@Autowired @Qualifier("discardAndExceptionOutput")
PollableChannel discardAndExceptionOutput;
+ private static volatile int adviceCalled;
@Test
public void filterWithSelectorAdapterAccepts() {
+ adviceCalled = 0;
adapterInput.send(new GenericMessage("test"));
Message> reply = adapterOutput.receive(0);
assertNotNull(reply);
assertEquals("test", reply.getPayload());
+ assertEquals(1, adviceCalled);
}
@Test
@@ -156,4 +159,13 @@ public class FilterParserTests {
}
}
+ public static class FooFilter extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml
index 20b6dfb392..5b2a3f9a66 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml
@@ -22,6 +22,10 @@
+
+
+
+
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java
index 87fa08bb9c..e70ef0739e 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java
@@ -35,6 +35,7 @@ import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.core.SubscribableChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.transformer.ContentEnricher;
@@ -44,7 +45,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @author Gunnar Hillert
- *
+ * @author Gary Russell
+ *
* @since 2.1
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -54,6 +56,7 @@ public class EnricherParserTests {
@Autowired
private ApplicationContext context;
+ private static volatile int adviceCalled;
@Test
@SuppressWarnings("unchecked")
@@ -84,13 +87,14 @@ public class EnricherParserTests {
throw new IllegalStateException("expected 'name', 'age', and 'gender' only, not: " + e.getKey().getExpressionString());
}
}
+
}
@Test
public void configurationCheckTimeoutParameters() {
-
+
Object endpoint = context.getBean("enricher");
-
+
Long requestTimeout = TestUtils.getPropertyValue(endpoint, "handler.requestTimeout", Long.class);
Long replyTimeout = TestUtils.getPropertyValue(endpoint, "handler.replyTimeout", Long.class);
@@ -98,18 +102,18 @@ public class EnricherParserTests {
assertEquals(Long.valueOf(9876L), replyTimeout);
}
-
+
@Test
public void configurationCheckRequiresReply() {
-
+
Object endpoint = context.getBean("enricher");
-
+
boolean requiresReply = TestUtils.getPropertyValue(endpoint, "handler.requiresReply", Boolean.class);
assertTrue("Was expecting requiresReply to be 'false'", requiresReply);
}
-
+
@Test
public void integrationTest() {
SubscribableChannel requests = context.getBean("requests", SubscribableChannel.class);
@@ -128,6 +132,7 @@ public class EnricherParserTests {
assertEquals(42, enriched.getAge());
assertEquals("male", enriched.getGender());
assertNotSame(original, enriched);
+ assertEquals(1, adviceCalled);
}
private static class Source {
@@ -176,6 +181,7 @@ public class EnricherParserTests {
this.gender = gender;
}
+ @Override
public Object clone() {
Target copy = new Target();
copy.setName(this.name);
@@ -184,4 +190,13 @@ public class EnricherParserTests {
}
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests-context.xml
index 16950067e9..f0b46f7961 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests-context.xml
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests-context.xml
@@ -21,4 +21,9 @@
+
+
+
+
+
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests.java
index d87b9a045c..6dca7a109f 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ServiceActivatorParserTests.java
@@ -20,12 +20,13 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.handler.ServiceActivatingHandler;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -56,6 +57,9 @@ public class ServiceActivatorParserTests {
@Autowired
private MessageChannel multipleArgsFromPayloadInput;
+ @Autowired
+ private MessageChannel advisedInput;
+
@SuppressWarnings("unused") // testing auto wiring only
@Autowired
@Qualifier("org.springframework.integration.config.ServiceActivatorFactoryBean#0")
@@ -102,6 +106,11 @@ public class ServiceActivatorParserTests {
assertEquals("JohnDoe", result);
}
+ @Test
+ public void advised() {
+ Object result = this.sendAndReceive(advisedInput, "hello");
+ assertEquals("bar", result);
+ }
private Object sendAndReceive(MessageChannel channel, Object payload) {
MessagingTemplate template = new MessagingTemplate(channel);
@@ -152,4 +161,13 @@ public class ServiceActivatorParserTests {
}
}
+ public static class BarAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ callback.execute();
+ return "bar";
+ }
+
+ }
}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/AdvisedMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/AdvisedMessageHandlerTests.java
new file mode 100644
index 0000000000..6e187893b0
--- /dev/null
+++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/AdvisedMessageHandlerTests.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright 2002-2012 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.handler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.aopalliance.aop.Advice;
+import org.junit.Test;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.integration.Message;
+import org.springframework.integration.MessageHandlingException;
+import org.springframework.integration.MessageHeaders;
+import org.springframework.integration.channel.QueueChannel;
+import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice;
+import org.springframework.integration.handler.advice.RequestHandlerCircuitBreakerAdvice;
+import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.retry.RecoveryCallback;
+import org.springframework.retry.RetryContext;
+import org.springframework.retry.RetryState;
+import org.springframework.retry.support.DefaultRetryState;
+
+/**
+ * @author Gary Russell
+ * @since 2.2
+ *
+ */
+public class AdvisedMessageHandlerTests {
+
+ @Test
+ public void successFailureAdvice() {
+ final AtomicBoolean doFail = new AtomicBoolean();
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (doFail.get()) {
+ throw new RuntimeException("qux");
+ }
+ return "baz";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ Message message = new GenericMessage("Hello, world!");
+
+ // no advice
+ handler.handleMessage(message);
+ Message> reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("baz", reply.getPayload());
+
+ PollableChannel successChannel = new QueueChannel();
+ PollableChannel failureChannel = new QueueChannel();
+ ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(
+ new SpelExpressionParser().parseExpression("'foo'"), successChannel,
+ new SpelExpressionParser().parseExpression("'bar'"), failureChannel);
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ // advice with success
+ handler.handleMessage(message);
+ reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("baz", reply.getPayload());
+
+ Message> success = successChannel.receive(1000);
+ assertNotNull(success);
+ assertEquals("Hello, world!", success.getPayload());
+ assertEquals("foo", success.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT));
+
+ // advice with failure, not trapped
+ doFail.set(true);
+ try {
+ handler.handleMessage(message);
+ fail("Expected exception");
+ }
+ catch (Exception e) {
+ assertEquals("qux", e.getCause().getMessage());
+ }
+
+ Message> failure = failureChannel.receive(1000);
+ assertNotNull(failure);
+ assertEquals("Hello, world!", failure.getPayload());
+ assertEquals("bar", failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT));
+
+ // advice with failure, trapped
+ advice.setTrapException(true);
+ handler.handleMessage(message);
+ failure = failureChannel.receive(1000);
+ assertNotNull(failure);
+ assertEquals("Hello, world!", failure.getPayload());
+ assertEquals("bar", failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT));
+ assertNull(replies.receive(1));
+
+ // advice with failure, eval is result
+ advice.setReturnFailureExpressionResult(true);
+ handler.handleMessage(message);
+ failure = failureChannel.receive(1000);
+ assertNotNull(failure);
+ assertEquals("Hello, world!", failure.getPayload());
+ assertEquals("bar", failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT));
+
+ reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("bar", reply.getPayload());
+
+ }
+
+ @Test
+ public void propagateOnSuccessExpressionFailures() {
+ final AtomicBoolean doFail = new AtomicBoolean();
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (doFail.get()) {
+ throw new RuntimeException("qux");
+ }
+ return "baz";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ Message message = new GenericMessage("Hello, world!");
+
+ PollableChannel successChannel = new QueueChannel();
+ PollableChannel failureChannel = new QueueChannel();
+ ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(
+ new SpelExpressionParser().parseExpression("1/0"), successChannel,
+ new SpelExpressionParser().parseExpression("1/0"), failureChannel);
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ // failing advice with success
+ handler.handleMessage(message);
+ Message> reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("baz", reply.getPayload());
+
+ Message> success = successChannel.receive(1000);
+ assertNotNull(success);
+ assertEquals("Hello, world!", success.getPayload());
+ assertEquals(MessageHandlingException.class, success.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT).getClass());
+ assertEquals("Expression evaluation failed: 1/0", ((Exception) success.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT)).getMessage());
+
+ // propagate failing advice with success
+ advice.setPropagateEvaluationFailures(true);
+ try {
+ handler.handleMessage(message);
+ fail("Expected Exception");
+ }
+ catch (MessageHandlingException e) {
+ assertEquals("Expression evaluation failed: 1/0", e.getMessage());
+ }
+ reply = replies.receive(1);
+ assertNull(reply);
+
+ success = successChannel.receive(1000);
+ assertNotNull(success);
+ assertEquals("Hello, world!", success.getPayload());
+ assertEquals(MessageHandlingException.class, success.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT).getClass());
+ assertEquals("Expression evaluation failed: 1/0", ((Exception) success.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT)).getMessage());
+
+ }
+
+ @Test
+ public void propagateOnFailureExpressionFailures() {
+ final AtomicBoolean doFail = new AtomicBoolean(true);
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (doFail.get()) {
+ throw new RuntimeException("qux");
+ }
+ return "baz";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ Message message = new GenericMessage("Hello, world!");
+
+ PollableChannel successChannel = new QueueChannel();
+ PollableChannel failureChannel = new QueueChannel();
+ ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(
+ new SpelExpressionParser().parseExpression("1/0"), successChannel,
+ new SpelExpressionParser().parseExpression("1/0"), failureChannel);
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ // failing advice with failure
+ try {
+ handler.handleMessage(message);
+ fail("Expected exception");
+ }
+ catch (Exception e) {
+ assertEquals("qux", e.getCause().getMessage());
+ }
+ Message> reply = replies.receive(1);
+ assertNull(reply);
+
+ Message> failure = failureChannel.receive(1000);
+ assertNotNull(failure);
+ assertEquals("Hello, world!", failure.getPayload());
+ assertEquals(MessageHandlingException.class, failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT).getClass());
+ assertEquals("Expression evaluation failed: 1/0", ((Exception) failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT)).getMessage());
+
+ // propagate failing advice with failure; expect original exception
+ advice.setPropagateEvaluationFailures(true);
+ try {
+ handler.handleMessage(message);
+ fail("Expected Exception");
+ }
+ catch (MessageHandlingException e) {
+ assertEquals("qux", e.getCause().getMessage());
+ }
+ reply = replies.receive(1);
+ assertNull(reply);
+
+ failure = failureChannel.receive(1000);
+ assertNotNull(failure);
+ assertEquals("Hello, world!", failure.getPayload());
+ assertEquals(MessageHandlingException.class, failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT).getClass());
+ assertEquals("Expression evaluation failed: 1/0", ((Exception) failure.getHeaders().get(MessageHeaders.POSTPROCESS_RESULT)).getMessage());
+
+ }
+
+ @Test
+ public void circuitBreakerTests() throws Exception {
+ final AtomicBoolean doFail = new AtomicBoolean();
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (doFail.get()) {
+ throw new RuntimeException("foo");
+ }
+ return "bar";
+ }
+
+ };
+ handler.setBeanName("baz");
+ handler.setOutputChannel(new QueueChannel());
+ RequestHandlerCircuitBreakerAdvice advice = new RequestHandlerCircuitBreakerAdvice();
+ /*
+ * Circuit breaker opens after 2 failures; allows a new attempt after 100ms and
+ * immediately opens again if that attempt fails. After a successful attempt,
+ * we reset the failure counter.
+ */
+ advice.setThreshold(2);
+ advice.setHalfOpenAfter(100);
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ doFail.set(true);
+ Message message = new GenericMessage("Hello, world!");
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("foo", e.getCause().getMessage());
+ }
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("foo", e.getCause().getMessage());
+ }
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("Circuit Breaker is Open for baz", e.getMessage());
+ }
+ Thread.sleep(100);
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("foo", e.getCause().getMessage());
+ }
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("Circuit Breaker is Open for baz", e.getMessage());
+ }
+ Thread.sleep(100);
+ doFail.set(false);
+ handler.handleMessage(message);
+ doFail.set(true);
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("foo", e.getCause().getMessage());
+ }
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("foo", e.getCause().getMessage());
+ }
+ try {
+ handler.handleMessage(message);
+ fail("Expected failure");
+ }
+ catch (Exception e) {
+ assertEquals("Circuit Breaker is Open for baz", e.getMessage());
+ }
+ }
+
+ @Test
+ public void defaultRetrySucceedonThirdTry() {
+ final AtomicInteger counter = new AtomicInteger(2);
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (counter.getAndDecrement() > 0) {
+ throw new RuntimeException("foo");
+ }
+ return "bar";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ Message message = new GenericMessage("Hello, world!");
+ handler.handleMessage(message);
+ assertTrue(counter.get() == -1);
+ Message> reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("bar", reply.getPayload());
+
+ }
+
+ @Test
+ public void defaultStatefulRetrySucceedonThirdTry() {
+ final AtomicInteger counter = new AtomicInteger(2);
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (counter.getAndDecrement() > 0) {
+ throw new RuntimeException("foo");
+ }
+ return "bar";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
+
+ advice.setRetryStateGenerator(new RetryStateGenerator() {
+ public RetryState determineRetryState(Message> message) {
+ return new DefaultRetryState(message.getHeaders().getId());
+ }
+ });
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ Message message = new GenericMessage("Hello, world!");
+ for (int i = 0; i < 3; i++) {
+ try {
+ handler.handleMessage(message);
+ }
+ catch (Exception e) {
+ assertTrue(i < 2);
+ }
+ }
+ assertTrue(counter.get() == -1);
+ Message> reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("bar", reply.getPayload());
+
+ }
+
+ @Test
+ public void defaultStatefulRetryRecoverAfterThirdTry() {
+ final AtomicInteger counter = new AtomicInteger(3);
+ AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
+
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ if (counter.getAndDecrement() > 0) {
+ throw new RuntimeException("foo");
+ }
+ return "bar";
+ }
+ };
+ QueueChannel replies = new QueueChannel();
+ handler.setOutputChannel(replies);
+ RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
+
+ advice.setRetryStateGenerator(new RetryStateGenerator() {
+ public RetryState determineRetryState(Message> message) {
+ return new DefaultRetryState(message.getHeaders().getId());
+ }
+ });
+
+ advice.setRecoveryCallback(new RecoveryCallback() {
+
+ public Object recover(RetryContext context) throws Exception {
+ return "baz";
+ }
+ });
+
+ List adviceChain = new ArrayList();
+ adviceChain.add(advice);
+ handler.setAdviceChain(adviceChain);
+ handler.afterPropertiesSet();
+
+ Message message = new GenericMessage("Hello, world!");
+ for (int i = 0; i < 4; i++) {
+ try {
+ handler.handleMessage(message);
+ }
+ catch (Exception e) {
+ }
+ }
+ assertTrue(counter.get() == 0);
+ Message> reply = replies.receive(1000);
+ assertNotNull(reply);
+ assertEquals("baz", reply.getPayload());
+
+ }
+}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/transformer/TransformerContextTests.java b/spring-integration-core/src/test/java/org/springframework/integration/transformer/TransformerContextTests.java
index 7bc55cccf4..2280203f14 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/transformer/TransformerContextTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/transformer/TransformerContextTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -19,19 +19,22 @@ package org.springframework.integration.transformer;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
-
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.message.GenericMessage;
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
public class TransformerContextTests {
+ private static volatile int adviceCalled;
+
@Test
public void methodInvokingTransformer() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -41,6 +44,16 @@ public class TransformerContextTests {
input.send(new GenericMessage("foo"));
Message> reply = output.receive(0);
assertEquals("FOO", reply.getPayload());
+ assertEquals(1, adviceCalled);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
\ No newline at end of file
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/transformer/transformerContextTests.xml b/spring-integration-core/src/test/java/org/springframework/integration/transformer/transformerContextTests.xml
index 5679865023..2fbcdc1dd9 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/transformer/transformerContextTests.xml
+++ b/spring-integration-core/src/test/java/org/springframework/integration/transformer/transformerContextTests.xml
@@ -13,7 +13,11 @@
-
+
+
+
+
+
diff --git a/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.2.xsd b/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.2.xsd
index 91a174aa06..1658e38d8d 100644
--- a/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.2.xsd
+++ b/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.2.xsd
@@ -81,9 +81,10 @@
-
+
-
+
+
diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests-context.xml b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests-context.xml
index 88903e44cd..b160d943f5 100644
--- a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests-context.xml
@@ -11,6 +11,14 @@
+
+
+
+
+
+
+
+
diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java
index 5e64e9dfc6..675e9de37e 100644
--- a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java
+++ b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java
@@ -16,7 +16,11 @@
package org.springframework.integration.event.config;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
import junit.framework.Assert;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
@@ -31,16 +35,15 @@ import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
/**
* @author Oleg Zhurakousky
* @author Artem Bilan
+ * @author Gary Russell
* @since 2.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -52,6 +55,7 @@ public class EventOutboundChannelAdapterParserTests {
private volatile boolean receivedEvent;
+ private static volatile int adviceCalled;
@Test
public void validateEventParser() {
@@ -82,8 +86,30 @@ public class EventOutboundChannelAdapterParserTests {
Assert.assertTrue(receivedEvent);
}
+ @Test
+ public void withAdvice() {
+ receivedEvent = false;
+ ApplicationListener> listener = new ApplicationListener() {
+ public void onApplicationEvent(ApplicationEvent event) {
+ Object source = event.getSource();
+ if (source instanceof Message){
+ String payload = (String) ((Message>) source).getPayload();
+ if (payload.equals("hello")) {
+ receivedEvent = true;
+ }
+ }
+ }
+ };
+ context.addApplicationListener(listener);
+ DirectChannel channel = context.getBean("inputAdvice", DirectChannel.class);
+ channel.send(new GenericMessage("hello"));
+ Assert.assertTrue(receivedEvent);
+ Assert.assertEquals(1, adviceCalled);
+ }
+
@Test //INT-2275
public void testInsideChain() {
+ receivedEvent = false;
ApplicationListener> listener = new ApplicationListener() {
public void onApplicationEvent(ApplicationEvent event) {
Object source = event.getSource();
@@ -103,6 +129,7 @@ public class EventOutboundChannelAdapterParserTests {
@Test(timeout=2000)
public void validateUsageWithPollableChannel() throws Exception {
+ receivedEvent = false;
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("EventOutboundChannelAdapterParserTestsWithPollable-context.xml", EventOutboundChannelAdapterParserTests.class);
final CyclicBarrier barier = new CyclicBarrier(2);
ApplicationListener> listener = new ApplicationListener() {
@@ -132,4 +159,13 @@ public class EventOutboundChannelAdapterParserTests {
Assert.assertTrue(receivedEvent);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java
index 3bac5a81ed..052318d5c0 100644
--- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java
+++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java
@@ -215,6 +215,8 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
@Override
public final void onInit() {
+ super.onInit();
+
this.evaluationContext.addPropertyAccessor(new MapAccessor());
final BeanFactory beanFactory = this.getBeanFactory();
diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java
index 591b7de360..3815df9bd1 100644
--- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java
+++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java
@@ -16,17 +16,16 @@
package org.springframework.integration.file.config;
-import org.w3c.dom.Element;
-
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
+import org.w3c.dom.Element;
/**
* Parser for the <outbound-channel-adapter/> element of the 'file'
* namespace.
- *
+ *
* @author Mark Fisher
* @author Iwein Fuld
* @author Oleg Zhurakousky
@@ -40,4 +39,10 @@ public class FileOutboundChannelAdapterParser extends AbstractOutboundChannelAda
return handlerBuilder.getBeanDefinition();
}
+ @Override
+ protected boolean isUsingReplyProducer() {
+ // cannot be automatically determined by superclass because we are using a factory bean.
+ return true;
+ }
+
}
diff --git a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd
index 4fbca60514..524a4ded55 100644
--- a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd
+++ b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd
@@ -255,9 +255,10 @@ Only files matching this regular expression will be picked up by this adapter.
-
+
-
+
+
diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml
index f4821a043f..6fed5a9bf8 100644
--- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml
@@ -47,7 +47,11 @@
+ directory="test">
+
+
+
+
message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
}
}
diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
index 2afba0e123..b105a54cb0 100644
--- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
+++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
@@ -19,7 +19,11 @@
+ auto-startup="false" order="777" filename-generator-expression="'foo.txt'">
+
+
+
+
("foo"));
+ assertEquals(1, adviceCalled);
}
/**
@@ -282,4 +287,13 @@ public class FileOutboundGatewayParserTests {
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.2.xsd b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.2.xsd
index 24e064c1d7..5ac4c3e054 100644
--- a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.2.xsd
+++ b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.2.xsd
@@ -20,6 +20,9 @@
+
+
+
@@ -232,6 +235,9 @@
+
+
+
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml
index 2adbd5ada3..ed5f351c6e 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml
@@ -59,7 +59,16 @@
channel="ftpChannel"
session-factory="cachingSessionFactory"
remote-directory="foo/bar"/>
-
+
+
+
+
+
+
+
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests.java
index 2cf4585dba..38fbce2e88 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests.java
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests.java
@@ -26,16 +26,18 @@ import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
-
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
/**
@@ -45,6 +47,8 @@ import org.springframework.integration.test.util.TestUtils;
*/
public class FtpOutboundChannelAdapterParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void testFtpOutboundChannelAdapterComplete() throws Exception{
ApplicationContext ac =
@@ -97,6 +101,15 @@ public class FtpOutboundChannelAdapterParserTests {
assertEquals(DefaultFtpSessionFactory.class, innerSfProperty.getClass());
}
+ @Test
+ public void adviceChain() {
+ ApplicationContext ac = new ClassPathXmlApplicationContext(
+ "FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
+ Object adapter = ac.getBean("advisedAdapter");
+ MessageHandler handler = TestUtils.getPropertyValue(adapter, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
@Test
public void testTemporaryFileSuffix() {
@@ -107,4 +120,13 @@ public class FtpOutboundChannelAdapterParserTests {
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"useTemporaryFileName"));
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
index b5dd3c5fae..60145b3ced 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
@@ -41,7 +41,11 @@
command-options="-P"
expression="payload"
order="2"
- />
+ >
+
+
+
+
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
index 33f67bcf1d..78ffb5cbc6 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
@@ -26,9 +26,12 @@ import java.util.Set;
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.endpoint.AbstractEndpoint;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -50,6 +53,8 @@ public class FtpOutboundGatewayParserTests {
@Autowired
AbstractEndpoint gateway2;
+ private static volatile int adviceCalled;
+
@Test
public void testGateway1() {
FtpOutboundGateway gateway = TestUtils.getPropertyValue(gateway1,
@@ -84,5 +89,17 @@ public class FtpOutboundGatewayParserTests {
@SuppressWarnings("unchecked")
Set options = TestUtils.getPropertyValue(gateway, "options", Set.class);
assertTrue(options.contains("-P"));
+ gateway.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
}
}
diff --git a/spring-integration-gemfire/src/main/resources/org/springframework/integration/gemfire/config/xml/spring-integration-gemfire-2.2.xsd b/spring-integration-gemfire/src/main/resources/org/springframework/integration/gemfire/config/xml/spring-integration-gemfire-2.2.xsd
index d5ceae6963..db4fb05c4e 100644
--- a/spring-integration-gemfire/src/main/resources/org/springframework/integration/gemfire/config/xml/spring-integration-gemfire-2.2.xsd
+++ b/spring-integration-gemfire/src/main/resources/org/springframework/integration/gemfire/config/xml/spring-integration-gemfire-2.2.xsd
@@ -132,7 +132,7 @@
writes Message to a Gemfire cache
-
+
@@ -142,7 +142,8 @@
-
+
+
diff --git a/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests-context.xml b/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests-context.xml
new file mode 100644
index 0000000000..713a1a335e
--- /dev/null
+++ b/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests-context.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests.java b/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests.java
index 0a10899d35..d1304b339d 100644
--- a/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests.java
+++ b/spring-integration-gemfire/src/test/java/org/springframework/integration/gemfire/config/xml/GemfireOutboundChannelAdapterParserTests.java
@@ -13,24 +13,51 @@
package org.springframework.integration.gemfire.config.xml;
-import org.junit.Test;
-import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
-import org.w3c.dom.Element;
-
+import static org.junit.Assert.assertEquals;
import static org.springframework.integration.gemfire.config.xml.ParserTestUtil.createFakeParserContext;
import static org.springframework.integration.gemfire.config.xml.ParserTestUtil.loadXMLFrom;
+import org.junit.Test;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
+import org.springframework.integration.MessageChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
+import org.w3c.dom.Element;
+
/**
* @author Dan Oxlade
*/
public class GemfireOutboundChannelAdapterParserTests {
- private GemfireOutboundChannelAdapterParser underTest = new GemfireOutboundChannelAdapterParser();
+ private GemfireOutboundChannelAdapterParser underTest = new GemfireOutboundChannelAdapterParser();
- @Test(expected = BeanDefinitionParsingException.class)
- public void regionIsARequiredAttribute() throws Exception {
- String xml = "";
- Element element = loadXMLFrom(xml).getDocumentElement();
- underTest.parseConsumer(element, createFakeParserContext());
- }
+ private volatile static int adviceCalled;
+
+ @Test(expected = BeanDefinitionParsingException.class)
+ public void regionIsARequiredAttribute() throws Exception {
+ String xml = "";
+ Element element = loadXMLFrom(xml).getDocumentElement();
+ underTest.parseConsumer(element, createFakeParserContext());
+ }
+
+ @Test
+ public void withAdvice() {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-context.xml", this.getClass());
+ MessageChannel channel = ctx.getBean("input", MessageChannel.class);
+ channel.send(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-groovy/src/main/resources/org/springframework/integration/groovy/config/spring-integration-groovy-2.2.xsd b/spring-integration-groovy/src/main/resources/org/springframework/integration/groovy/config/spring-integration-groovy-2.2.xsd
index 627fee4e21..dc60b9a20e 100644
--- a/spring-integration-groovy/src/main/resources/org/springframework/integration/groovy/config/spring-integration-groovy-2.2.xsd
+++ b/spring-integration-groovy/src/main/resources/org/springframework/integration/groovy/config/spring-integration-groovy-2.2.xsd
@@ -49,10 +49,11 @@
]]>
-
+
-
+
+
diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests-context.xml b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests-context.xml
index cc92b14d75..3272ca7af6 100644
--- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests-context.xml
+++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests-context.xml
@@ -21,7 +21,11 @@
+ customizer="groovyCustomizer">
+
+
+
+
diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests.java
index dc197d238d..531846b50b 100644
--- a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests.java
+++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyControlBusTests.java
@@ -20,12 +20,11 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import groovy.lang.GroovyObject;
import java.util.HashMap;
import java.util.Map;
-import groovy.lang.GroovyObject;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException;
@@ -36,6 +35,7 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageHandlingException;
import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
@@ -49,6 +49,7 @@ import org.springframework.web.context.request.RequestContextHolder;
/**
* @author Dave Syer
* @author Artem Bilan
+ * @author Gary Russell
* @since 2.0
*/
@ContextConfiguration
@@ -64,6 +65,8 @@ public class GroovyControlBusTests {
@Autowired
private MyGroovyCustomizer groovyCustomizer;
+ private static volatile int adviceCalled;
+
@Test
public void testOperationOfControlBus() { // long is > 3
this.groovyCustomizer.executed = false;
@@ -72,6 +75,7 @@ public class GroovyControlBusTests {
assertEquals("catbar", output.receive(0).getPayload());
assertNull(output.receive(0));
assertTrue(this.groovyCustomizer.executed);
+ assertEquals(1, adviceCalled);
}
@Test //INT-2567
@@ -201,4 +205,13 @@ public class GroovyControlBusTests {
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd
index 75902c0f34..63abaae351 100644
--- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd
+++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-2.2.xsd
@@ -1,11 +1,13 @@
+
-
+
-
+
+
@@ -509,9 +512,10 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
-
+
-
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
index 77d0a29fbe..08e59d432d 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
@@ -40,6 +40,12 @@
+
+
+
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
index 0b93513d47..3535b4e885 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
@@ -28,7 +28,6 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
-
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -41,8 +40,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.AbstractEndpoint;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -52,6 +55,7 @@ import org.springframework.web.client.RestTemplate;
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@@ -75,12 +79,16 @@ public class HttpOutboundChannelAdapterParserTests {
@Autowired @Qualifier("withUrlExpression")
private AbstractEndpoint withUrlExpression;
+ @Autowired @Qualifier("withAdvice")
+ private AbstractEndpoint withAdvice;
+
@Autowired @Qualifier("withUrlExpressionAndTemplate")
private AbstractEndpoint withUrlExpressionAndTemplate;
@Autowired
private ApplicationContext applicationContext;
+ private static volatile int adviceCalled;
@Test
public void minimalConfig() {
@@ -201,6 +209,13 @@ public class HttpOutboundChannelAdapterParserTests {
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
}
+ @Test
+ public void withAdvice() {
+ MessageHandler handler = TestUtils.getPropertyValue(this.withAdvice, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void withUrlExpressionAndTemplate() {
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlExpressionAndTemplate);
@@ -239,4 +254,13 @@ public class HttpOutboundChannelAdapterParserTests {
}
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
index b86162eb4a..57fbdd3f8b 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
@@ -42,6 +42,12 @@
+
+
+
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
index f70be245bb..37e15b8400 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
@@ -26,7 +26,6 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
-
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -37,9 +36,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.endpoint.AbstractEndpoint;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -48,6 +50,7 @@ import org.springframework.web.client.ResponseErrorHandler;
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@@ -62,9 +65,13 @@ public class HttpOutboundGatewayParserTests {
@Autowired @Qualifier("withUrlExpression")
private AbstractEndpoint withUrlExpressionEndpoint;
+ @Autowired @Qualifier("withAdvice")
+ private AbstractEndpoint withAdvice;
+
@Autowired
private ApplicationContext applicationContext;
+ private static volatile int adviceCalled;
@Test
public void minimalConfig() {
@@ -160,6 +167,13 @@ public class HttpOutboundGatewayParserTests {
assertEquals(false, handlerAccessor.getPropertyValue("transferCookies"));
}
+ @Test
+ public void withAdvice() {
+ HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) new DirectFieldAccessor(
+ this.withAdvice).getPropertyValue("handler");
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
public static class StubErrorHandler implements ResponseErrorHandler {
@@ -171,4 +185,13 @@ public class HttpOutboundGatewayParserTests {
}
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.2.xsd b/spring-integration-ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.2.xsd
index 16df61d304..5745e91552 100644
--- a/spring-integration-ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.2.xsd
+++ b/spring-integration-ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.2.xsd
@@ -84,6 +84,9 @@ message headers (ip_hostName). Default "true".
+
+
+
@@ -176,6 +179,9 @@ task executors such as a WorkManagerTaskExecutor.
+
+
+
@@ -298,6 +304,9 @@ task executors such as a WorkManagerTaskExecutor.
+
+
+
diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
index e3bfc95b9d..cbfd3564aa 100644
--- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
+++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/config/ParserUnitTests-context.xml
@@ -138,6 +138,15 @@
order="12"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
+ @Test
+ public void tcpAdvice() {
+ adviceCalled = 0;
+ this.tcpAdviceChannel.send(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
+ @Test
+ public void tcpGatewayAdvice() {
+ adviceCalled = 0;
+ this.tcpAdviceGateChannel.send(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void testOutTcp() {
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOut);
@@ -592,4 +631,14 @@ public class ParserUnitTests {
assertSame(socketFactorySupport, dfa.getPropertyValue("tcpSocketFactorySupport"));
assertSame(socketSupport, dfa.getPropertyValue("tcpSocketSupport"));
}
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
index 53474cbfdb..1a0639fb08 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/JdbcOutboundGateway.java
@@ -106,6 +106,7 @@ public class JdbcOutboundGateway extends AbstractReplyProducingMessageHandler im
@Override
protected void onInit() {
+ super.onInit();
if (this.maxRowsPerPoll != null) {
Assert.notNull(poller, "If you want to set 'maxRowsPerPoll', then you must provide a 'selectQuery'.");
diff --git a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.2.xsd b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.2.xsd
index 46198b45a6..ba12b7ef3f 100644
--- a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.2.xsd
+++ b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-2.2.xsd
@@ -245,9 +245,10 @@
-
+
-
+
+
@@ -334,7 +335,7 @@
-
+
@@ -357,7 +358,8 @@
-
+
+
@@ -652,6 +654,7 @@
+
@@ -787,6 +790,7 @@
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
index afd4ed0299..e460214d4a 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcMessageHandlerParserTests.java
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2012 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.
@@ -28,6 +28,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jdbc.JdbcMessageHandler;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
@@ -45,11 +46,13 @@ import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcMessageHandlerParserTests {
private JdbcTemplate jdbcTemplate;
-
+
private MessageChannel channel;
-
+
private ConfigurableApplicationContext context;
-
+
+ private static volatile int adviceCalled;
+
@Test
public void testSimpleOutboundChannelAdapter(){
setUp("handlingWithJdbcOperationsJdbcOutboundChannelAdapterTest.xml", getClass());
@@ -60,6 +63,7 @@ public class JdbcMessageHandlerParserTests {
assertEquals("Wrong id", "foo", map.get("name"));
JdbcMessageHandler handler = context.getBean(JdbcMessageHandler.class);
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
+ assertEquals(1, adviceCalled);
}
@Test
@@ -103,7 +107,7 @@ public class JdbcMessageHandlerParserTests {
assertEquals("Wrong id", message.getHeaders().getId().toString(), map.get("ID"));
assertEquals("Wrong name", "bar", map.get("name"));
}
-
+
@Test
public void testOutboundAdapterWithPoller() throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("JdbcOutboundAdapterWithPollerTest-context.xml", this.getClass());
@@ -132,11 +136,20 @@ public class JdbcMessageHandlerParserTests {
context.close();
}
}
-
+
public void setUp(String name, Class> cls){
context = new ClassPathXmlApplicationContext(name, cls);
jdbcTemplate = new JdbcTemplate(this.context.getBean("dataSource",DataSource.class));
channel = this.context.getBean("target", MessageChannel.class);
}
-
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
index 75b4f0a40f..79a1bf233d 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
@@ -32,6 +32,7 @@ import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.endpoint.PollingConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jdbc.JdbcOutboundGateway;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
@@ -55,6 +56,8 @@ public class JdbcOutboundGatewayParserTests {
private MessagingTemplate messagingTemplate;
+ private static volatile int adviceCalled;
+
@Test
public void testMapPayloadMapReply() {
setUp("handlingMapPayloadJdbcOutboundGatewayTest.xml", getClass());
@@ -71,6 +74,8 @@ public class JdbcOutboundGatewayParserTests {
assertEquals("bar", payload.get("name"));
JdbcOutboundGateway gateway = context.getBean(JdbcOutboundGateway.class);
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
+ Object gw = context.getBean("jdbcGateway");
+ assertEquals(1, adviceCalled);
}
@Test
@@ -230,4 +235,13 @@ public class JdbcOutboundGatewayParserTests {
setupMessagingTemplate();
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java
index 5ef56e90a3..13edd19973 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcMessageHandlerParserTests.java
@@ -27,14 +27,20 @@ import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.Expression;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.test.util.TestUtils;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
+ * @author Gary Russell
* @since 2.1
*
*/
@@ -44,6 +50,8 @@ public class StoredProcMessageHandlerParserTests {
private EventDrivenConsumer consumer;
+ private static volatile int adviceCalled;
+
@Test
public void testProcedureNameIsSet() throws Exception {
setUp("basicStoredProcOutboundChannelAdapterTest.xml", getClass());
@@ -149,6 +157,15 @@ public class StoredProcMessageHandlerParserTests {
}
+ @Test
+ public void adviceCalled() throws Exception {
+ setUp("advisedStoredProcOutboundChannelAdapterTest.xml", getClass());
+
+ MessageHandler handler = TestUtils.getPropertyValue(this.consumer, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@After
public void tearDown(){
if(context != null){
@@ -161,4 +178,13 @@ public class StoredProcMessageHandlerParserTests {
consumer = this.context.getBean("storedProcedureOutboundChannelAdapter", EventDrivenConsumer.class);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
index 027be53dbe..cfe9a4dfa0 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
@@ -30,10 +30,15 @@ import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.Expression;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jdbc.storedproc.PrimeMapper;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.test.util.TestUtils;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlInOutParameter;
import org.springframework.jdbc.core.SqlOutParameter;
@@ -41,6 +46,7 @@ import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
+ * @author Gary Russell
* @since 2.1
*
*/
@@ -50,6 +56,8 @@ public class StoredProcOutboundGatewayParserTests {
private EventDrivenConsumer outboundGateway;
+ private static volatile int adviceCalled;
+
@Test
public void testProcedureNameIsSet() throws Exception {
setUp("storedProcOutboundGatewayParserTest.xml", getClass());
@@ -206,6 +214,15 @@ public class StoredProcOutboundGatewayParserTests {
}
+ @Test
+ public void advised() throws Exception {
+ setUp("advisedStoredProcOutboundGatewayParserTest.xml", getClass());
+
+ MessageHandler handler = TestUtils.getPropertyValue(this.outboundGateway, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@After
public void tearDown(){
if(context != null){
@@ -218,4 +235,13 @@ public class StoredProcOutboundGatewayParserTests {
this.outboundGateway = this.context.getBean("storedProcedureOutboundGateway", EventDrivenConsumer.class);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundChannelAdapterTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundChannelAdapterTest.xml
new file mode 100644
index 0000000000..bf0dc8f6e6
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundChannelAdapterTest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundGatewayParserTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundGatewayParserTest.xml
new file mode 100644
index 0000000000..c9477ef1d1
--- /dev/null
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/advisedStoredProcOutboundGatewayParserTest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
index d081186d5e..e23878060a 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
@@ -17,7 +17,11 @@
+ request-channel="target" reply-channel="output" data-source="dataSource" order="23">
+
+
+
+
+ channel="target" jdbc-operations="jdbcTemplate" order="23">
+
+
+
+
diff --git a/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java b/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java
index e97363b404..91de46dbe3 100644
--- a/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java
+++ b/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java
@@ -50,7 +50,7 @@ import org.springframework.util.Assert;
/**
* An outbound Messaging Gateway for request/reply JMS.
- *
+ *
* @author Mark Fisher
* @author Arjen Poutsma
* @author Juergen Hoeller
@@ -182,7 +182,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
* Specify whether the request destination is a Topic. This value is
* necessary when providing a destination name for a Topic rather than
* a destination reference.
- *
+ *
* @param requestPubSubDomain true if the request destination is a Topic
*/
public void setRequestPubSubDomain(boolean requestPubSubDomain) {
@@ -193,7 +193,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
* Specify whether the reply destination is a Topic. This value is
* necessary when providing a destination name for a Topic rather than
* a destination reference.
- *
+ *
* @param replyPubSubDomain true if the reply destination is a Topic
*/
public void setReplyPubSubDomain(boolean replyPubSubDomain) {
@@ -275,8 +275,8 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
}
/**
- * This property describes how a JMS Message should be generated from the
- * Spring Integration Message. If set to 'true', the body of the JMS Message will be
+ * This property describes how a JMS Message should be generated from the
+ * Spring Integration Message. If set to 'true', the body of the JMS Message will be
* created from the Spring Integration Message's payload (via the MessageConverter).
* If set to 'false', then the entire Spring Integration Message will serve as
* the base for JMS Message creation. Since the JMS Message is created by the
@@ -284,7 +284,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
* the entire Spring Integration Message or only its payload.
*
* Default is 'true'
- *
+ *
* @param extractRequestPayload
*/
public void setExtractRequestPayload(boolean extractRequestPayload) {
@@ -297,7 +297,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
* created from the JMS Reply Message's body (via MessageConverter).
* Otherwise, the entire JMS Message will become the payload of the
* Spring Integration Message.
- *
+ *
* @param extractReplyPayload
*/
public void setExtractReplyPayload(boolean extractReplyPayload) {
@@ -312,6 +312,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
this.setOutputChannel(replyChannel);
}
+ @Override
public String getComponentType() {
return "jms:outbound-gateway";
}
@@ -369,6 +370,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
^ this.requestDestinationName != null
^ this.requestDestinationExpressionProcessor != null,
"Exactly one of 'requestDestination', 'requestDestinationName', or 'requestDestinationExpression' is required.");
+ super.onInit();
if (this.requestDestinationExpressionProcessor != null) {
this.requestDestinationExpressionProcessor.setBeanFactory(getBeanFactory());
this.requestDestinationExpressionProcessor.setConversionService(getConversionService());
@@ -516,7 +518,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
"because that ID can only be provided to a MessageSelector after the reuqest Message has been sent thereby " +
"creating a race condition where a fast response might be sent before the MessageConsumer has been created. " +
"Consider providing a value to the 'correlationKey' property of this gateway instead. Then the MessageConsumer " +
- "will be created before the request Message is sent.");
+ "will be created before the request Message is sent.");
}
MessageProducer messageProducer = null;
MessageConsumer messageConsumer = null;
@@ -554,7 +556,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler {
*/
private void deleteDestinationIfTemporary(Destination destination) {
try {
- if (destination instanceof TemporaryQueue) {
+ if (destination instanceof TemporaryQueue) {
((TemporaryQueue) destination).delete();
}
else if (destination instanceof TemporaryTopic) {
diff --git a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.2.xsd b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.2.xsd
index 62ae297da3..5c53c83dfe 100644
--- a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.2.xsd
+++ b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-2.2.xsd
@@ -731,9 +731,10 @@
-
+
-
+
+
@@ -967,9 +968,10 @@
-
+
-
+
+
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundChannelAdapterParserTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundChannelAdapterParserTests.java
index 370e302313..ac97178ecf 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundChannelAdapterParserTests.java
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundChannelAdapterParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -23,20 +23,27 @@ import static org.junit.Assert.assertTrue;
import javax.jms.DeliveryMode;
import org.junit.Test;
-
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jms.JmsHeaderMapper;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.test.util.TestUtils;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MessageConverter;
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
public class JmsOutboundChannelAdapterParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void adapterWithConnectionFactoryAndDestination() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
@@ -47,6 +54,16 @@ public class JmsOutboundChannelAdapterParserTests {
assertNotNull(accessor.getPropertyValue("jmsTemplate"));
}
+ @Test
+ public void advisedAdapter() {
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ "jmsOutboundWithConnectionFactoryAndDestination.xml", this.getClass());
+ EventDrivenConsumer endpoint = (EventDrivenConsumer) context.getBean("advised");
+ MessageHandler handler = TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void adapterWithConnectionFactoryAndDestinationName() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
@@ -164,4 +181,13 @@ public class JmsOutboundChannelAdapterParserTests {
assertEquals(false, accessor.getPropertyValue("explicitQosEnabled"));
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
index 3702c1af56..4d4ca31b1c 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2011 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -30,7 +30,6 @@ import javax.jms.DeliveryMode;
import org.junit.Test;
import org.mockito.Mockito;
-
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
@@ -41,9 +40,11 @@ import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.core.SubscribableChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.endpoint.PollingConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.jms.JmsOutboundGateway;
import org.springframework.integration.jms.StubMessageConverter;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.jms.support.converter.MessageConverter;
@@ -51,9 +52,12 @@ import org.springframework.jms.support.converter.MessageConverter;
* @author Jonas Partner
* @author Oleg Zhurakousky
* @author Mark Fisher
+ * @author Gary Russell
*/
public class JmsOutboundGatewayParserTests {
-
+
+ private static volatile int adviceCalled;
+
@Test
public void testWithDeliveryPersistentAttribute(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
@@ -66,6 +70,16 @@ public class JmsOutboundGatewayParserTests {
assertEquals(DeliveryMode.PERSISTENT, deliveryMode);
}
+ @Test
+ public void testAdvised(){
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
+ "jmsOutboundGatewayWithDeliveryPersistent.xml", this.getClass());
+ EventDrivenConsumer endpoint = (EventDrivenConsumer) context.getBean("advised");
+ JmsOutboundGateway gateway = TestUtils.getPropertyValue(endpoint, "handler", JmsOutboundGateway.class);
+ gateway.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void testDefault(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
@@ -88,7 +102,7 @@ public class JmsOutboundGatewayParserTests {
Object order = accessor.getPropertyValue("order");
assertEquals(99, order);
}
-
+
@Test
public void gatewayMaintainsReplyChannelAndInboundHistory() {
ActiveMqTestUtils.prepare();
@@ -96,7 +110,7 @@ public class JmsOutboundGatewayParserTests {
"gatewayMaintainsReplyChannel.xml", this.getClass());
SampleGateway gateway = context.getBean("gateway", SampleGateway.class);
SubscribableChannel jmsInput = context.getBean("jmsInput", SubscribableChannel.class);
- MessageHandler handler = new MessageHandler() {
+ MessageHandler handler = new MessageHandler() {
public void handleMessage(Message> message) throws MessagingException {
MessageHistory history = MessageHistory.read(message);
assertNotNull(history);
@@ -139,11 +153,20 @@ public class JmsOutboundGatewayParserTests {
public static interface SampleGateway{
public String echo(String value);
}
-
+
public static class SampleService{
public String echo(String value){
return value.toUpperCase();
}
}
-
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
index 9b9b65c1b4..b6f8e6074e 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
@@ -24,5 +24,14 @@
-
+
+
+
+
+
+
+
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundWithConnectionFactoryAndDestination.xml b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundWithConnectionFactoryAndDestination.xml
index 1daa93aac5..7681480200 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundWithConnectionFactoryAndDestination.xml
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundWithConnectionFactoryAndDestination.xml
@@ -27,4 +27,13 @@
+
+
+
+
+
+
diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/OperationInvokingMessageHandler.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/OperationInvokingMessageHandler.java
index 363f304c80..5a47131102 100644
--- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/OperationInvokingMessageHandler.java
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/OperationInvokingMessageHandler.java
@@ -103,6 +103,7 @@ public class OperationInvokingMessageHandler extends AbstractReplyProducingMessa
@Override
public final void onInit() {
Assert.notNull(this.server, "MBeanServer is required.");
+ super.onInit();
}
@Override
diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParser.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParser.java
index 501fbb80d0..113e3c69f3 100644
--- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParser.java
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -16,16 +16,17 @@
package org.springframework.integration.jmx.config;
-import org.w3c.dom.Element;
-
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
+import org.springframework.integration.jmx.NotificationPublishingMessageHandler;
+import org.w3c.dom.Element;
/**
* @author Mark Fisher
+ * @author Gary Russell
* @since 2.0
*/
public class NotificationPublishingChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@@ -37,8 +38,8 @@ public class NotificationPublishingChannelAdapterParser extends AbstractOutbound
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
- "org.springframework.integration.jmx.NotificationPublishingMessageHandler");
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder
+ .rootBeanDefinition(NotificationPublishingMessageHandler.class);
builder.addConstructorArgValue(element.getAttribute("object-name"));
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-notification-type");
return builder.getBeanDefinition();
diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParser.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParser.java
index 55c22940e3..2319aca529 100644
--- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParser.java
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -16,16 +16,17 @@
package org.springframework.integration.jmx.config;
-import org.w3c.dom.Element;
-
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
+import org.springframework.integration.jmx.OperationInvokingMessageHandler;
+import org.w3c.dom.Element;
/**
* @author Mark Fisher
+ * @author Gary Russell
* @since 2.0
*/
public class OperationInvokingChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@@ -37,8 +38,7 @@ public class OperationInvokingChannelAdapterParser extends AbstractOutboundChann
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
- "org.springframework.integration.jmx.OperationInvokingMessageHandler");
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(OperationInvokingMessageHandler.class);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "server");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "object-name");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "operation-name");
diff --git a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.2.xsd b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.2.xsd
index 7f0a939f52..05cd858d68 100644
--- a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.2.xsd
+++ b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.2.xsd
@@ -42,6 +42,9 @@
+
+
+
@@ -58,6 +61,9 @@
+
+
+
@@ -90,6 +96,9 @@
+
+
+
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests-context.xml
index d8b1f8c8db..58be1e19da 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests-context.xml
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests-context.xml
@@ -22,7 +22,11 @@
+ default-notification-type="default.type">
+
+
+
+
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests.java
index b3dc8b303d..015c7025fa 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests.java
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/NotificationPublishingChannelAdapterParserTests.java
@@ -28,6 +28,7 @@ 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.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jmx.JmxHeaders;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.test.context.ContextConfiguration;
@@ -36,6 +37,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @author Artem Bilan
+ * @author Gary Russell
* @since 2.0
*/
@ContextConfiguration
@@ -51,6 +53,8 @@ public class NotificationPublishingChannelAdapterParserTests {
@Autowired
private MessageChannel publishingWithinChainChannel;
+ private static volatile int adviceCalled;
+
@After
public void clearListener() {
listener.lastNotification = null;
@@ -59,6 +63,7 @@ public class NotificationPublishingChannelAdapterParserTests {
@Test
public void publishStringMessage() throws Exception {
+ adviceCalled = 0;
assertNull(listener.lastNotification);
Message> message = MessageBuilder.withPayload("XYZ")
.setHeader(JmxHeaders.NOTIFICATION_TYPE, "test.type").build();
@@ -68,6 +73,7 @@ public class NotificationPublishingChannelAdapterParserTests {
assertEquals("XYZ", notification.getMessage());
assertEquals("test.type", notification.getType());
assertNull(notification.getUserData());
+ assertEquals(1, adviceCalled);
}
@Test
@@ -110,4 +116,15 @@ public class NotificationPublishingChannelAdapterParserTests {
private static class TestData {
}
+ public static class FooADvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ System.out.println("foo");
+ new RuntimeException("foo").printStackTrace();
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests-context.xml
index 642f15d064..4c6ec94578 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests-context.xml
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingChannelAdapterParserTests-context.xml
@@ -18,7 +18,11 @@
+ operation-name="test">
+
+
+
+
("test2"));
input.send(new GenericMessage("test3"));
assertEquals(3, testBean.messages.size());
+ assertEquals(3, adviceCalled);
}
@Test
@@ -118,4 +122,14 @@ public class OperationInvokingChannelAdapterParserTests {
.setHeader(JmxHeaders.OBJECT_NAME, "org.springframework.integration.jmx.config:type=TestBean,name=foo")
.setHeader(JmxHeaders.OPERATION_NAME, "blah").build();
}
+
+ public static class FooADvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
index f9742c7275..64482bbe5d 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
@@ -27,7 +27,11 @@
+ operation-name="testWithReturn">
+
+
+
+
) withReplyChannelOutput.receive().getPayload()).size());
withReplyChannel.send(new GenericMessage("3"));
assertEquals(3, ((List>) withReplyChannelOutput.receive().getPayload()).size());
+ assertEquals(3, adviceCalled);
}
@Test
@@ -94,4 +99,13 @@ public class OperationInvokingOutboundGatewayTests {
assertEquals(3, ((List>) withReplyChannelOutput.receive().getPayload()).size());
}
+ public static class FooADvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/JpaOutboundChannelAdapterParser.java b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/JpaOutboundChannelAdapterParser.java
index bc6b40d662..22e7b698ae 100644
--- a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/JpaOutboundChannelAdapterParser.java
+++ b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/JpaOutboundChannelAdapterParser.java
@@ -73,11 +73,16 @@ public class JpaOutboundChannelAdapterParser extends AbstractOutboundChannelAdap
BeanDefinition txAdviceDefinition = IntegrationNamespaceUtils.configureTransactionAttributes(transactionalElement);
ManagedList adviceChain = new ManagedList();
adviceChain.add(txAdviceDefinition);
- jpaOutboundChannelAdapterBuilder.addPropertyValue("adviceChain", adviceChain);
+ jpaOutboundChannelAdapterBuilder.addPropertyValue("txAdviceChain", adviceChain);
}
return jpaOutboundChannelAdapterBuilder.getBeanDefinition();
}
+ @Override
+ protected boolean isUsingReplyProducer() {
+ return true;
+ }
+
}
diff --git a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
index 439027b6c3..3914d23c83 100644
--- a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
+++ b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
@@ -39,19 +39,34 @@ import org.springframework.util.CollectionUtils;
*
* @author Amol Nayak
* @author Gunnar Hillert
+ * @author Gary Russell
* @since 2.2
*
*/
public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean {
- private final JpaExecutor jpaExecutor;
+ private final JpaExecutor jpaExecutor;
+
private OutboundGatewayType gatewayType = OutboundGatewayType.UPDATING;
+ /**
+ * <transactional /> element applies to entire flow from this point
+ */
+ private volatile List txAdviceChain;
+
+ /**
+ * <request-handler-advice-chain /> only applies to the handleRequestMessage.
+ */
private volatile List adviceChain;
+
private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
+
private boolean producesReply = true;
+
private MessageChannel outputChannel;
+
private int order;
+
private long replyTimeout;
/**
@@ -69,34 +84,8 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean getObjectType() {
- return MessageHandler.class;
- }
-
- @Override
- protected MessageHandler createInstance() {
-
- JpaOutboundGateway jpaOutboundGateway = new JpaOutboundGateway(jpaExecutor);
- jpaOutboundGateway.setGatewayType(this.gatewayType);
- jpaOutboundGateway.setProducesReply(this.producesReply);
- jpaOutboundGateway.setOutputChannel(this.outputChannel);
- jpaOutboundGateway.setOrder(this.order);
- jpaOutboundGateway.setSendTimeout(replyTimeout);
-
- if (!CollectionUtils.isEmpty(this.adviceChain)) {
-
- ProxyFactory proxyFactory = new ProxyFactory(jpaOutboundGateway);
- if (!CollectionUtils.isEmpty(adviceChain)) {
- for (Advice advice : adviceChain) {
- proxyFactory.addAdvice(advice);
- }
- }
-
- return (MessageHandler) proxyFactory.getProxy(this.beanClassLoader);
- }
-
- return jpaOutboundGateway;
+ public void setTxAdviceChain(List txAdviceChain) {
+ this.txAdviceChain = txAdviceChain;
}
public void setAdviceChain(List adviceChain) {
@@ -125,7 +114,38 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean getObjectType() {
+ return MessageHandler.class;
+ }
+ @Override
+ protected MessageHandler createInstance() {
+ JpaOutboundGateway jpaOutboundGateway = new JpaOutboundGateway(jpaExecutor);
+ jpaOutboundGateway.setGatewayType(this.gatewayType);
+ jpaOutboundGateway.setProducesReply(this.producesReply);
+ jpaOutboundGateway.setOutputChannel(this.outputChannel);
+ jpaOutboundGateway.setOrder(this.order);
+ jpaOutboundGateway.setSendTimeout(replyTimeout);
+ if (this.adviceChain != null) {
+ jpaOutboundGateway.setAdviceChain(this.adviceChain);
+ }
+ jpaOutboundGateway.afterPropertiesSet();
+
+ if (!CollectionUtils.isEmpty(this.txAdviceChain)) {
+
+ ProxyFactory proxyFactory = new ProxyFactory(jpaOutboundGateway);
+ if (!CollectionUtils.isEmpty(txAdviceChain)) {
+ for (Advice advice : txAdviceChain) {
+ proxyFactory.addAdvice(advice);
+ }
+ }
+
+ return (MessageHandler) proxyFactory.getProxy(this.beanClassLoader);
+ }
+
+ return jpaOutboundGateway;
+ }
}
diff --git a/spring-integration-jpa/src/main/resources/org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd b/spring-integration-jpa/src/main/resources/org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd
index a3b3fcb6b3..33a0068d92 100644
--- a/spring-integration-jpa/src/main/resources/org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd
+++ b/spring-integration-jpa/src/main/resources/org/springframework/integration/jpa/config/xml/spring-integration-jpa-2.2.xsd
@@ -9,7 +9,7 @@
+ schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.2.xsd" />
+
@@ -187,6 +188,7 @@
+
@@ -218,6 +220,7 @@
+
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.java b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.java
index 39f3421cd5..78e7df421f 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.java
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.java
@@ -24,12 +24,16 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
import org.springframework.integration.channel.AbstractMessageChannel;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jpa.core.JpaExecutor;
import org.springframework.integration.jpa.core.JpaOperations;
import org.springframework.integration.jpa.support.JpaParameter;
import org.springframework.integration.jpa.support.PersistMode;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
/**
@@ -44,6 +48,8 @@ public class JpaMessageHandlerParserTests {
private EventDrivenConsumer consumer;
+ private static volatile int adviceCalled;
+
@Test
public void testJpaMessageHandlerParser() throws Exception {
setUp("JpaMessageHandlerParserTests.xml", getClass());
@@ -77,6 +83,47 @@ public class JpaMessageHandlerParserTests {
}
+ @Test
+ public void advised() throws Exception {
+ setUp("JpaMessageHandlerParserTests.xml", getClass());
+
+ EventDrivenConsumer consumer = this.context.getBean("advised", EventDrivenConsumer.class);
+
+ final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(consumer, "inputChannel", AbstractMessageChannel.class);
+
+ assertEquals("target", inputChannel.getComponentName());
+
+ final MessageHandler handler = TestUtils.getPropertyValue(consumer, "handler", MessageHandler.class);
+
+ adviceCalled = 0;
+
+ handler.handleMessage(new GenericMessage("foo"));
+
+ assertEquals(1, adviceCalled);
+ }
+
+ /*
+ * Tests that an already advised handler (tx) gets the request handler advice added to its chain.
+ */
+ @Test
+ public void advisedAndTransactional() throws Exception {
+ setUp("JpaMessageHandlerParserTests.xml", getClass());
+
+ EventDrivenConsumer consumer = this.context.getBean("advisedAndTransactional", EventDrivenConsumer.class);
+
+ final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(consumer, "inputChannel", AbstractMessageChannel.class);
+
+ assertEquals("target", inputChannel.getComponentName());
+
+ final MessageHandler handler = TestUtils.getPropertyValue(consumer, "handler", MessageHandler.class);
+
+ adviceCalled = 0;
+
+ handler.handleMessage(new GenericMessage("foo"));
+
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void testJpaMessageHandlerParserWithEntityManagerFactory() throws Exception {
setUp("JpaMessageHandlerParserTestsWithEmFactory.xml", getClass());
@@ -156,7 +203,7 @@ public class JpaMessageHandlerParserTests {
assertNotNull(context.getBean("jpaOutboundChannelAdapter.jpaExecutor", JpaExecutor.class));
}
-
+
@After
public void tearDown(){
if(context != null){
@@ -169,4 +216,13 @@ public class JpaMessageHandlerParserTests {
consumer = this.context.getBean("jpaOutboundChannelAdapter", EventDrivenConsumer.class);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.xml b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.xml
index 93e455e3fa..588dbad2b1 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.xml
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaMessageHandlerParserTests.xml
@@ -26,4 +26,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
index 22413e1140..6bd1758a64 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
@@ -20,18 +20,22 @@ import org.junit.After;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jpa.core.JpaExecutor;
import org.springframework.integration.jpa.core.JpaOperations;
import org.springframework.integration.jpa.outbound.JpaOutboundGateway;
import org.springframework.integration.jpa.support.OutboundGatewayType;
import org.springframework.integration.jpa.support.PersistMode;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
/**
* @author Gunnar Hillert
* @author Amol Nayak
+ * @author Gary Russell
* @since 2.2
*
*/
@@ -41,6 +45,8 @@ public class JpaOutboundGatewayParserTests {
private EventDrivenConsumer consumer;
+ private static volatile int adviceCalled;
+
@Test
public void testRetrievingJpaOutboundGatewayParser() throws Exception {
setUp("JpaOutboundGatewayParserTests.xml", getClass(), "retrievingJpaOutboundGateway");
@@ -126,6 +132,16 @@ public class JpaOutboundGatewayParserTests {
}
+ @Test
+ public void advised() throws Exception {
+ setUp("JpaOutboundGatewayParserTests.xml", getClass(), "updatingJpaOutboundGateway");
+
+ EventDrivenConsumer consumer = this.context.getBean("advised", EventDrivenConsumer.class);
+ final JpaOutboundGateway jpaOutboundGateway = TestUtils.getPropertyValue(consumer, "handler", JpaOutboundGateway.class);
+ jpaOutboundGateway.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void testJpaExecutorBeanIdNaming() throws Exception {
@@ -148,4 +164,13 @@ public class JpaOutboundGatewayParserTests {
consumer = this.context.getBean(gatewayId, EventDrivenConsumer.class);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
index e081b85db5..9cffc8b0cc 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
@@ -36,4 +36,19 @@
reply-channel="out"
reply-timeout="100"/>
+
+
+
+
+
+
diff --git a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.2.xsd b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.2.xsd
index 63006186a5..ea240f4b1e 100644
--- a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.2.xsd
+++ b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.2.xsd
@@ -26,9 +26,10 @@
Defines an outbound mail-sending Channel Adapter.
-
+
-
+
+
diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParserTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParserTests.java
index 7ae2580037..5c650d77ff 100644
--- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParserTests.java
+++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/MailOutboundChannelAdapterParserTests.java
@@ -16,27 +16,33 @@
package org.springframework.integration.mail.config;
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
import java.util.Properties;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
import org.springframework.integration.channel.QueueChannel;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.PollingConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.mail.MailSendingMessageHandler;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.mail.MailSender;
-import static junit.framework.Assert.assertEquals;
-
-import static org.junit.Assert.assertNotNull;
-
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
public class MailOutboundChannelAdapterParserTests {
+ public static volatile int adviceCalled;
+
@Test
public void adapterWithMailSenderReference() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -50,6 +56,17 @@ public class MailOutboundChannelAdapterParserTests {
assertEquals(23, fieldAccessor.getPropertyValue("order"));
}
+ @Test
+ public void advised() {
+ ApplicationContext context = new ClassPathXmlApplicationContext(
+ "mailOutboundChannelAdapterParserTests.xml", this.getClass());
+ Object adapter = context.getBean("advised.adapter");
+ MessageHandler handler = (MessageHandler)
+ new DirectFieldAccessor(adapter).getPropertyValue("handler");
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void adapterWithHostProperty() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -61,7 +78,7 @@ public class MailOutboundChannelAdapterParserTests {
MailSender mailSender = (MailSender) fieldAccessor.getPropertyValue("mailSender");
assertNotNull(mailSender);
}
-
+
@Test
public void adapterWithPollableChannel() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -70,7 +87,7 @@ public class MailOutboundChannelAdapterParserTests {
QueueChannel pollableChannel = TestUtils.getPropertyValue(pc, "inputChannel", QueueChannel.class);
assertEquals("pollableChannel", pollableChannel.getComponentName());
}
-
+
@Test
public void adapterWithJavaMailProperties() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -87,4 +104,13 @@ public class MailOutboundChannelAdapterParserTests {
assertEquals("true", javaMailProperties.get("mail.smtps.auth"));
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/mailOutboundChannelAdapterParserTests.xml b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/mailOutboundChannelAdapterParserTests.xml
index 55b32ce0c8..b8e242e922 100644
--- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/mailOutboundChannelAdapterParserTests.xml
+++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/mailOutboundChannelAdapterParserTests.xml
@@ -32,4 +32,11 @@
+
+
+
+
+
+
diff --git a/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-2.2.xsd b/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-2.2.xsd
index 5ed498f799..ff7d8d0135 100644
--- a/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-2.2.xsd
+++ b/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-2.2.xsd
@@ -63,9 +63,10 @@
-
+
-
+
+
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
index d219fcefea..d6043ce61b 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
@@ -27,6 +27,7 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.rmi.RmiInboundGateway;
import org.springframework.integration.rmi.RmiOutboundGateway;
@@ -42,6 +43,8 @@ public class RmiOutboundGatewayParserTests {
private final QueueChannel testChannel = new QueueChannel();
+ private static volatile int adviceCalled;
+
@Before
public void setupTestInboundGateway() throws Exception {
testChannel.setBeanName("testChannel");
@@ -55,7 +58,7 @@ public class RmiOutboundGatewayParserTests {
public void testOrder() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"rmiOutboundGatewayParserTests.xml", this.getClass());
- RmiOutboundGateway gateway = context.getBean(RmiOutboundGateway.class);
+ RmiOutboundGateway gateway = context.getBean("gateway.handler", RmiOutboundGateway.class);
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
}
@@ -63,11 +66,12 @@ public class RmiOutboundGatewayParserTests {
public void directInvocation() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"rmiOutboundGatewayParserTests.xml", this.getClass());
- MessageChannel localChannel = (MessageChannel) context.getBean("localChannel");
+ MessageChannel localChannel = (MessageChannel) context.getBean("advisedChannel");
localChannel.send(new GenericMessage("test"));
Message> result = testChannel.receive(1000);
assertNotNull(result);
assertEquals("test", result.getPayload());
+ assertEquals(1, adviceCalled);
}
@Test //INT-1029
@@ -93,4 +97,13 @@ public class RmiOutboundGatewayParserTests {
assertEquals("TEST", result.getPayload());
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return callback.execute();
+ }
+
+ }
}
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
index 1e3c4b80ed..8254ef1ccb 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
@@ -18,6 +18,17 @@
remote-channel="testChannel"
host="localhost"/>
+
+
+
+
+
+
+
+
diff --git a/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-2.2.xsd b/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-2.2.xsd
index ebccdbca7a..1170d41246 100644
--- a/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-2.2.xsd
+++ b/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-2.2.xsd
@@ -21,7 +21,9 @@
-
+
+
+
@@ -235,7 +237,9 @@
-
+
+
+
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml
index f0ce6448e3..04c984ca6f 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml
@@ -50,6 +50,17 @@
charset="UTF-8"
use-temporary-file-name="false"
remote-directory="foo/bar"/>
+
+
+
+
+
+
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests.java
index 7d9931708d..c00137efef 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests.java
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests.java
@@ -27,19 +27,21 @@ import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
-
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.expression.spel.standard.SpelExpression;
+import org.springframework.integration.Message;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.integration.test.util.TestUtils;
@@ -50,6 +52,8 @@ import org.springframework.integration.test.util.TestUtils;
*/
public class OutboundChannelAdapterParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void testOutboundChannelAdapterWithId(){
ApplicationContext context =
@@ -117,6 +121,16 @@ public class OutboundChannelAdapterParserTests {
assertFalse((Boolean)TestUtils.getPropertyValue(handler,"useTemporaryFileName"));
}
+ @Test
+ public void advised(){
+ ApplicationContext context =
+ new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context.xml", this.getClass());
+ Object consumer = context.getBean("advised");
+ MessageHandler handler = TestUtils.getPropertyValue(consumer, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test(expected=BeanDefinitionStoreException.class)
public void testFailWithRemoteDirAndExpression(){
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context-fail.xml", this.getClass());
@@ -128,4 +142,14 @@ public class OutboundChannelAdapterParserTests {
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context-fail-fileFileGen.xml", this.getClass());
}
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
index 32baa477af..95484539ce 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
@@ -43,6 +43,24 @@
order="2"
/>
+
+
+
+
+
+
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
index 60b246ae02..dd459a44c6 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
@@ -26,8 +26,11 @@ import java.util.Set;
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.endpoint.AbstractEndpoint;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.sftp.gateway.SftpOutboundGateway;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
@@ -50,6 +53,11 @@ public class SftpOutboundGatewayParserTests {
@Autowired
AbstractEndpoint gateway2;
+ @Autowired
+ AbstractEndpoint advised;
+
+ private static volatile int adviceCalled;
+
@Test
public void testGateway1() {
SftpOutboundGateway gateway = TestUtils.getPropertyValue(gateway1,
@@ -85,4 +93,22 @@ public class SftpOutboundGatewayParserTests {
Set options = TestUtils.getPropertyValue(gateway, "options", Set.class);
assertTrue(options.contains("-P"));
}
+
+ @Test
+ public void advised() {
+ SftpOutboundGateway gateway = TestUtils.getPropertyValue(advised,
+ "handler", SftpOutboundGateway.class);
+ gateway.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.2.xsd b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.2.xsd
index 4d969ce032..1f3269d07d 100644
--- a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.2.xsd
+++ b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.2.xsd
@@ -159,6 +159,9 @@
+
+
+
diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml
index 2a14b52895..e3c6e36120 100644
--- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml
+++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml
@@ -29,6 +29,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java
index 9a56a8280f..d8a50ea46d 100644
--- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java
+++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2011 the original author or authors.
+ * Copyright 2002-2012 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.
@@ -17,12 +17,16 @@
package org.springframework.integration.twitter.config;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
import org.junit.Test;
-
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
@@ -33,13 +37,32 @@ import org.springframework.integration.twitter.outbound.DirectMessageSendingMess
*/
public class TestSendingMessageHandlerParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void testSendingMessageHandlerSuccessfulBootstrap(){
ApplicationContext ac = new ClassPathXmlApplicationContext("TestSendingMessageHandlerParser-context.xml", this.getClass());
EventDrivenConsumer dmAdapter = ac.getBean("dmAdapter", EventDrivenConsumer.class);
- Object handler = TestUtils.getPropertyValue(dmAdapter, "handler");
+ MessageHandler handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
assertEquals(DirectMessageSendingMessageHandler.class, handler.getClass());
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
+ dmAdapter = ac.getBean("dmAdvised", EventDrivenConsumer.class);
+ handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ MessageHandler handler2 = TestUtils.getPropertyValue(ac.getBean("advised"), "handler", MessageHandler.class);
+ assertNotSame(handler, handler2);
+ handler2.handleMessage(new GenericMessage("foo"));
+ assertEquals(2, adviceCalled);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-2.2.xsd b/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-2.2.xsd
index 1e20f1bf66..ce308ea07e 100644
--- a/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-2.2.xsd
+++ b/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-2.2.xsd
@@ -29,6 +29,7 @@
+
diff --git a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
index 472a98075e..849f9f9db8 100644
--- a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
+++ b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
@@ -16,17 +16,24 @@
package org.springframework.integration.ws.config;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
+
import java.util.List;
import org.junit.Test;
-
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.endpoint.PollingConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
@@ -40,18 +47,16 @@ import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import static org.junit.Assert.assertNull;
-
/**
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gunnar Hillert
+ * @author Gary Russell
*/
public class WebServiceOutboundGatewayParserTests {
+ private static volatile int adviceCalled;
+
@Test
public void simpleGatewayWithReplyChannel() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -360,6 +365,17 @@ public class WebServiceOutboundGatewayParserTests {
assertEquals("Wrong DestinationProvider", stubProvider,destinationProviderObject);
}
+ @Test
+ public void advised() {
+ ApplicationContext context = new ClassPathXmlApplicationContext(
+ "simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
+ AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithAdvice");
+ assertEquals(EventDrivenConsumer.class, endpoint.getClass());
+ MessageHandler handler = TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test(expected = BeanDefinitionParsingException.class)
public void invalidGatewayWithBothUriAndDestinationProvider() {
new ClassPathXmlApplicationContext("invalidGatewayWithBothUriAndDestinationProvider.xml", this.getClass());
@@ -370,4 +386,13 @@ public class WebServiceOutboundGatewayParserTests {
new ClassPathXmlApplicationContext("invalidGatewayWithNeitherUriNorDestinationProvider.xml", this.getClass());
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
index 3d49c505ec..d991f24cf9 100644
--- a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
+++ b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
@@ -102,6 +102,14 @@
request-channel="inputChannel"
destination-provider="destinationProvider" />
+
+
+
+
+
+
diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.2.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.2.xsd
index 763a44aa6d..483316d8d4 100644
--- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.2.xsd
+++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.2.xsd
@@ -214,9 +214,10 @@
-
+
-
+
+
diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests-context.xml
index beffa34209..6c05125532 100644
--- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests-context.xml
@@ -43,6 +43,13 @@
xmpp-connection="testConnection">
+
+
+
+
+
+
diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests.java
index 73fc340b86..02356947f9 100644
--- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests.java
+++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/ChatMessageOutboundChannelAdapterParserTests.java
@@ -16,6 +16,11 @@
package org.springframework.integration.xmpp.config;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import java.util.List;
import org.jivesoftware.smack.XMPPConnection;
@@ -24,15 +29,17 @@ import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.channel.QueueChannel;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.SubscribableChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.endpoint.PollingConsumer;
+import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.xmpp.XmppHeaders;
@@ -41,11 +48,6 @@ import org.springframework.integration.xmpp.support.XmppHeaderMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
@@ -57,10 +59,12 @@ public class ChatMessageOutboundChannelAdapterParserTests {
@Autowired
private ApplicationContext context;
-
+
@Autowired
private XmppHeaderMapper headerMapper;
+ private static volatile int adviceCalled;
+
@Test
public void testPollingConsumer() {
Object pollingConsumer = context.getBean("withHeaderMapper");
@@ -75,11 +79,19 @@ public class ChatMessageOutboundChannelAdapterParserTests {
assertTrue(eventConsumer instanceof SubscribableChannel);
}
+ @Test
+ public void advised() {
+ MessageHandler handler = TestUtils.getPropertyValue(context.getBean("advised"),
+ "handler", MessageHandler.class);
+ handler.handleMessage(new GenericMessage("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@SuppressWarnings("unchecked")
@Test
public void testEventConsumer() {
Object eventConsumer = context.getBean("outboundEventAdapter");
- DefaultXmppHeaderMapper headerMapper =
+ DefaultXmppHeaderMapper headerMapper =
TestUtils.getPropertyValue(eventConsumer, "handler.headerMapper", DefaultXmppHeaderMapper.class);
List requestHeaderNames = TestUtils.getPropertyValue(headerMapper, "requestHeaderNames", List.class);
assertEquals(2, requestHeaderNames.size());
@@ -98,7 +110,7 @@ public class ChatMessageOutboundChannelAdapterParserTests {
Message> message = MessageBuilder.withPayload("hello").setHeader(XmppHeaders.TO, "oleg").
setHeader("foobar", "foobar").build();
XMPPConnection connection = context.getBean("testConnection", XMPPConnection.class);
-
+
Mockito.doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
@@ -108,9 +120,9 @@ public class ChatMessageOutboundChannelAdapterParserTests {
return null;
}})
.when(connection).sendPacket(Mockito.any(org.jivesoftware.smack.packet.Message.class));
-
+
channel.send(message);
-
+
verify(connection, times(1)).sendPacket(Mockito.any(org.jivesoftware.smack.packet.Message.class));
Mockito.reset(connection);
}
@@ -137,4 +149,13 @@ public class ChatMessageOutboundChannelAdapterParserTests {
Mockito.reset(connection);
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}
diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/PresenceOutboundChannelAdapterParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/PresenceOutboundChannelAdapterParserTests-context.xml
index b9529edfae..63be35a8fa 100644
--- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/PresenceOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/PresenceOutboundChannelAdapterParserTests-context.xml
@@ -29,6 +29,16 @@
xmpp-connection="testConnection"
channel="eventChannel"
order="34"/>
+
+
+
+
+
+
+
("foo"));
+ assertEquals(1, adviceCalled);
+ }
+
@Test
public void testRosterEventOutboundChannel(){
Object channel = context.getBean("eventOutboundRosterChannel");
@@ -78,4 +91,13 @@ public class PresenceOutboundChannelAdapterParserTests {
assertEquals(45, TestUtils.getPropertyValue(handlers.toArray()[0], "order"));
}
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
+
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ adviceCalled++;
+ return null;
+ }
+
+ }
}