diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterOutboundChannelAdapterParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterOutboundChannelAdapterParser.java index 711222038c..7fac8f68f6 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterOutboundChannelAdapterParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterOutboundChannelAdapterParser.java @@ -18,10 +18,14 @@ package org.springframework.integration.twitter.config; import static org.springframework.integration.twitter.config.TwitterNamespaceHandler.BASE_PACKAGE; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; +import org.springframework.util.StringUtils; + import org.w3c.dom.Element; /** @@ -38,6 +42,12 @@ public class TwitterOutboundChannelAdapterParser extends AbstractOutboundChannel String className = determineClassName(element, parserContext); BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(className); builder.addConstructorArgReference(element.getAttribute("twitter-template")); + String targetUserExpression = element.getAttribute("target-user-expression"); + if (StringUtils.hasText(targetUserExpression)){ + BeanDefinition expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(targetUserExpression); + builder.addPropertyValue("targetUserExpression", expressionDef); + } return builder.getBeanDefinition(); } @@ -54,6 +64,7 @@ public class TwitterOutboundChannelAdapterParser extends AbstractOutboundChannel else { parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element); } + return className; } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java index e6b3ff0db2..62ac5fc98c 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java @@ -16,6 +16,14 @@ package org.springframework.integration.twitter.outbound; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.core.convert.ConversionService; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.StandardTypeConverter; import org.springframework.integration.Message; import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.twitter.core.TwitterHeaders; @@ -32,6 +40,10 @@ import org.springframework.util.Assert; public class DirectMessageSendingMessageHandler extends AbstractMessageHandler { private final TwitterOperations twitterOperations; + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + private static final ExpressionParser PARSER = new SpelExpressionParser(); + + private volatile Expression targetUserExpression; public DirectMessageSendingMessageHandler(TwitterOperations twitterOperations) { @@ -39,14 +51,20 @@ public class DirectMessageSendingMessageHandler extends AbstractMessageHandler { this.twitterOperations = twitterOperations; } + public void setTargetUserExpression(Expression targetUserExpression) { + Assert.notNull(targetUserExpression, "'targetUserExpression' must not be null"); + this.targetUserExpression = targetUserExpression; + } @Override protected void handleMessageInternal(Message message) throws Exception { Assert.isInstanceOf(String.class, message.getPayload(), "Only payload of type String is supported. If your payload " + "is not of type String consider adding a transformer to the message flow in front of this adapter."); - Assert.isTrue(message.getHeaders().containsKey(TwitterHeaders.DM_TARGET_USER_ID), - "the '" + TwitterHeaders.DM_TARGET_USER_ID + "' header is required"); - Object toUser = message.getHeaders().get(TwitterHeaders.DM_TARGET_USER_ID); +// Assert.isTrue(message.getHeaders().containsKey(TwitterHeaders.DM_TARGET_USER_ID), +// "the '" + TwitterHeaders.DM_TARGET_USER_ID + "' header is required"); + + Object toUser = targetUserExpression.getValue(this.evaluationContext, message); + Assert.isTrue(toUser instanceof String || toUser instanceof Integer, "the header '" + TwitterHeaders.DM_TARGET_USER_ID + "' must be either a String (a screenname) or an int (a user ID)"); @@ -58,5 +76,22 @@ public class DirectMessageSendingMessageHandler extends AbstractMessageHandler { this.twitterOperations.sendDirectMessage((String) toUser, payload); } } + + @Override + public void onInit() throws Exception{ + super.onInit(); + BeanFactory beanFactory = this.getBeanFactory(); + if (beanFactory != null) { + this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); + } + ConversionService conversionService = this.getConversionService(); + if (conversionService != null) { + this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService)); + } + if (targetUserExpression == null){ + targetUserExpression = + PARSER.parseExpression("headers[T(org.springframework.integration.twitter.core.TwitterHeaders).DM_TARGET_USER_ID]"); + } + } } diff --git a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd index 1632a97cde..7f0ae7e17b 100644 --- a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd +++ b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd @@ -94,7 +94,15 @@ - + + + + + Allows you to provide a valid SpEL Expression which will compute the target userid. + + + + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml index fce383db4d..178d6c69cb 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml @@ -24,7 +24,10 @@ - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java index 8b3aa2176e..213fa1f819 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java @@ -16,8 +16,16 @@ package org.springframework.integration.twitter.config; +import static junit.framework.Assert.assertEquals; + import org.junit.Test; + +import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.expression.Expression; +import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler; /** * @author Oleg Zhurakousky @@ -27,8 +35,12 @@ public class TestSendingMessageHandlerParserTests { @Test public void testSendingMessageHandlerSuccessfulBootstrap(){ - new ClassPathXmlApplicationContext("TestSendingMessageHandlerParser-context.xml", this.getClass()); - // the fact that no exception was thrown satisfies this test + ApplicationContext ac = new ClassPathXmlApplicationContext("TestSendingMessageHandlerParser-context.xml", this.getClass()); + EventDrivenConsumer dmAdapter = ac.getBean("dmAdapter", EventDrivenConsumer.class); + DirectMessageSendingMessageHandler handler = + (DirectMessageSendingMessageHandler) TestUtils.getPropertyValue(dmAdapter, "handler"); + Expression targetUserExpression = (Expression) TestUtils.getPropertyValue(handler, "targetUserExpression"); + assertEquals("'z' + '_oleg'", targetUserExpression.getExpressionString()); } } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandlerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandlerTests.java index 466ca7c2f3..db6e2b9227 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandlerTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandlerTests.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.verify; import org.junit.Test; import org.springframework.integration.Message; +import org.springframework.integration.config.ExpressionFactoryBean; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.twitter.core.TwitterHeaders; import org.springframework.integration.twitter.core.TwitterOperations; @@ -47,5 +48,17 @@ public class DirectMessageSendingMessageHandlerTests { handler.handleMessage(message2); verify(twitter, times(1)).sendDirectMessage(123, "hello"); } + + @Test + public void validateSendDirectMessageWithTargetUserExpression() throws Exception{ + Message message1 = MessageBuilder.withPayload("hello").build(); + DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(twitter); + ExpressionFactoryBean efb = new ExpressionFactoryBean("'z' + '_oleg'"); + efb.afterPropertiesSet(); + handler.setTargetUserExpression(efb.getObject()); + handler.afterPropertiesSet(); + handler.handleMessage(message1); + verify(twitter, times(1)).sendDirectMessage("z_oleg", "hello"); + } }