INT-1636 added 'target-user-expression' to the Twitter DM adapter

This commit is contained in:
Oleg Zhurakousky
2010-12-10 16:00:13 -05:00
parent 69c0a8bdcf
commit 2a456d9373
6 changed files with 89 additions and 7 deletions

View File

@@ -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;
}

View File

@@ -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]");
}
}
}

View File

@@ -94,7 +94,15 @@
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type"/>
<xsd:extension base="outbound-twitter-type">
<xsd:attribute name="target-user-expression" use="optional">
<xsd:annotation>
<xsd:documentation>
Allows you to provide a valid SpEL Expression which will compute the target userid.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>

View File

@@ -24,7 +24,10 @@
<channel id="inputChannel"/>
<twitter:dm-outbound-channel-adapter twitter-template="twitter" channel="inputChannel" />
<twitter:dm-outbound-channel-adapter id="dmAdapter"
twitter-template="twitter"
channel="inputChannel"
target-user-expression="'z' + '_oleg'"/>
<twitter:outbound-channel-adapter twitter-template="twitter" channel="inputChannel" />

View File

@@ -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());
}
}

View File

@@ -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");
}
}