/*
* Copyright 2013-2017 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.amqp.inbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.amqp.support.DefaultAmqpHeaderMapper;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.json.JsonToObjectTransformer;
import org.springframework.integration.json.ObjectToJsonTransformer;
import org.springframework.integration.mapping.support.JsonHeaders;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.transformer.MessageTransformingHandler;
import org.springframework.integration.transformer.Transformer;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import com.rabbitmq.client.Channel;
/**
* @author Artem Bilan
* @author Gary Russell
* @since 3.0
*/
public class InboundEndpointTests {
@Test
public void testInt2809JavaTypePropertiesToAmqp() throws Exception {
Connection connection = mock(Connection.class);
doAnswer(invocation -> mock(Channel.class)).when(connection).createChannel(anyBoolean());
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
when(connectionFactory.createConnection()).thenReturn(connection);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(container);
adapter.setMessageConverter(new Jackson2JsonMessageConverter());
PollableChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
adapter.setBeanFactory(mock(BeanFactory.class));
adapter.afterPropertiesSet();
Object payload = new Foo("bar1");
Transformer objectToJsonTransformer = new ObjectToJsonTransformer();
Message<?> jsonMessage = objectToJsonTransformer.transform(new GenericMessage<Object>(payload));
MessageProperties amqpMessageProperties = new MessageProperties();
amqpMessageProperties.setDeliveryTag(123L);
org.springframework.amqp.core.Message amqpMessage =
new SimpleMessageConverter().toMessage(jsonMessage.getPayload(), amqpMessageProperties);
DefaultAmqpHeaderMapper.inboundMapper().fromHeadersToRequest(jsonMessage.getHeaders(), amqpMessageProperties);
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Channel rabbitChannel = mock(Channel.class);
listener.onMessage(amqpMessage, rabbitChannel);
Message<?> result = channel.receive(1000);
assertEquals(payload, result.getPayload());
assertSame(rabbitChannel, result.getHeaders().get(AmqpHeaders.CHANNEL));
assertEquals(123L, result.getHeaders().get(AmqpHeaders.DELIVERY_TAG));
}
@Test
public void testInt2809JavaTypePropertiesFromAmqp() throws Exception {
Connection connection = mock(Connection.class);
doAnswer(invocation -> mock(Channel.class)).when(connection).createChannel(anyBoolean());
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
when(connectionFactory.createConnection()).thenReturn(connection);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(container);
PollableChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
adapter.setBeanFactory(mock(BeanFactory.class));
adapter.afterPropertiesSet();
Object payload = new Foo("bar1");
MessageProperties amqpMessageProperties = new MessageProperties();
org.springframework.amqp.core.Message amqpMessage =
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
listener.onMessage(amqpMessage, null);
Message<?> receive = channel.receive(1000);
Message<?> result = new JsonToObjectTransformer().transform(receive);
assertEquals(payload, result.getPayload());
}
@Test
public void testMessageConverterJsonHeadersHavePrecedenceOverMessageHeaders() throws Exception {
Connection connection = mock(Connection.class);
doAnswer(invocation -> mock(Channel.class)).when(connection).createChannel(anyBoolean());
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
when(connectionFactory.createConnection()).thenReturn(connection);
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
DirectChannel channel = new DirectChannel();
final Channel rabbitChannel = mock(Channel.class);
channel.subscribe(new MessageTransformingHandler(message -> {
assertSame(rabbitChannel, message.getHeaders().get(AmqpHeaders.CHANNEL));
assertEquals(123L, message.getHeaders().get(AmqpHeaders.DELIVERY_TAG));
return MessageBuilder.fromMessage(message)
.setHeader(JsonHeaders.TYPE_ID, "foo")
.setHeader(JsonHeaders.CONTENT_TYPE_ID, "bar")
.setHeader(JsonHeaders.KEY_TYPE_ID, "baz")
.build();
}));
RabbitTemplate rabbitTemplate = spy(new RabbitTemplate());
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
CountDownLatch sendLatch = new CountDownLatch(1);
Mockito.doAnswer(invocation -> {
org.springframework.amqp.core.Message message =
invocation.getArgument(2);
Map<String, Object> headers = message.getMessageProperties().getHeaders();
assertTrue(headers.containsKey(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertNotEquals("foo", headers.get(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertFalse(headers.containsKey(JsonHeaders.KEY_TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
assertFalse(headers.containsKey(JsonHeaders.TYPE_ID));
assertFalse(headers.containsKey(JsonHeaders.KEY_TYPE_ID));
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID));
sendLatch.countDown();
return null;
}).when(rabbitTemplate)
.send(anyString(), anyString(), any(org.springframework.amqp.core.Message.class), isNull());
AmqpInboundGateway gateway = new AmqpInboundGateway(container, rabbitTemplate);
gateway.setMessageConverter(new Jackson2JsonMessageConverter());
gateway.setRequestChannel(channel);
gateway.setBeanFactory(mock(BeanFactory.class));
gateway.setDefaultReplyTo("foo");
gateway.afterPropertiesSet();
Object payload = new Foo("bar1");
MessageProperties amqpMessageProperties = new MessageProperties();
amqpMessageProperties.setDeliveryTag(123L);
org.springframework.amqp.core.Message amqpMessage =
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
listener.onMessage(amqpMessage, rabbitChannel);
assertTrue(sendLatch.await(10, TimeUnit.SECONDS));
}
public static class Foo {
private String bar;
public Foo() {
}
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Foo foo = (Foo) o;
return !(bar != null ? !bar.equals(foo.bar) : foo.bar != null);
}
@Override
public int hashCode() {
return bar != null ? bar.hashCode() : 0;
}
}
}