/*
* 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.channel.config;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
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.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.Executor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.ExecutorChannel;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.TestChannelInterceptor;
import org.springframework.integration.dispatcher.RoundRobinLoadBalancingStrategy;
import org.springframework.integration.dispatcher.UnicastingDispatcher;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.util.ErrorHandlingTaskExecutor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @author Iwein Fuld
* @author Gunnar Hillert
* @author Gary Russell
*
* @see ChannelWithCustomQueueParserTests
*/
@ContextConfiguration(locations = {
"/org/springframework/integration/channel/config/ChannelParserTests-context.xml",
"/org/springframework/integration/channel/config/priorityChannelParserTests.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class ChannelParserTests {
@Autowired
private ApplicationContext context;
@Test(expected = FatalBeanException.class)
public void testChannelWithoutId() {
new ClassPathXmlApplicationContext("channelWithoutId.xml", this.getClass()).close();
}
@Test
public void testChannelWithCapacity() {
MessageChannel channel = (MessageChannel) context.getBean("capacityChannel");
for (int i = 0; i < 10; i++) {
boolean result = channel.send(new GenericMessage<String>("test"), 10);
assertTrue(result);
}
assertFalse(channel.send(new GenericMessage<String>("test"), 3));
}
@Test
public void testDirectChannelByDefault() throws InterruptedException {
MessageChannel channel = (MessageChannel) context.getBean("defaultChannel");
assertThat(channel, instanceOf(DirectChannel.class));
DirectFieldAccessor accessor = new DirectFieldAccessor(channel);
Object dispatcher = accessor.getPropertyValue("dispatcher");
assertThat(dispatcher, is(instanceOf(UnicastingDispatcher.class)));
assertThat(new DirectFieldAccessor(dispatcher).getPropertyValue("loadBalancingStrategy"),
is(instanceOf(RoundRobinLoadBalancingStrategy.class)));
}
@Test
public void testExecutorChannel() throws InterruptedException {
MessageChannel channel = context.getBean("executorChannel", MessageChannel.class);
assertThat(channel, instanceOf(ExecutorChannel.class));
assertNotNull(TestUtils.getPropertyValue(channel, "messageConverter"));
assertNotNull(TestUtils.getPropertyValue(channel, "messageConverter.conversionService"));
}
@Test
public void testExecutorChannelNoConverter() throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"ChannelParserTests-no-converter-context.xml", this.getClass());
MessageChannel channel = context.getBean("executorChannel", MessageChannel.class);
assertThat(channel, instanceOf(ExecutorChannel.class));
assertNotNull(TestUtils.getPropertyValue(channel, "messageConverter"));
assertNotNull(TestUtils.getPropertyValue(channel, "messageConverter.conversionService"));
context.close();
}
@Test
public void channelWithFailoverDispatcherAttribute() throws Exception {
MessageChannel channel = (MessageChannel) context.getBean("channelWithFailover");
assertEquals(DirectChannel.class, channel.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(channel);
Object dispatcher = accessor.getPropertyValue("dispatcher");
assertThat(dispatcher, is(instanceOf(UnicastingDispatcher.class)));
assertNull(new DirectFieldAccessor(dispatcher).getPropertyValue("loadBalancingStrategy"));
}
@Test
public void testPublishSubscribeChannel() throws InterruptedException {
MessageChannel channel = (MessageChannel) context.getBean("publishSubscribeChannel");
assertEquals(PublishSubscribeChannel.class, channel.getClass());
}
@Test
public void testPublishSubscribeChannelWithTaskExecutorReference() throws InterruptedException {
MessageChannel channel = (MessageChannel) context.getBean("publishSubscribeChannelWithTaskExecutorRef");
assertEquals(PublishSubscribeChannel.class, channel.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(channel);
accessor = new DirectFieldAccessor(accessor.getPropertyValue("dispatcher"));
Object executorProperty = accessor.getPropertyValue("executor");
assertNotNull(executorProperty);
assertEquals(ErrorHandlingTaskExecutor.class, executorProperty.getClass());
DirectFieldAccessor executorAccessor = new DirectFieldAccessor(executorProperty);
Executor innerExecutor = (Executor) executorAccessor.getPropertyValue("executor");
Object executorBean = context.getBean("taskExecutor");
assertEquals(executorBean, innerExecutor);
}
@Test
public void channelWithCustomQueue() {
Object customQueue = context.getBean("customQueue");
Object channelWithCustomQueue = context.getBean("channelWithCustomQueue");
assertEquals(QueueChannel.class, channelWithCustomQueue.getClass());
Object actualQueue = new DirectFieldAccessor(channelWithCustomQueue).getPropertyValue("queue");
assertSame(customQueue, actualQueue);
}
@Test
public void testDatatypeChannelWithCorrectType() {
MessageChannel channel = (MessageChannel) context.getBean("integerChannel");
assertTrue(channel.send(new GenericMessage<Integer>(123)));
}
@Test(expected = MessageDeliveryException.class)
public void testDatatypeChannelWithIncorrectType() {
MessageChannel channel = (MessageChannel) context.getBean("integerChannel");
channel.send(new GenericMessage<String>("incorrect type"));
assertTrue(TestUtils.getPropertyValue(channel, "messageConverter") instanceof UselessMessageConverter);
}
@Test
public void testDatatypeChannelGlobalConverter() {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("channelParserGlobalConverterTests.xml", getClass());
MessageChannel channel = context.getBean("integerChannel", MessageChannel.class);
context.close();
assertTrue(TestUtils.getPropertyValue(channel, "messageConverter") instanceof UselessMessageConverter);
}
@Test
public void testDatatypeChannelWithAssignableSubTypes() {
MessageChannel channel = (MessageChannel) context.getBean("numberChannel");
assertTrue(channel.send(new GenericMessage<>(123)));
assertTrue(channel.send(new GenericMessage<>(123.45)));
assertTrue(channel.send(new GenericMessage<>(Boolean.TRUE)));
assertThat(TestUtils.getPropertyValue(channel, "messageConverter"),
instanceOf(DefaultDatatypeChannelMessageConverter.class));
assertNotNull(TestUtils.getPropertyValue(channel, "messageConverter.conversionService"));
}
@Test
public void testMultipleDatatypeChannelWithCorrectTypes() {
MessageChannel channel = (MessageChannel) context.getBean("stringOrNumberChannel");
assertTrue(channel.send(new GenericMessage<>(123)));
assertTrue(channel.send(new GenericMessage<>("accepted type")));
}
@Test(expected = MessageDeliveryException.class)
public void testMultipleDatatypeChannelWithIncorrectType() {
MessageChannel channel = (MessageChannel) context.getBean("stringOrNumberChannel");
channel.send(new GenericMessage<>(Boolean.TRUE));
}
@Test
public void testChannelInteceptorRef() {
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("channelInterceptorParserTests.xml", getClass());
PollableChannel channel = (PollableChannel) context.getBean("channelWithInterceptorRef");
TestChannelInterceptor interceptor = (TestChannelInterceptor) context.getBean("interceptor");
assertEquals(0, interceptor.getSendCount());
channel.send(new GenericMessage<>("test"));
assertEquals(1, interceptor.getSendCount());
assertEquals(0, interceptor.getReceiveCount());
channel.receive();
assertEquals(1, interceptor.getReceiveCount());
context.close();
}
@Test
public void testChannelInteceptorInnerBean() {
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("channelInterceptorParserTests.xml", getClass());
PollableChannel channel = (PollableChannel) context.getBean("channelWithInterceptorInnerBean");
channel.send(new GenericMessage<String>("test"));
Message<?> transformed = channel.receive(1000);
assertEquals("TEST", transformed.getPayload());
context.close();
}
@Test
public void testPriorityChannelWithDefaultComparator() {
PollableChannel channel = this.context.getBean("priorityChannelWithDefaultComparator", PollableChannel.class);
Message<String> lowPriorityMessage = MessageBuilder.withPayload("low").setPriority(-14).build();
Message<String> midPriorityMessage = MessageBuilder.withPayload("mid").setPriority(0).build();
Message<String> highPriorityMessage = MessageBuilder.withPayload("high").setPriority(99).build();
channel.send(lowPriorityMessage);
channel.send(highPriorityMessage);
channel.send(midPriorityMessage);
Message<?> reply1 = channel.receive(0);
Message<?> reply2 = channel.receive(0);
Message<?> reply3 = channel.receive(0);
assertEquals("high", reply1.getPayload());
assertEquals("mid", reply2.getPayload());
assertEquals("low", reply3.getPayload());
}
@Test
public void testPriorityChannelWithCustomComparator() {
PollableChannel channel = this.context.getBean("priorityChannelWithCustomComparator", PollableChannel.class);
channel.send(new GenericMessage<>("C"));
channel.send(new GenericMessage<>("A"));
channel.send(new GenericMessage<>("D"));
channel.send(new GenericMessage<>("B"));
Message<?> reply1 = channel.receive(0);
Message<?> reply2 = channel.receive(0);
Message<?> reply3 = channel.receive(0);
Message<?> reply4 = channel.receive(0);
assertEquals("A", reply1.getPayload());
assertEquals("B", reply2.getPayload());
assertEquals("C", reply3.getPayload());
assertEquals("D", reply4.getPayload());
}
@Test
public void testPriorityChannelWithIntegerDatatypeEnforced() {
PollableChannel channel = this.context.getBean("integerOnlyPriorityChannel", PollableChannel.class);
channel.send(new GenericMessage<>(3));
channel.send(new GenericMessage<>(2));
channel.send(new GenericMessage<>(1));
assertEquals(1, channel.receive(0).getPayload());
assertEquals(2, channel.receive(0).getPayload());
assertEquals(3, channel.receive(0).getPayload());
boolean threwException = false;
try {
channel.send(new GenericMessage<>("wrong type"));
}
catch (MessageDeliveryException e) {
assertEquals("wrong type", e.getFailedMessage().getPayload());
threwException = true;
}
assertTrue(threwException);
}
public static class TestInterceptor extends ChannelInterceptorAdapter {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
return MessageBuilder.withPayload(message.getPayload().toString().toUpperCase()).build();
}
}
public static class TestConverter implements Converter<Boolean, Number> {
@Override
public Number convert(Boolean source) {
return source ? 1 : 0;
}
}
public static class UselessMessageConverter implements MessageConverter {
@Override
public Object fromMessage(Message<?> message, Class<?> targetClass) {
return null;
}
@Override
public Message<?> toMessage(Object payload, MessageHeaders header) {
return null;
}
}
}