/*
* Copyright 2002-2016 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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.StopWatch;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Artem Bilan
* @author Gary Russell
*/
public class MessageHistoryIntegrationTests {
private final Log logger = LogFactory.getLog(getClass());
@Test
public void testNoHistoryAwareMessageHandler() {
ConfigurableApplicationContext 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);
String handlerClassName = bridgeAccessor.getPropertyValue("handler").getClass().getName();
assertFalse("org.springframework.integration.config.MessageHistoryWritingMessageHandler".equals(handlerClassName));
}
ac.close();
}
@Test
public void testMessageHistoryWithHistoryWriter() {
ConfigurableApplicationContext 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() {
@Override
public void handleMessage(Message<?> message) {
Iterator<Properties> historyIterator = message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
Properties event = historyIterator.next();
assertEquals("sampleGateway", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("gateway", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("bridgeInChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("testBridge", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("bridge", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("headerEnricherChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("testHeaderEnricher", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("transformer", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("chainChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("sampleChain", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("chain", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("sampleChain$child.service-activator-within-chain", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("service-activator", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("filterChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("testFilter", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("filter", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("splitterChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("testSplitter", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("splitter", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("aggregatorChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("testAggregator", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("aggregator", event.getProperty(MessageHistory.TYPE_PROPERTY));
event = historyIterator.next();
assertEquals("endOfThePipeChannel", event.getProperty(MessageHistory.NAME_PROPERTY));
assertEquals("channel", event.getProperty(MessageHistory.TYPE_PROPERTY));
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));
assertNotNull(result);
//assertEquals("hello", result);
ac.close();
}
@Test
public void testMessageHistoryWithoutHistoryWriter() {
ConfigurableApplicationContext 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() {
@Override
public void handleMessage(Message<?> message) {
assertNull(message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class));
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));
ac.close();
}
@Test
public void testMessageHistoryParser() {
ConfigurableApplicationContext 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() {
@Override
public void handleMessage(Message<?> message) {
Iterator<Properties> historyIterator = message.getHeaders()
.get(MessageHistory.HEADER_NAME, MessageHistory.class).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));
ac.close();
}
@Test
public void testMessageHistoryParserWithNamePatterns() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"messageHistoryWithHistoryWriterNamespaceAndPatterns.xml", MessageHistoryIntegrationTests.class);
SampleGateway gateway = ac.getBean("sampleGateway", SampleGateway.class);
DirectChannel endOfThePipeChannel = ac.getBean("endOfThePipeChannel", DirectChannel.class);
MessageHandler handler = Mockito.spy(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) {
Iterator<Properties> historyIterator = message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
assertTrue(historyIterator.hasNext());
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
assertTrue(historyIterator.hasNext());
Properties chainHistory = historyIterator.next();
assertEquals("sampleChain", chainHistory.get("name"));
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));
ac.close();
}
@Test(expected = BeanCreationException.class)
public void testMessageHistoryMoreThanOneNamespaceFail() {
new ClassPathXmlApplicationContext("messageHistoryWithHistoryWriterNamespace-fail.xml",
MessageHistoryIntegrationTests.class).close();
}
@Test @Ignore
public void testMessageHistoryWithHistoryPerformance() {
ConfigurableApplicationContext acWithHistory = new ClassPathXmlApplicationContext("perfWithMessageHistory.xml",
MessageHistoryIntegrationTests.class);
ConfigurableApplicationContext acWithoutHistory = new ClassPathXmlApplicationContext(
"perfWithoutMessageHistory.xml", MessageHistoryIntegrationTests.class);
SampleGateway gatewayHistory = acWithHistory.getBean("sampleGateway", SampleGateway.class);
DirectChannel endOfThePipeChannelHistory = acWithHistory.getBean("endOfThePipeChannel", DirectChannel.class);
endOfThePipeChannelHistory.subscribe(message -> {
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
replyChannel.send(message);
});
SampleGateway gateway = acWithoutHistory.getBean("sampleGateway", SampleGateway.class);
DirectChannel endOfThePipeChannel = acWithoutHistory.getBean("endOfThePipeChannel", DirectChannel.class);
endOfThePipeChannel.subscribe(message -> {
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
replyChannel.send(message);
});
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < 10000; i++) {
gatewayHistory.echo("hello");
}
stopWatch.stop();
logger.info("Elapsed time with history 10000 calls: " + stopWatch.getTotalTimeSeconds());
stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < 10000; i++) {
gateway.echo("hello");
}
stopWatch.stop();
logger.info("Elapsed time without history 10000 calls: " + stopWatch.getTotalTimeSeconds());
acWithHistory.close();
acWithoutHistory.close();
}
public interface SampleGateway {
Message<?> echo(String value);
}
}