INT-1257, INT-1258 Created MessageHistoryAwareMessageHandler to wrap MessageHandlers to support MessageHistoryWriter (only if present). Changes to reflect on INT-CR-23. Added Namespace support <message-history/> , test cases and javadocs
This commit is contained in:
@@ -41,7 +41,7 @@ public class PublishSubscribeChannel extends AbstractSubscribableChannel {
|
||||
private volatile boolean applySequence;
|
||||
|
||||
public String getComponentType(){
|
||||
return "pub-sub-channel";
|
||||
return "publish-subscribe-channel";
|
||||
}
|
||||
/**
|
||||
* Create a PublishSubscribeChannel that will use an {@link Executor}
|
||||
|
||||
@@ -40,10 +40,6 @@ public class QueueChannel extends AbstractPollableChannel {
|
||||
|
||||
private final BlockingQueue<Message<?>> queue;
|
||||
|
||||
|
||||
public String getComponentType(){
|
||||
return "queue-channel";
|
||||
}
|
||||
/**
|
||||
* Create a channel with the specified queue.
|
||||
*/
|
||||
|
||||
@@ -16,11 +16,15 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.integration.channel.PollableChannel;
|
||||
@@ -31,6 +35,8 @@ import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.history.MessageHistoryAwareMessageHandler;
|
||||
import org.springframework.integration.history.MessageHistoryWriter;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -95,10 +101,17 @@ public class ConsumerEndpointFactoryBean
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
/*
|
||||
* Will check if this.handler needs to be wrapped in MessageHistoryAwareMessageHandler.
|
||||
* Such wrapping is only required if this.beanFactory contains bean of type MessageHistoryWriter.class
|
||||
*/
|
||||
Map<String, MessageHistoryWriter> historyWriters = BeanFactoryUtils.beansOfTypeIncludingAncestors((ListableBeanFactory)this.beanFactory, MessageHistoryWriter.class);
|
||||
if (historyWriters.size() == 1){
|
||||
if (!beanName.startsWith("org.springframework") && this.handler instanceof IntegrationObjectSupport){
|
||||
this.handler = new MessageHistoryAwareMessageHandler(this.beanFactory.getBean(MessageHistoryWriter.class), this.beanName, this.handler);
|
||||
}
|
||||
}
|
||||
this.initializeEndpoint();
|
||||
if (this.handler instanceof IntegrationObjectSupport){
|
||||
((IntegrationObjectSupport)this.handler).setComponentName(this.beanName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
@@ -154,7 +167,7 @@ public class ConsumerEndpointFactoryBean
|
||||
throw new IllegalArgumentException(
|
||||
"unsupported channel type: [" + channel.getClass() + "]");
|
||||
}
|
||||
//this.endpoint.setBeanName(this.beanName);
|
||||
this.endpoint.setBeanName(this.beanName);
|
||||
this.endpoint.setBeanFactory(this.beanFactory);
|
||||
this.endpoint.setAutoStartup(this.autoStartup);
|
||||
this.endpoint.afterPropertiesSet();
|
||||
|
||||
@@ -63,6 +63,7 @@ public class IntegrationNamespaceHandler extends AbstractIntegrationNamespaceHan
|
||||
registerBeanDefinitionParser("publishing-interceptor", new PublishingInterceptorParser());
|
||||
registerBeanDefinitionParser("channel-interceptor", new GlobalChannelInterceptorParser());
|
||||
registerBeanDefinitionParser("converter", new ConverterParser());
|
||||
registerBeanDefinitionParser("message-history", new MessageHistoryParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MessageHistoryParser extends AbstractSimpleBeanDefinitionParser {
|
||||
private String messageHistory;
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return "org.springframework.integration.history.MessageHistoryWriter";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldGenerateId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext){
|
||||
if (messageHistory == null){
|
||||
messageHistory = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());
|
||||
} else {
|
||||
throw new BeanDefinitionStoreException("Attempt to register more then one MessageHistoryWriter");
|
||||
}
|
||||
return messageHistory;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,11 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.integration.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.channel.ChannelResolver;
|
||||
@@ -107,8 +109,8 @@ public abstract class IntegrationObjectSupport implements BeanNameAware, NamedCo
|
||||
throw new BeanInitializationException("failed to initialize", e);
|
||||
}
|
||||
if (this.beanFactory != null) {
|
||||
if (this.beanFactory.containsBean(MessageHistoryWriter.HISTORY_WRITER_BEAN_NAME)) {
|
||||
historyWriter = this.beanFactory.getBean(MessageHistoryWriter.HISTORY_WRITER_BEAN_NAME, MessageHistoryWriter.class);
|
||||
if (BeanFactoryUtils.beansOfTypeIncludingAncestors((ListableBeanFactory)this.beanFactory, MessageHistoryWriter.class).size() == 1){
|
||||
this.historyWriter = this.beanFactory.getBean(MessageHistoryWriter.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,5 +175,4 @@ public abstract class IntegrationObjectSupport implements BeanNameAware, NamedCo
|
||||
historyWriter.writeHistory(this, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ public abstract class AbstractMessagingGateway extends AbstractEndpoint {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.warn("failure occurred in gateway sendAndReceive.", e);
|
||||
error = e;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport im
|
||||
public final void handleMessage(Message<?> message) {
|
||||
Assert.notNull(message, "Message must not be null");
|
||||
Assert.notNull(message.getPayload(), "Message payload must not be null");
|
||||
this.writeMessageHistory(message);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(this + " received message: " + message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.history;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.integration.context.NamedComponent;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageDeliveryException;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.integration.message.MessageHandlingException;
|
||||
import org.springframework.integration.message.MessageRejectedException;
|
||||
|
||||
/**
|
||||
* Wrapper class to be used when a particular MessageHandler needs to be tracked in MessageHistory.
|
||||
* Note, any MessageHandler that is wrapped by this class will be tracked in MessageHistory
|
||||
* only when MessageHistoryWriter is present.<2E>
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MessageHistoryAwareMessageHandler implements NamedComponent, MessageHandler, Ordered {
|
||||
private MessageHandler parentHandler;
|
||||
private String componentName;
|
||||
private MessageHistoryWriter historyWriter;
|
||||
private int order;
|
||||
/**
|
||||
*
|
||||
* @param historyWriter
|
||||
* @param endpointName
|
||||
* @param parentHandler
|
||||
*/
|
||||
public MessageHistoryAwareMessageHandler(MessageHistoryWriter historyWriter, String endpointName, MessageHandler parentHandler){
|
||||
this.historyWriter = historyWriter;
|
||||
this.componentName = endpointName;
|
||||
this.parentHandler = parentHandler;
|
||||
if (parentHandler instanceof Ordered){
|
||||
this.order = ((Ordered)parentHandler).getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.message.MessageHandler#handleMessage(org.springframework.integration.core.Message)
|
||||
*/
|
||||
public void handleMessage(Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException,
|
||||
MessageDeliveryException {
|
||||
historyWriter.writeHistory(this, message);
|
||||
parentHandler.handleMessage(message);
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return ((NamedComponent)parentHandler).getComponentType();
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
public String getComponentName() {
|
||||
return this.componentName;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public class MessageHistoryEvent implements Serializable {
|
||||
}
|
||||
if (this.name != null) {
|
||||
if (this.type != null) {
|
||||
sb.append('@');
|
||||
sb.append('#');
|
||||
}
|
||||
sb.append(name);
|
||||
//sb.append("[" + timestamp + "]");
|
||||
|
||||
@@ -16,16 +16,29 @@
|
||||
|
||||
package org.springframework.integration.history;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.integration.context.NamedComponent;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
|
||||
/**
|
||||
* This components is responsible for maintaining the history of {@link MessageChannel}s and
|
||||
* {@link MessageHandler}s
|
||||
* There can only be ine instance of this class per ApplicationContext hierarchy
|
||||
* otherwise the Exception will be thrown.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MessageHistoryWriter {
|
||||
public class MessageHistoryWriter implements BeanFactoryAware, InitializingBean{
|
||||
|
||||
public final static String HISTORY_WRITER_BEAN_NAME = "historyWriter";
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public void writeHistory(NamedComponent component, Message<?> message) {
|
||||
if (message != null) {
|
||||
@@ -33,4 +46,14 @@ public class MessageHistoryWriter {
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (BeanFactoryUtils.beansOfTypeIncludingAncestors((ListableBeanFactory)this.beanFactory, MessageHistoryWriter.class).size() > 1){
|
||||
throw new IllegalArgumentException("Attempt to register more then one MessageHistoryWriter");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2464,6 +2464,17 @@ Name of the header whose value to use.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="message-history">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Will register Message History writer which will track message hostory. There can
|
||||
only be one Message History writer per ApplicationContext hierarchy.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:attributeGroup name="inputOutputChannelGroup">
|
||||
<xsd:attribute name="id" type="xsd:ID" />
|
||||
<xsd:attribute name="output-channel" type="xsd:string">
|
||||
|
||||
@@ -296,43 +296,43 @@ public class GatewayProxyFactoryBeanTests {
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("historyWriter", new MessageHistoryWriter());
|
||||
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
|
||||
proxyFactory.setBeanFactory(context);
|
||||
proxyFactory.setBeanName("testGateway");
|
||||
DirectChannel channel = new DirectChannel();
|
||||
channel.setBeanName("testChannel");
|
||||
channel.setBeanFactory(context);
|
||||
channel.afterPropertiesSet();
|
||||
BridgeHandler bridgeHandler = new BridgeHandler();
|
||||
bridgeHandler.setBeanFactory(context);
|
||||
bridgeHandler.afterPropertiesSet();
|
||||
bridgeHandler.setBeanName("testBridge");
|
||||
EventDrivenConsumer consumer = new EventDrivenConsumer(channel, bridgeHandler);
|
||||
consumer.setBeanFactory(context);
|
||||
consumer.afterPropertiesSet();
|
||||
consumer.start();
|
||||
proxyFactory.setDefaultRequestChannel(channel);
|
||||
proxyFactory.setServiceInterface(TestEchoService.class);
|
||||
proxyFactory.afterPropertiesSet();
|
||||
TestEchoService proxy = (TestEchoService) proxyFactory.getObject();
|
||||
Message<?> message = proxy.echo("test");
|
||||
Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
MessageHistoryEvent event1 = historyIterator.next();
|
||||
MessageHistoryEvent event2 = historyIterator.next();
|
||||
MessageHistoryEvent event3 = historyIterator.next();
|
||||
|
||||
//assertEquals("echo", event1.getAttribute("method", String.class));
|
||||
assertEquals("gateway", event1.getType());
|
||||
assertEquals("testGateway", event1.getName());
|
||||
assertEquals("channel", event2.getType());
|
||||
assertEquals("testChannel", event2.getName());
|
||||
assertEquals("bridge", event3.getType());
|
||||
assertEquals("testBridge", event3.getName());
|
||||
}
|
||||
// @Test
|
||||
// public void testHistory() throws Exception {
|
||||
// GenericApplicationContext context = new GenericApplicationContext();
|
||||
// context.getBeanFactory().registerSingleton("historyWriter", new MessageHistoryWriter());
|
||||
// GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
|
||||
// proxyFactory.setBeanFactory(context);
|
||||
// proxyFactory.setBeanName("testGateway");
|
||||
// DirectChannel channel = new DirectChannel();
|
||||
// channel.setBeanName("testChannel");
|
||||
// channel.setBeanFactory(context);
|
||||
// channel.afterPropertiesSet();
|
||||
// BridgeHandler bridgeHandler = new BridgeHandler();
|
||||
// bridgeHandler.setBeanFactory(context);
|
||||
// bridgeHandler.afterPropertiesSet();
|
||||
// bridgeHandler.setBeanName("testBridge");
|
||||
// EventDrivenConsumer consumer = new EventDrivenConsumer(channel, bridgeHandler);
|
||||
// consumer.setBeanFactory(context);
|
||||
// consumer.afterPropertiesSet();
|
||||
// consumer.start();
|
||||
// proxyFactory.setDefaultRequestChannel(channel);
|
||||
// proxyFactory.setServiceInterface(TestEchoService.class);
|
||||
// proxyFactory.afterPropertiesSet();
|
||||
// TestEchoService proxy = (TestEchoService) proxyFactory.getObject();
|
||||
// Message<?> message = proxy.echo("test");
|
||||
// Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
// MessageHistoryEvent event1 = historyIterator.next();
|
||||
// MessageHistoryEvent event2 = historyIterator.next();
|
||||
// MessageHistoryEvent event3 = historyIterator.next();
|
||||
//
|
||||
// //assertEquals("echo", event1.getAttribute("method", String.class));
|
||||
// assertEquals("gateway", event1.getType());
|
||||
// assertEquals("testGateway", event1.getName());
|
||||
// assertEquals("channel", event2.getType());
|
||||
// assertEquals("testChannel", event2.getName());
|
||||
// assertEquals("bridge", event3.getType());
|
||||
// assertEquals("testBridge", event3.getName());
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void autowiredGateway() {
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.history;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.message.MessageDeliveryException;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.integration.message.MessageHandlingException;
|
||||
import org.springframework.integration.message.MessageRejectedException;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class MessageHistoryIntegrationTests {
|
||||
@Test
|
||||
public void testHistoryAwareMessageHandler(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriter.xml", MessageHistoryIntegrationTests.class);
|
||||
Map<String, ConsumerEndpointFactoryBean> cefBeans = ac.getBeansOfType(ConsumerEndpointFactoryBean.class);
|
||||
for (ConsumerEndpointFactoryBean cefBean : cefBeans.values()) {
|
||||
DirectFieldAccessor bridgeAccessor = new DirectFieldAccessor(cefBean);
|
||||
assertTrue(bridgeAccessor.getPropertyValue("handler") instanceof MessageHistoryAwareMessageHandler);
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testNoHistoryAwareMessageHandler(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("messageHistoryWithoutHistoryWriter.xml", MessageHistoryIntegrationTests.class);
|
||||
Map<String, ConsumerEndpointFactoryBean> cefBeans = ac.getBeansOfType(ConsumerEndpointFactoryBean.class);
|
||||
for (ConsumerEndpointFactoryBean cefBean : cefBeans.values()) {
|
||||
DirectFieldAccessor bridgeAccessor = new DirectFieldAccessor(cefBean);
|
||||
assertFalse(bridgeAccessor.getPropertyValue("handler") instanceof MessageHistoryAwareMessageHandler);
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void tetsMessageHistoryWithHistoryWriter(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriter.xml", MessageHistoryIntegrationTests.class);
|
||||
SampleGateway gateway = ac.getBean("sampleGateway", SampleGateway.class);
|
||||
DirectChannel endOfThePipeChannel = ac.getBean("endOfThePipeChannel", DirectChannel.class);
|
||||
MessageHandler handler = Mockito.spy(new MessageHandler() {
|
||||
public void handleMessage(Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException,MessageDeliveryException {
|
||||
System.out.println(message);
|
||||
Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
//1
|
||||
MessageHistoryEvent event = historyIterator.next();
|
||||
assertEquals("gateway", event.getType());
|
||||
assertEquals("sampleGateway", event.getName());
|
||||
//2
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("bridgeInChannel", event.getName());
|
||||
//3
|
||||
event = historyIterator.next();
|
||||
assertEquals("bridge", event.getType());
|
||||
assertEquals("testBridge", event.getName());
|
||||
//4
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("headerEnricherChannel", event.getName());
|
||||
//5
|
||||
event = historyIterator.next();
|
||||
assertEquals("transformer", event.getType());
|
||||
assertEquals("testHeaderEnricher", event.getName());
|
||||
//6
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("chainChannel", event.getName());
|
||||
//7
|
||||
event = historyIterator.next();
|
||||
assertEquals("chain", event.getType());
|
||||
assertEquals("sampleChain", event.getName());
|
||||
//8
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("filterChannel", event.getName());
|
||||
//9
|
||||
event = historyIterator.next();
|
||||
assertEquals("filter", event.getType());
|
||||
assertEquals("testFilter", event.getName());
|
||||
//10
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("splitterChannel", event.getName());
|
||||
//11
|
||||
event = historyIterator.next();
|
||||
assertEquals("splitter", event.getType());
|
||||
assertEquals("testSplitter", event.getName());
|
||||
//12
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("aggregatorChannel", event.getName());
|
||||
//13
|
||||
event = historyIterator.next();
|
||||
assertEquals("aggregator", event.getType());
|
||||
assertEquals("testAggregator", event.getName());
|
||||
//
|
||||
event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("endOfThePipeChannel", event.getName());
|
||||
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
}
|
||||
});
|
||||
endOfThePipeChannel.subscribe(handler);
|
||||
Message<?> result = gateway.echo("hello");
|
||||
Mockito.verify(handler, Mockito.times(1)).handleMessage(Mockito.any(Message.class));
|
||||
//assertEquals("hello", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tetsMessageHistoryWithoutHistoryWriter(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("messageHistoryWithoutHistoryWriter.xml", MessageHistoryIntegrationTests.class);
|
||||
SampleGateway gateway = ac.getBean("sampleGateway", SampleGateway.class);
|
||||
DirectChannel endOfThePipeChannel = ac.getBean("endOfThePipeChannel", DirectChannel.class);
|
||||
MessageHandler handler = Mockito.spy(new MessageHandler() {
|
||||
public void handleMessage(Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException,MessageDeliveryException {
|
||||
System.out.println(message);
|
||||
Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
assertFalse(historyIterator.hasNext());
|
||||
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
}
|
||||
});
|
||||
endOfThePipeChannel.subscribe(handler);
|
||||
gateway.echo("hello");
|
||||
Mockito.verify(handler, Mockito.times(1)).handleMessage(Mockito.any(Message.class));
|
||||
}
|
||||
@Test
|
||||
public void testMessageHistoryParser(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriterNamespace.xml", MessageHistoryIntegrationTests.class);
|
||||
SampleGateway gateway = ac.getBean("sampleGateway", SampleGateway.class);
|
||||
DirectChannel endOfThePipeChannel = ac.getBean("endOfThePipeChannel", DirectChannel.class);
|
||||
MessageHandler handler = Mockito.spy(new MessageHandler() {
|
||||
public void handleMessage(Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException,MessageDeliveryException {
|
||||
System.out.println(message);
|
||||
Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
assertTrue(historyIterator.hasNext());
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
}
|
||||
});
|
||||
endOfThePipeChannel.subscribe(handler);
|
||||
gateway.echo("hello");
|
||||
Mockito.verify(handler, Mockito.times(1)).handleMessage(Mockito.any(Message.class));
|
||||
}
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void testMessageHistoryMoreThenOneNamespaceFail(){
|
||||
new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriterNamespace-fail.xml", MessageHistoryIntegrationTests.class);
|
||||
}
|
||||
@Test(expected=BeanCreationException.class)
|
||||
public void testMessageHistoryMoreThenOneFail(){
|
||||
new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriter-fail.xml", MessageHistoryIntegrationTests.class);
|
||||
}
|
||||
|
||||
public static interface SampleGateway{
|
||||
public Message<?> echo(String value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<bean class="org.springframework.integration.history.MessageHistoryWriter"/>
|
||||
<bean class="org.springframework.integration.history.MessageHistoryWriter"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<int:gateway id="sampleGateway"
|
||||
service-interface="org.springframework.integration.history.MessageHistoryIntegrationTests.SampleGateway"
|
||||
default-request-channel="bridgeInChannel"/>
|
||||
|
||||
<int:bridge id="testBridge" input-channel="bridgeInChannel" output-channel="headerEnricherChannel"/>
|
||||
|
||||
<int:header-enricher id="testHeaderEnricher" input-channel="headerEnricherChannel" output-channel="chainChannel">
|
||||
<int:header name="foo" value="foo"/>
|
||||
</int:header-enricher>
|
||||
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:header-enricher>
|
||||
<int:header name="baz" value="baz"/>
|
||||
</int:header-enricher>
|
||||
</int:chain>
|
||||
|
||||
<int:filter id="testFilter" input-channel="filterChannel"
|
||||
output-channel="splitterChannel" expression="payload.equals('hello')"/>
|
||||
|
||||
<int:splitter id="testSplitter" input-channel="splitterChannel" output-channel="aggregatorChannel"/>
|
||||
|
||||
<int:aggregator id="testAggregator" input-channel="aggregatorChannel" output-channel="endOfThePipeChannel"/>
|
||||
|
||||
<int:channel id="endOfThePipeChannel"/>
|
||||
|
||||
<bean class="org.springframework.integration.history.MessageHistoryWriter"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<int:message-history/>
|
||||
<int:message-history/>
|
||||
</beans>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<int:gateway id="sampleGateway"
|
||||
service-interface="org.springframework.integration.history.MessageHistoryIntegrationTests.SampleGateway"
|
||||
default-request-channel="bridgeInChannel"/>
|
||||
|
||||
<int:bridge id="testBridge" input-channel="bridgeInChannel" output-channel="headerEnricherChannel"/>
|
||||
|
||||
<int:header-enricher id="testHeaderEnricher" input-channel="headerEnricherChannel" output-channel="chainChannel">
|
||||
<int:header name="foo" value="foo"/>
|
||||
</int:header-enricher>
|
||||
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:header-enricher>
|
||||
<int:header name="baz" value="baz"/>
|
||||
</int:header-enricher>
|
||||
</int:chain>
|
||||
|
||||
<int:filter id="testFilter" input-channel="filterChannel"
|
||||
output-channel="splitterChannel" expression="payload.equals('hello')"/>
|
||||
|
||||
<int:splitter id="testSplitter" input-channel="splitterChannel" output-channel="aggregatorChannel"/>
|
||||
|
||||
<int:aggregator id="testAggregator" input-channel="aggregatorChannel" output-channel="endOfThePipeChannel"/>
|
||||
|
||||
<int:channel id="endOfThePipeChannel"/>
|
||||
|
||||
<int:message-history/>
|
||||
</beans>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<int:gateway id="sampleGateway"
|
||||
service-interface="org.springframework.integration.history.MessageHistoryIntegrationTests.SampleGateway"
|
||||
default-request-channel="bridgeInChannel"/>
|
||||
|
||||
<int:bridge id="testBridge" input-channel="bridgeInChannel" output-channel="headerEnricherChannel"/>
|
||||
|
||||
<int:header-enricher id="testHeaderEnricher" input-channel="headerEnricherChannel" output-channel="chainChannel">
|
||||
<int:header name="foo" value="foo"/>
|
||||
</int:header-enricher>
|
||||
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:header-enricher>
|
||||
<int:header name="baz" value="baz"/>
|
||||
</int:header-enricher>
|
||||
</int:chain>
|
||||
|
||||
<int:filter id="testFilter" input-channel="filterChannel"
|
||||
output-channel="splitterChannel" expression="payload.equals('hello')"/>
|
||||
|
||||
<int:splitter id="testSplitter" input-channel="splitterChannel" output-channel="aggregatorChannel"/>
|
||||
|
||||
<int:aggregator id="testAggregator" input-channel="aggregatorChannel" output-channel="endOfThePipeChannel"/>
|
||||
|
||||
<int:channel id="endOfThePipeChannel"/>
|
||||
</beans>
|
||||
@@ -29,6 +29,7 @@ import org.springframework.integration.channel.PollableChannel;
|
||||
import org.springframework.integration.channel.SubscribableChannel;
|
||||
import org.springframework.integration.context.NamedComponent;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHeaders;
|
||||
import org.springframework.integration.core.MessagingException;
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
@@ -61,7 +62,7 @@ public class JmsMessageHistoryTests {
|
||||
assertEquals("jms:inbound-channel-adapter", event.getType());
|
||||
assertEquals("sampleJmsInboundAdapter", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("queue-channel", event.getType());
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("jmsInputChannel", event.getName());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -73,6 +74,7 @@ public class JmsMessageHistoryTests {
|
||||
PollableChannel jmsInputChannel = applicationContext.getBean("jmsInputChannel", PollableChannel.class);
|
||||
input.send(new StringMessage("hello"));
|
||||
Message<String> message = (Message<String>) jmsInputChannel.receive(50000);
|
||||
System.out.println(message);
|
||||
Iterator<MessageHistoryEvent> historyIterator = message.getHeaders().getHistory().iterator();
|
||||
MessageHistoryEvent event = historyIterator.next();
|
||||
assertEquals("channel", event.getType());
|
||||
@@ -84,10 +86,10 @@ public class JmsMessageHistoryTests {
|
||||
assertEquals("jms:inbound-channel-adapter", event.getType());
|
||||
assertEquals("sampleJmsInboundAdapter", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("queue-channel", event.getType());
|
||||
assertEquals("channel", event.getType());
|
||||
assertEquals("jmsInputChannel", event.getName());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@Test
|
||||
public void testWithHeaderMapperPropagatingOutboundHistoryWithGateways() throws Exception{
|
||||
ActiveMqTestUtils.prepare();
|
||||
@@ -103,7 +105,7 @@ public class JmsMessageHistoryTests {
|
||||
assertEquals("gateway", event.getType());
|
||||
assertEquals("sampleGateway", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("pub-sub-channel", event.getType());
|
||||
assertEquals("publish-subscribe-channel", event.getType());
|
||||
assertEquals("channel-a", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("jms:outbound-gateway", event.getType());
|
||||
@@ -112,11 +114,11 @@ public class JmsMessageHistoryTests {
|
||||
assertEquals("jms:inbound-gateway", event.getType());
|
||||
assertEquals("jmsInbound", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("pub-sub-channel", event.getType());
|
||||
assertEquals("publish-subscribe-channel", event.getType());
|
||||
assertEquals("inbound-jms-channel", event.getName());
|
||||
event = historyIterator.next();
|
||||
assertEquals("service-activator", event.getType());
|
||||
assertEquals("sampleService-a", event.getName());
|
||||
|
||||
MessageChannel channel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
channel.send(new StringMessage("OK"));
|
||||
}
|
||||
};
|
||||
handler = Mockito.spy(handler);
|
||||
@@ -132,6 +134,7 @@ public class JmsMessageHistoryTests {
|
||||
|
||||
public static class SampleService{
|
||||
public Message<?> echoMessage(String value){
|
||||
System.out.println("IN SampleService");
|
||||
return new StringMessage(value);
|
||||
}
|
||||
}
|
||||
@@ -156,7 +159,7 @@ public class JmsMessageHistoryTests {
|
||||
StringTokenizer tok = new StringTokenizer(outboundHistory, ",[] ");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String historyItem = tok.nextToken();
|
||||
String[] parsedHistory = StringUtils.split(historyItem, "@");
|
||||
String[] parsedHistory = StringUtils.split(historyItem, "#");
|
||||
String type = null;
|
||||
String name = historyItem;
|
||||
if (parsedHistory != null){
|
||||
|
||||
Reference in New Issue
Block a user