/*
* Copyright 2014-2015 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.monitor;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.aggregator.AggregatingMessageHandler;
import org.springframework.integration.aggregator.DefaultAggregatingMessageGroupProcessor;
import org.springframework.integration.aggregator.ExpressionEvaluatingMessageGroupProcessor;
import org.springframework.integration.aggregator.ExpressionEvaluatingReleaseStrategy;
import org.springframework.integration.aggregator.HeaderAttributeCorrelationStrategy;
import org.springframework.integration.aggregator.MessageCountReleaseStrategy;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.handler.BridgeHandler;
import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport;
import org.springframework.integration.router.RecipientListRouter;
import org.springframework.integration.scattergather.ScatterGatherHandler;
import org.springframework.integration.store.SimpleMessageStore;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Artem Bilan
* @author Gary Russell
* @since 4.1
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class ScatterGatherHandlerIntegrationTests {
@Autowired
private PollableChannel output;
@Autowired
private MessageChannel inputAuctionWithoutGatherChannel;
@Autowired
private MessageChannel inputAuctionWithGatherChannel;
@Autowired
private MessageChannel distributionChannel;
@Test
public void testSimpleAuction() {
Message<String> quoteMessage = MessageBuilder.withPayload("testQuote").build();
this.inputAuctionWithoutGatherChannel.send(quoteMessage);
Message<?> bestQuoteMessage = this.output.receive(10000);
assertNotNull(bestQuoteMessage);
Object payload = bestQuoteMessage.getPayload();
assertThat(payload, instanceOf(Double.class));
assertThat((Double) payload, lessThan(10D));
}
@SuppressWarnings("rawtypes")
@Test
public void testAuctionWithGatherChannel() {
Message<String> quoteMessage = MessageBuilder.withPayload("testQuote").build();
this.inputAuctionWithGatherChannel.send(quoteMessage);
Message<?> bestQuoteMessage = this.output.receive(10000);
assertNotNull(bestQuoteMessage);
Object payload = bestQuoteMessage.getPayload();
assertThat(payload, instanceOf(List.class));
assertEquals(3, ((List) payload).size());
}
@Test
public void testDistribution() {
Message<String> quoteMessage = MessageBuilder.withPayload("testQuote").build();
this.distributionChannel.send(quoteMessage);
Message<?> bestQuoteMessage = this.output.receive(10000);
assertNotNull(bestQuoteMessage);
Object payload = bestQuoteMessage.getPayload();
assertThat(payload, instanceOf(Double.class));
assertThat((Double) payload, lessThan(10D));
}
@Configuration
@EnableIntegration
@EnableIntegrationMBeanExport(server = "mBeanServer")
public static class ContextConfiguration {
@Bean
public static MBeanServerFactoryBean mBeanServer() {
MBeanServerFactoryBean mBeanServerFactoryBean = new MBeanServerFactoryBean();
mBeanServerFactoryBean.setLocateExistingServerIfPossible(true);
return mBeanServerFactoryBean;
}
@Bean
public PollableChannel output() {
return new QueueChannel();
}
@Bean
public SubscribableChannel scatterAuctionWithoutGatherChannel() {
PublishSubscribeChannel channel = new PublishSubscribeChannel();
channel.setApplySequence(true);
return channel;
}
@Bean
public MessageHandler gatherer1() {
return new AggregatingMessageHandler(
new ExpressionEvaluatingMessageGroupProcessor("^[payload gt 5] ?: -1D"),
new SimpleMessageStore(),
new HeaderAttributeCorrelationStrategy(IntegrationMessageHeaderAccessor.CORRELATION_ID),
new ExpressionEvaluatingReleaseStrategy("size() == 2"));
}
@Bean
public MessageChannel inputAuctionWithoutGatherChannel() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "inputAuctionWithoutGatherChannel")
public MessageHandler scatterGatherAuctionWithoutGatherChannel() {
ScatterGatherHandler handler = new ScatterGatherHandler(scatterAuctionWithoutGatherChannel(), gatherer1());
handler.setOutputChannel(output());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithoutGatherChannel")
public MessageHandler auctionWithoutGatherChannelBridge1() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithoutGatherChannel")
public MessageHandler auctionWithoutGatherChannelBridge2() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithoutGatherChannel")
public MessageHandler auctionWithoutGatherChannelBridge3() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
public MessageChannel serviceChannel1() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "serviceChannel1")
public MessageHandler service1() {
return new AbstractReplyProducingMessageHandler() {
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
return Math.random() * 10;
}
};
}
@Bean
public MessageHandler distributor() {
RecipientListRouter router = new RecipientListRouter();
router.setApplySequence(true);
router.setChannels(Arrays.asList(distributionChannel1(), distributionChannel2(), distributionChannel3()));
return router;
}
@Bean
public MessageChannel distributionChannel1() {
return new DirectChannel();
}
@Bean
public MessageChannel distributionChannel2() {
return new DirectChannel();
}
@Bean
public MessageChannel distributionChannel3() {
return new DirectChannel();
}
@Bean
public MessageChannel distributionChannel() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "distributionChannel")
public MessageHandler scatterGatherDistribution() {
ScatterGatherHandler handler = new ScatterGatherHandler(distributor(), gatherer1());
handler.setOutputChannel(output());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "distributionChannel1")
public MessageHandler distributionBridge1() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "distributionChannel2")
public MessageHandler distributionBridge2() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "distributionChannel3")
public MessageHandler distributionBridge3() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel1());
return handler;
}
@Bean
public MessageChannel inputAuctionWithGatherChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel gatherChannel() {
return new DirectChannel();
}
@Bean
public SubscribableChannel scatterAuctionWithGatherChannel() {
PublishSubscribeChannel channel = new PublishSubscribeChannel(Executors.newCachedThreadPool());
channel.setApplySequence(true);
return channel;
}
@Bean
public MessageHandler gatherer2() {
return new AggregatingMessageHandler(new DefaultAggregatingMessageGroupProcessor(),
new SimpleMessageStore(),
new HeaderAttributeCorrelationStrategy(IntegrationMessageHeaderAccessor.CORRELATION_ID),
new MessageCountReleaseStrategy(3));
}
@Bean
@ServiceActivator(inputChannel = "inputAuctionWithGatherChannel")
public MessageHandler scatterGatherAuctionWithGatherChannel() {
ScatterGatherHandler handler = new ScatterGatherHandler(scatterAuctionWithGatherChannel(), gatherer2());
handler.setGatherChannel(gatherChannel());
handler.setOutputChannel(output());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithGatherChannel")
public MessageHandler auctionWithGatherChannelBridge1() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel2());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithGatherChannel")
public MessageHandler auctionWithGatherChannelBridge2() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel2());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithGatherChannel")
public MessageHandler auctionWithGatherChannelBridge3() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel2());
return handler;
}
@Bean
@ServiceActivator(inputChannel = "scatterAuctionWithGatherChannel")
public MessageHandler auctionWithGatherChannelBridge4() {
BridgeHandler handler = new BridgeHandler();
handler.setOutputChannel(serviceChannel2());
return handler;
}
@Bean
public MessageChannel serviceChannel2() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "serviceChannel2")
public MessageHandler service2() {
return new AbstractReplyProducingMessageHandler() {
{
setOutputChannel(gatherChannel());
}
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
return Math.random();
}
};
}
}
}