INT-2999 Add BeanResolvers to AMQP OB Endpoints

Expressions (routing key, exchange, correlation data) did
not resolve beans. Need to add the BeanFactory (if present)
to the MessageProcessors.

Add test case.
This commit is contained in:
Gary Russell
2013-04-29 18:30:33 -04:00
committed by Mark Fisher
parent 121b28f426
commit d5ce090d19
2 changed files with 52 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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
@@ -23,6 +23,7 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
@@ -87,21 +88,31 @@ public class AmqpOutboundEndpoint extends AbstractReplyProducingMessageHandler
"Either an exchangeName or an exchangeNameExpression can be provided, but not both");
Assert.state(this.confirmCorrelationExpression == null || !this.expectReply,
"Confirm correlation expression does not apply to a gateway");
BeanFactory beanFactory = this.getBeanFactory();
if (exchangeNameExpression != null) {
Expression expression = expressionParser.parseExpression(this.exchangeNameExpression);
this.exchangeNameGenerator = new ExpressionEvaluatingMessageProcessor<String>(expression, String.class);
if (beanFactory != null) {
this.exchangeNameGenerator.setBeanFactory(beanFactory);
}
}
Assert.state(routingKeyExpression == null || routingKey == null,
"Either a routingKey or a routingKeyExpression can be provided, but not both");
if (routingKeyExpression != null) {
Expression expression = expressionParser.parseExpression(this.routingKeyExpression);
this.routingKeyGenerator = new ExpressionEvaluatingMessageProcessor<String>(expression, String.class);
if (beanFactory != null) {
this.routingKeyGenerator.setBeanFactory(beanFactory);
}
}
if (this.confirmCorrelationExpression != null) {
Expression expression = expressionParser.parseExpression(this.confirmCorrelationExpression);
this.correlationDataGenerator = new ExpressionEvaluatingMessageProcessor<Object>(expression, Object.class);
Assert.isTrue(amqpTemplate instanceof RabbitTemplate, "RabbitTemplate implementation is required for publisher confirms");
((RabbitTemplate) this.amqpTemplate).setConfirmCallback(this);
if (beanFactory != null) {
this.correlationDataGenerator.setBeanFactory(beanFactory);
}
}
if (this.returnChannel != null) {
Assert.isTrue(amqpTemplate instanceof RabbitTemplate, "RabbitTemplate implementation is required for publisher returns");

View File

@@ -16,12 +16,24 @@
package org.springframework.integration.amqp.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.amqp.outbound.AmqpOutboundEndpoint;
import org.springframework.integration.handler.MessageProcessor;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.util.ReflectionTestUtils;
/**
@@ -31,7 +43,7 @@ import org.springframework.test.util.ReflectionTestUtils;
*/
public class OutboundGatewayTests {
private ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
private final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
@Test
public void testVanillaConfiguration() throws Exception {
@@ -46,4 +58,30 @@ public class OutboundGatewayTests {
assertNotNull(ReflectionTestUtils.getField(ReflectionTestUtils.getField(target, "handler"), "routingKeyGenerator"));
}
@SuppressWarnings("unchecked")
@Test
public void testExpressionsBeanResolver() {
BeanFactory bf = mock(BeanFactory.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArguments()[0] + "bar";
}
}).when(bf).getBean(anyString());
RabbitTemplate template = mock(RabbitTemplate.class);
AmqpOutboundEndpoint endpoint = new AmqpOutboundEndpoint(template);
endpoint.setRoutingKeyExpression("@foo");
endpoint.setExchangeNameExpression("@bar");
endpoint.setConfirmCorrelationExpression("@baz");
endpoint.setBeanFactory(bf);
endpoint.afterPropertiesSet();
Message<?> message = new GenericMessage<String>("Hello, world!");
assertEquals("foobar", TestUtils.getPropertyValue(endpoint, "routingKeyGenerator", MessageProcessor.class)
.processMessage(message));
assertEquals("barbar", TestUtils.getPropertyValue(endpoint, "exchangeNameGenerator", MessageProcessor.class)
.processMessage(message));
assertEquals("bazbar", TestUtils.getPropertyValue(endpoint, "correlationDataGenerator", MessageProcessor.class)
.processMessage(message));
}
}