Twitter - Fix DOS Newlines

This commit is contained in:
Gary Russell
2018-09-27 17:16:49 -04:00
parent c211d51776
commit 6402ab0422
36 changed files with 2805 additions and 2805 deletions

View File

@@ -1,74 +1,74 @@
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource;
import org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource;
import org.springframework.integration.twitter.inbound.SearchReceivingMessageSource;
import org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource;
/**
* Parser for inbound Twitter Channel Adapters.
*
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TwitterInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
@Override
protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) {
Class<?> clazz = determineClass(element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
builder.addConstructorArgValue(element.getAttribute(ID_ATTRIBUTE));
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "query");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "page-size");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "metadata-store");
return builder.getBeanDefinition();
}
private static Class<?> determineClass(Element element, ParserContext parserContext) {
Class<?> clazz = null;
String elementName = element.getLocalName().trim();
if ("inbound-channel-adapter".equals(elementName)) {
clazz = TimelineReceivingMessageSource.class;
}
else if ("dm-inbound-channel-adapter".equals(elementName)) {
clazz = DirectMessageReceivingMessageSource.class;
}
else if ("mentions-inbound-channel-adapter".equals(elementName)) {
clazz = MentionsReceivingMessageSource.class;
}
else if ("search-inbound-channel-adapter".equals(elementName)) {
clazz = SearchReceivingMessageSource.class;
}
else {
parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element);
}
return clazz;
}
}
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource;
import org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource;
import org.springframework.integration.twitter.inbound.SearchReceivingMessageSource;
import org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource;
/**
* Parser for inbound Twitter Channel Adapters.
*
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TwitterInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
@Override
protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) {
Class<?> clazz = determineClass(element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
builder.addConstructorArgValue(element.getAttribute(ID_ATTRIBUTE));
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "query");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "page-size");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "metadata-store");
return builder.getBeanDefinition();
}
private static Class<?> determineClass(Element element, ParserContext parserContext) {
Class<?> clazz = null;
String elementName = element.getLocalName().trim();
if ("inbound-channel-adapter".equals(elementName)) {
clazz = TimelineReceivingMessageSource.class;
}
else if ("dm-inbound-channel-adapter".equals(elementName)) {
clazz = DirectMessageReceivingMessageSource.class;
}
else if ("mentions-inbound-channel-adapter".equals(elementName)) {
clazz = MentionsReceivingMessageSource.class;
}
else if ("search-inbound-channel-adapter".equals(elementName)) {
clazz = SearchReceivingMessageSource.class;
}
else {
parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element);
}
return clazz;
}
}

View File

@@ -1,44 +1,44 @@
/*
* Copyright 2018 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.twitter.config;
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
/**
* Namespace handler for the Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TwitterNamespaceHandler extends AbstractIntegrationNamespaceHandler {
@Override
public void init() {
// inbound
registerBeanDefinitionParser("inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("dm-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("mentions-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("search-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
// outbound
registerBeanDefinitionParser("outbound-channel-adapter", new TwitterOutboundChannelAdapterParser());
registerBeanDefinitionParser("dm-outbound-channel-adapter", new TwitterOutboundChannelAdapterParser());
registerBeanDefinitionParser("search-outbound-gateway", new TwitterSearchOutboundGatewayParser());
}
}
/*
* Copyright 2018 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.twitter.config;
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
/**
* Namespace handler for the Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TwitterNamespaceHandler extends AbstractIntegrationNamespaceHandler {
@Override
public void init() {
// inbound
registerBeanDefinitionParser("inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("dm-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("mentions-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
registerBeanDefinitionParser("search-inbound-channel-adapter", new TwitterInboundChannelAdapterParser());
// outbound
registerBeanDefinitionParser("outbound-channel-adapter", new TwitterOutboundChannelAdapterParser());
registerBeanDefinitionParser("dm-outbound-channel-adapter", new TwitterOutboundChannelAdapterParser());
registerBeanDefinitionParser("search-outbound-gateway", new TwitterSearchOutboundGatewayParser());
}
}

View File

@@ -1,70 +1,70 @@
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
import org.springframework.integration.twitter.outbound.StatusUpdatingMessageHandler;
import org.springframework.util.StringUtils;
/**
* Parser for all outbound Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
public class TwitterOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
Class<?> clazz = determineClass(element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
String tweetDataExpression = element.getAttribute("tweet-data-expression");
if (StringUtils.hasText(tweetDataExpression)) {
builder.addPropertyValue("tweetDataExpression",
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
.addConstructorArgValue(tweetDataExpression)
.getBeanDefinition());
}
return builder.getBeanDefinition();
}
private static Class<?> determineClass(Element element, ParserContext parserContext) {
Class<?> clazz = null;
String elementName = element.getLocalName().trim();
if ("outbound-channel-adapter".equals(elementName)) {
clazz = StatusUpdatingMessageHandler.class;
}
else if ("dm-outbound-channel-adapter".equals(elementName)) {
clazz = DirectMessageSendingMessageHandler.class;
}
else {
parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element);
}
return clazz;
}
}
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
import org.springframework.integration.twitter.outbound.StatusUpdatingMessageHandler;
import org.springframework.util.StringUtils;
/**
* Parser for all outbound Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
public class TwitterOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
Class<?> clazz = determineClass(element, parserContext);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
String tweetDataExpression = element.getAttribute("tweet-data-expression");
if (StringUtils.hasText(tweetDataExpression)) {
builder.addPropertyValue("tweetDataExpression",
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
.addConstructorArgValue(tweetDataExpression)
.getBeanDefinition());
}
return builder.getBeanDefinition();
}
private static Class<?> determineClass(Element element, ParserContext parserContext) {
Class<?> clazz = null;
String elementName = element.getLocalName().trim();
if ("outbound-channel-adapter".equals(elementName)) {
clazz = StatusUpdatingMessageHandler.class;
}
else if ("dm-outbound-channel-adapter".equals(elementName)) {
clazz = DirectMessageSendingMessageHandler.class;
}
else {
parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element);
}
return clazz;
}
}

View File

@@ -1,59 +1,59 @@
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
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.ExpressionFactoryBean;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway;
import org.springframework.util.StringUtils;
/**
* Parser for {@code <int-twitter:search-outbound-gateway/>}.
*
* @author Gary Russell
*/
public class TwitterSearchOutboundGatewayParser extends AbstractConsumerEndpointParser {
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
}
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TwitterSearchOutboundGateway.class);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
String searchArgsExpression = element.getAttribute("search-args-expression");
if (StringUtils.hasText(searchArgsExpression)) {
BeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(searchArgsExpression);
builder.addPropertyValue("searchArgsExpression", expressionDef);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
return builder;
}
}
/*
* Copyright 2018 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.twitter.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
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.ExpressionFactoryBean;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway;
import org.springframework.util.StringUtils;
/**
* Parser for {@code <int-twitter:search-outbound-gateway/>}.
*
* @author Gary Russell
*/
public class TwitterSearchOutboundGatewayParser extends AbstractConsumerEndpointParser {
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
}
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TwitterSearchOutboundGateway.class);
builder.addConstructorArgReference(element.getAttribute("twitter-template"));
String searchArgsExpression = element.getAttribute("search-args-expression");
if (StringUtils.hasText(searchArgsExpression)) {
BeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(searchArgsExpression);
builder.addPropertyValue("searchArgsExpression", expressionDef);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
return builder;
}
}

View File

@@ -1,4 +1,4 @@
/**
* Contains parser classes for the Twitter namespace support.
*/
package org.springframework.integration.twitter.config;
/**
* Contains parser classes for the Twitter namespace support.
*/
package org.springframework.integration.twitter.config;

View File

@@ -1,43 +1,43 @@
/*
* Copyright 2018 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.twitter.core;
/**
* Header keys used by the various Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
*/
public final class TwitterHeaders {
private static final String PREFIX = "twitter_";
/**
* The name of the header for the target user for DM.
*/
public static final String DM_TARGET_USER_ID = PREFIX + "dmTargetUserId";
/**
* The name of the header for the search metadata.
*/
public static final String SEARCH_METADATA = PREFIX + "searchMetadata";
private TwitterHeaders() { }
}
/*
* Copyright 2018 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.twitter.core;
/**
* Header keys used by the various Twitter adapters.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
*/
public final class TwitterHeaders {
private static final String PREFIX = "twitter_";
/**
* The name of the header for the target user for DM.
*/
public static final String DM_TARGET_USER_ID = PREFIX + "dmTargetUserId";
/**
* The name of the header for the search metadata.
*/
public static final String SEARCH_METADATA = PREFIX + "searchMetadata";
private TwitterHeaders() { }
}

View File

@@ -1,4 +1,4 @@
/**
* Provides classes used across all Twitter components.
*/
package org.springframework.integration.twitter.core;
/**
* Provides classes used across all Twitter components.
*/
package org.springframework.integration.twitter.core;

View File

@@ -1,295 +1,295 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.Lifecycle;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.metadata.MetadataStore;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.UserOperations;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Abstract class that defines common operations for receiving various types of
* messages when using the Twitter API. This class also handles keeping track of
* the latest inbound message it has received and avoiding, where possible,
* redelivery of duplicate messages. This functionality is enabled using the
* {@link org.springframework.integration.metadata.MetadataStore} strategy.
*
* @param <T> the target twitter object type.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gunnar Hillert
* @author Artem Bilan
*/
abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport implements MessageSource<T>,
Lifecycle {
private static final int DEFAULT_PAGE_SIZE = 20;
private final Twitter twitter;
private final TweetComparator tweetComparator = new TweetComparator();
private final Object lastEnqueuedIdMonitor = new Object();
private final String metadataKey;
private final Queue<T> tweets = new LinkedBlockingQueue<T>();
private volatile MetadataStore metadataStore;
private volatile int prefetchThreshold = 0;
private volatile long lastEnqueuedId = -1;
private volatile long lastProcessedId = -1;
private volatile int pageSize = DEFAULT_PAGE_SIZE;
private volatile boolean running;
protected AbstractTwitterMessageSource(Twitter twitter, String metadataKey) {
Assert.notNull(twitter, "twitter must not be null");
Assert.notNull(metadataKey, "metadataKey must not be null");
this.twitter = twitter;
if (this.twitter.isAuthorized()) {
UserOperations userOperations = this.twitter.userOperations();
metadataKey += "." + userOperations.getProfileId();
}
this.metadataKey = metadataKey;
}
public void setMetadataStore(MetadataStore metadataStore) {
this.metadataStore = metadataStore;
}
public void setPrefetchThreshold(int prefetchThreshold) {
this.prefetchThreshold = prefetchThreshold;
}
protected Twitter getTwitter() {
return this.twitter;
}
protected int getPageSize() {
return this.pageSize;
}
/**
* Set the limit for the number of results returned on each poll; default 20.
* @param pageSize The pageSize.
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Override
protected void onInit() throws Exception {
super.onInit();
if (this.metadataStore == null) {
// first try to look for a 'metadataStore' in the context
BeanFactory beanFactory = this.getBeanFactory();
if (beanFactory != null) {
this.metadataStore = IntegrationContextUtils.getMetadataStore(beanFactory);
}
if (this.metadataStore == null) {
this.metadataStore = new SimpleMetadataStore();
}
}
}
@Override
public synchronized void start() {
if (!this.running) {
String lastId = this.metadataStore.get(this.metadataKey);
// initialize the last status ID from the metadataStore
if (StringUtils.hasText(lastId)) {
this.lastProcessedId = Long.parseLong(lastId);
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = this.lastProcessedId;
}
}
this.running = true;
}
}
@Override
public synchronized void stop() {
this.running = false;
}
@Override
public synchronized boolean isRunning() {
return this.running;
}
@Override
public Message<T> receive() {
T tweet = this.tweets.poll();
if (tweet == null) {
this.refreshTweetQueueIfNecessary();
tweet = this.tweets.poll();
}
if (tweet != null) {
this.lastProcessedId = this.getIdForTweet(tweet);
this.metadataStore.put(this.metadataKey, String.valueOf(this.lastProcessedId));
return this.getMessageBuilderFactory().withPayload(tweet).build();
}
return null;
}
private void enqueueAll(List<T> tweets) {
tweets.sort(this.tweetComparator);
tweets.forEach(this::enqueue);
}
private void enqueue(T tweet) {
synchronized (this.lastEnqueuedIdMonitor) {
long id = this.getIdForTweet(tweet);
if (id > this.lastEnqueuedId) {
this.tweets.add(tweet);
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = id;
}
}
}
}
private void refreshTweetQueueIfNecessary() {
try {
if (this.tweets.size() <= this.prefetchThreshold) {
synchronized (this.lastEnqueuedIdMonitor) {
List<T> tweets = pollForTweets(this.lastEnqueuedId);
if (!CollectionUtils.isEmpty(tweets)) {
enqueueAll(tweets);
}
}
}
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new MessagingException("failed while polling Twitter", e);
}
}
/**
* Subclasses must implement this to return tweets.
* The 'sinceId' value will be negative if no last id is known.
*
* @param sinceId The id of the last reported tweet.
* @return The list of tweets.
*/
protected abstract List<T> pollForTweets(long sinceId);
private long getIdForTweet(T twitterMessage) {
if (twitterMessage instanceof Tweet) {
return ((Tweet) twitterMessage).getId();
}
else if (twitterMessage instanceof DirectMessage) {
return ((DirectMessage) twitterMessage).getId();
}
else {
throw new IllegalArgumentException("Unsupported Twitter object: " + twitterMessage);
}
}
/**
* Remove the metadata key and the corresponding value from the Metadata Store.
*/
@ManagedOperation(description = "Remove the metadata key and the corresponding value from the Metadata Store.")
void resetMetadataStore() {
synchronized (this) {
this.metadataStore.remove(this.metadataKey);
this.lastProcessedId = -1L;
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = -1L;
}
}
}
/**
* Obtain the last processed id.
* @return {@code -1} if lastProcessedId is not set, yet.
*/
@ManagedAttribute
public long getLastProcessedId() {
return this.lastProcessedId;
}
private class TweetComparator implements Comparator<T> {
TweetComparator() {
super();
}
@Override
public int compare(T tweet1, T tweet2) {
// hopefully temporary logic. Will suggest that SpringSocial use a common base class for DM and Tweet
if (tweet1 instanceof Tweet && tweet2 instanceof Tweet) {
Tweet t1 = (Tweet) tweet1;
Tweet t2 = (Tweet) tweet2;
Date t1CreatedAt = t1.getCreatedAt();
Date t2CreatedAt = t2.getCreatedAt();
Assert.notNull(t1CreatedAt, "Tweet is missing 'createdAt' date. Cannot compare.");
Assert.notNull(t2CreatedAt, "Tweet is missing 'createdAt' date. Cannot compare.");
return t1CreatedAt.compareTo(t2CreatedAt);
}
else if (tweet1 instanceof DirectMessage && tweet2 instanceof DirectMessage) {
DirectMessage d1 = (DirectMessage) tweet1;
DirectMessage d2 = (DirectMessage) tweet2;
Date d1CreatedAt = d1.getCreatedAt();
Date d2CreatedAt = d2.getCreatedAt();
Assert.notNull(d1CreatedAt, "DirectMessage is missing 'createdAt' date. Cannot compare.");
Assert.notNull(d2CreatedAt, "DirectMessage is missing 'createdAt' date. Cannot compare.");
return d1CreatedAt.compareTo(d2CreatedAt);
}
else {
throw new IllegalArgumentException("Uncomparable Twitter objects: " + tweet1 + " and " + tweet2);
}
}
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.Lifecycle;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.metadata.MetadataStore;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.UserOperations;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Abstract class that defines common operations for receiving various types of
* messages when using the Twitter API. This class also handles keeping track of
* the latest inbound message it has received and avoiding, where possible,
* redelivery of duplicate messages. This functionality is enabled using the
* {@link org.springframework.integration.metadata.MetadataStore} strategy.
*
* @param <T> the target twitter object type.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gunnar Hillert
* @author Artem Bilan
*/
abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport implements MessageSource<T>,
Lifecycle {
private static final int DEFAULT_PAGE_SIZE = 20;
private final Twitter twitter;
private final TweetComparator tweetComparator = new TweetComparator();
private final Object lastEnqueuedIdMonitor = new Object();
private final String metadataKey;
private final Queue<T> tweets = new LinkedBlockingQueue<T>();
private volatile MetadataStore metadataStore;
private volatile int prefetchThreshold = 0;
private volatile long lastEnqueuedId = -1;
private volatile long lastProcessedId = -1;
private volatile int pageSize = DEFAULT_PAGE_SIZE;
private volatile boolean running;
protected AbstractTwitterMessageSource(Twitter twitter, String metadataKey) {
Assert.notNull(twitter, "twitter must not be null");
Assert.notNull(metadataKey, "metadataKey must not be null");
this.twitter = twitter;
if (this.twitter.isAuthorized()) {
UserOperations userOperations = this.twitter.userOperations();
metadataKey += "." + userOperations.getProfileId();
}
this.metadataKey = metadataKey;
}
public void setMetadataStore(MetadataStore metadataStore) {
this.metadataStore = metadataStore;
}
public void setPrefetchThreshold(int prefetchThreshold) {
this.prefetchThreshold = prefetchThreshold;
}
protected Twitter getTwitter() {
return this.twitter;
}
protected int getPageSize() {
return this.pageSize;
}
/**
* Set the limit for the number of results returned on each poll; default 20.
* @param pageSize The pageSize.
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
@Override
protected void onInit() throws Exception {
super.onInit();
if (this.metadataStore == null) {
// first try to look for a 'metadataStore' in the context
BeanFactory beanFactory = this.getBeanFactory();
if (beanFactory != null) {
this.metadataStore = IntegrationContextUtils.getMetadataStore(beanFactory);
}
if (this.metadataStore == null) {
this.metadataStore = new SimpleMetadataStore();
}
}
}
@Override
public synchronized void start() {
if (!this.running) {
String lastId = this.metadataStore.get(this.metadataKey);
// initialize the last status ID from the metadataStore
if (StringUtils.hasText(lastId)) {
this.lastProcessedId = Long.parseLong(lastId);
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = this.lastProcessedId;
}
}
this.running = true;
}
}
@Override
public synchronized void stop() {
this.running = false;
}
@Override
public synchronized boolean isRunning() {
return this.running;
}
@Override
public Message<T> receive() {
T tweet = this.tweets.poll();
if (tweet == null) {
this.refreshTweetQueueIfNecessary();
tweet = this.tweets.poll();
}
if (tweet != null) {
this.lastProcessedId = this.getIdForTweet(tweet);
this.metadataStore.put(this.metadataKey, String.valueOf(this.lastProcessedId));
return this.getMessageBuilderFactory().withPayload(tweet).build();
}
return null;
}
private void enqueueAll(List<T> tweets) {
tweets.sort(this.tweetComparator);
tweets.forEach(this::enqueue);
}
private void enqueue(T tweet) {
synchronized (this.lastEnqueuedIdMonitor) {
long id = this.getIdForTweet(tweet);
if (id > this.lastEnqueuedId) {
this.tweets.add(tweet);
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = id;
}
}
}
}
private void refreshTweetQueueIfNecessary() {
try {
if (this.tweets.size() <= this.prefetchThreshold) {
synchronized (this.lastEnqueuedIdMonitor) {
List<T> tweets = pollForTweets(this.lastEnqueuedId);
if (!CollectionUtils.isEmpty(tweets)) {
enqueueAll(tweets);
}
}
}
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new MessagingException("failed while polling Twitter", e);
}
}
/**
* Subclasses must implement this to return tweets.
* The 'sinceId' value will be negative if no last id is known.
*
* @param sinceId The id of the last reported tweet.
* @return The list of tweets.
*/
protected abstract List<T> pollForTweets(long sinceId);
private long getIdForTweet(T twitterMessage) {
if (twitterMessage instanceof Tweet) {
return ((Tweet) twitterMessage).getId();
}
else if (twitterMessage instanceof DirectMessage) {
return ((DirectMessage) twitterMessage).getId();
}
else {
throw new IllegalArgumentException("Unsupported Twitter object: " + twitterMessage);
}
}
/**
* Remove the metadata key and the corresponding value from the Metadata Store.
*/
@ManagedOperation(description = "Remove the metadata key and the corresponding value from the Metadata Store.")
void resetMetadataStore() {
synchronized (this) {
this.metadataStore.remove(this.metadataKey);
this.lastProcessedId = -1L;
synchronized (this.lastEnqueuedIdMonitor) {
this.lastEnqueuedId = -1L;
}
}
}
/**
* Obtain the last processed id.
* @return {@code -1} if lastProcessedId is not set, yet.
*/
@ManagedAttribute
public long getLastProcessedId() {
return this.lastProcessedId;
}
private class TweetComparator implements Comparator<T> {
TweetComparator() {
super();
}
@Override
public int compare(T tweet1, T tweet2) {
// hopefully temporary logic. Will suggest that SpringSocial use a common base class for DM and Tweet
if (tweet1 instanceof Tweet && tweet2 instanceof Tweet) {
Tweet t1 = (Tweet) tweet1;
Tweet t2 = (Tweet) tweet2;
Date t1CreatedAt = t1.getCreatedAt();
Date t2CreatedAt = t2.getCreatedAt();
Assert.notNull(t1CreatedAt, "Tweet is missing 'createdAt' date. Cannot compare.");
Assert.notNull(t2CreatedAt, "Tweet is missing 'createdAt' date. Cannot compare.");
return t1CreatedAt.compareTo(t2CreatedAt);
}
else if (tweet1 instanceof DirectMessage && tweet2 instanceof DirectMessage) {
DirectMessage d1 = (DirectMessage) tweet1;
DirectMessage d2 = (DirectMessage) tweet2;
Date d1CreatedAt = d1.getCreatedAt();
Date d2CreatedAt = d2.getCreatedAt();
Assert.notNull(d1CreatedAt, "DirectMessage is missing 'createdAt' date. Cannot compare.");
Assert.notNull(d2CreatedAt, "DirectMessage is missing 'createdAt' date. Cannot compare.");
return d1CreatedAt.compareTo(d2CreatedAt);
}
else {
throw new IllegalArgumentException("Uncomparable Twitter objects: " + tweet1 + " and " + tweet2);
}
}
}
}

View File

@@ -1,48 +1,48 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Twitter;
/**
* This class handles support for receiving DMs (direct messages) using Twitter.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*/
public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource<DirectMessage> {
public DirectMessageReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:dm-inbound-channel-adapter";
}
@Override
protected List<DirectMessage> pollForTweets(long sinceId) {
return this.getTwitter().directMessageOperations().getDirectMessagesReceived(1, this.getPageSize(), sinceId, 0);
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Twitter;
/**
* This class handles support for receiving DMs (direct messages) using Twitter.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*/
public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource<DirectMessage> {
public DirectMessageReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:dm-inbound-channel-adapter";
}
@Override
protected List<DirectMessage> pollForTweets(long sinceId) {
return this.getTwitter().directMessageOperations().getDirectMessagesReceived(1, this.getPageSize(), sinceId, 0);
}
}

View File

@@ -1,47 +1,47 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
/**
* Receives Message Tweets.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class MentionsReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public MentionsReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:mentions-inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getMentions(this.getPageSize(), sinceId, 0);
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
/**
* Receives Message Tweets.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class MentionsReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public MentionsReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:mentions-inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getMentions(this.getPageSize(), sinceId, 0);
}
}

View File

@@ -1,62 +1,62 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Collections;
import java.util.List;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* The {@link AbstractTwitterMessageSource} implementation for search.
*
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gunnar Hillert
* @author Gary Russell
*/
public class SearchReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
private volatile String query;
public SearchReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
public void setQuery(String query) {
Assert.hasText(query, "'query' must not be null");
this.query = query;
}
@Override
public String getComponentType() {
return "twitter:search-inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
SearchParameters searchParameters = new SearchParameters(this.query).count(this.getPageSize()).sinceId(sinceId);
SearchResults results = this.getTwitter().searchOperations().search(searchParameters);
return (results != null) ? results.getTweets() : Collections.<Tweet>emptyList();
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Collections;
import java.util.List;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* The {@link AbstractTwitterMessageSource} implementation for search.
*
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gunnar Hillert
* @author Gary Russell
*/
public class SearchReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
private volatile String query;
public SearchReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
public void setQuery(String query) {
Assert.hasText(query, "'query' must not be null");
this.query = query;
}
@Override
public String getComponentType() {
return "twitter:search-inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
SearchParameters searchParameters = new SearchParameters(this.query).count(this.getPageSize()).sinceId(sinceId);
SearchResults results = this.getTwitter().searchOperations().search(searchParameters);
return (results != null) ? results.getTweets() : Collections.<Tweet>emptyList();
}
}

View File

@@ -1,48 +1,48 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
/**
* This {@link org.springframework.integration.core.MessageSource} lets Spring Integration consume
* given account's timeline as messages. It has support for dynamic throttling of API requests.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TimelineReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public TimelineReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getHomeTimeline(this.getPageSize(), sinceId, 0);
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
/**
* This {@link org.springframework.integration.core.MessageSource} lets Spring Integration consume
* given account's timeline as messages. It has support for dynamic throttling of API requests.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TimelineReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public TimelineReceivingMessageSource(Twitter twitter, String metadataKey) {
super(twitter, metadataKey);
}
@Override
public String getComponentType() {
return "twitter:inbound-channel-adapter";
}
@Override
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getHomeTimeline(this.getPageSize(), sinceId, 0);
}
}

View File

@@ -1,4 +1,4 @@
/**
* Provides inbound Twitter components.
*/
package org.springframework.integration.twitter.inbound;
/**
* Provides inbound Twitter components.
*/
package org.springframework.integration.twitter.inbound;

View File

@@ -1,64 +1,64 @@
/*
* Copyright 2018 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.twitter.outbound;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* Simple adapter to support sending outbound direct messages ("DM"s) using Twitter.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
*/
public class DirectMessageSendingMessageHandler extends AbstractMessageHandler {
private final Twitter twitter;
public DirectMessageSendingMessageHandler(Twitter twitter) {
Assert.notNull(twitter, "twitter must not be null");
this.twitter = twitter;
}
@Override
public String getComponentType() {
return "twitter:dm-outbound-channel-adapter";
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
Assert.isTrue(message.getPayload() instanceof String, "Only payload of type String is supported. " +
"Consider adding a transformer to the message flow in front of this adapter.");
Object toUser = message.getHeaders().get(TwitterHeaders.DM_TARGET_USER_ID);
Assert.isTrue(toUser instanceof String || toUser instanceof Number,
"the header '" + TwitterHeaders.DM_TARGET_USER_ID +
"' must contain either a String (a screenname) or an number (a user ID)");
String payload = (String) message.getPayload();
if (toUser instanceof Number) {
this.twitter.directMessageOperations().sendDirectMessage(((Number) toUser).longValue(), payload);
}
else if (toUser instanceof String) {
this.twitter.directMessageOperations().sendDirectMessage((String) toUser, payload);
}
}
}
/*
* Copyright 2018 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.twitter.outbound;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* Simple adapter to support sending outbound direct messages ("DM"s) using Twitter.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Mark Fisher
*/
public class DirectMessageSendingMessageHandler extends AbstractMessageHandler {
private final Twitter twitter;
public DirectMessageSendingMessageHandler(Twitter twitter) {
Assert.notNull(twitter, "twitter must not be null");
this.twitter = twitter;
}
@Override
public String getComponentType() {
return "twitter:dm-outbound-channel-adapter";
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
Assert.isTrue(message.getPayload() instanceof String, "Only payload of type String is supported. " +
"Consider adding a transformer to the message flow in front of this adapter.");
Object toUser = message.getHeaders().get(TwitterHeaders.DM_TARGET_USER_ID);
Assert.isTrue(toUser instanceof String || toUser instanceof Number,
"the header '" + TwitterHeaders.DM_TARGET_USER_ID +
"' must contain either a String (a screenname) or an number (a user ID)");
String payload = (String) message.getPayload();
if (toUser instanceof Number) {
this.twitter.directMessageOperations().sendDirectMessage(((Number) toUser).longValue(), payload);
}
else if (toUser instanceof String) {
this.twitter.directMessageOperations().sendDirectMessage((String) toUser, payload);
}
}
}

View File

@@ -1,120 +1,120 @@
/*
* Copyright 2018 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.twitter.outbound;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.TweetData;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* MessageHandler for sending regular status updates as well as 'replies' or 'mentions'.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
public class StatusUpdatingMessageHandler extends AbstractMessageHandler {
private final Twitter twitter;
private volatile Expression tweetDataExpression;
private EvaluationContext evaluationContext;
public StatusUpdatingMessageHandler(Twitter twitter) {
Assert.notNull(twitter, "twitter must not be null");
this.twitter = twitter;
}
@Override
public String getComponentType() {
return "twitter:outbound-channel-adapter";
}
/**
* An expression that is used to build the {@link TweetData}; must resolve to a
* {@link TweetData} object, or a {@link String}, or a {@link Tweet}.
* <p> When using a {@code TweetData} directly in the expression, it is not necessary
* to include the package:
* {@code "new TweetData("test").withMedia(headers.mediaResource).displayCoordinates(true)")}.
* @param tweetDataExpression The expression.
* @since 4.0
*/
public void setTweetDataExpression(Expression tweetDataExpression) {
this.tweetDataExpression = tweetDataExpression;
}
public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
@Override
protected void onInit() throws Exception {
super.onInit();
if (this.evaluationContext == null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
if (typeLocator instanceof StandardTypeLocator) {
/*
* Register the twitter api package so they don't need a FQCN for TweetData.
*/
((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api");
}
}
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
Object value;
if (this.tweetDataExpression != null) {
value = this.tweetDataExpression.getValue(this.evaluationContext, message);
}
else {
value = message.getPayload();
}
Assert.notNull(value, "The tweetData cannot evaluate to 'null'.");
TweetData tweetData = null;
if (value instanceof TweetData) {
tweetData = (TweetData) value;
}
else if (value instanceof Tweet) {
tweetData = new TweetData(((Tweet) value).getText());
}
else if (value instanceof String) {
tweetData = new TweetData((String) value);
}
else {
throw new MessageHandlingException(message, "Unsupported tweetData: " + value);
}
this.twitter.timelineOperations().updateStatus(tweetData);
}
}
/*
* Copyright 2018 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.twitter.outbound;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.TweetData;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* MessageHandler for sending regular status updates as well as 'replies' or 'mentions'.
*
* @author Josh Long
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
public class StatusUpdatingMessageHandler extends AbstractMessageHandler {
private final Twitter twitter;
private volatile Expression tweetDataExpression;
private EvaluationContext evaluationContext;
public StatusUpdatingMessageHandler(Twitter twitter) {
Assert.notNull(twitter, "twitter must not be null");
this.twitter = twitter;
}
@Override
public String getComponentType() {
return "twitter:outbound-channel-adapter";
}
/**
* An expression that is used to build the {@link TweetData}; must resolve to a
* {@link TweetData} object, or a {@link String}, or a {@link Tweet}.
* <p> When using a {@code TweetData} directly in the expression, it is not necessary
* to include the package:
* {@code "new TweetData("test").withMedia(headers.mediaResource).displayCoordinates(true)")}.
* @param tweetDataExpression The expression.
* @since 4.0
*/
public void setTweetDataExpression(Expression tweetDataExpression) {
this.tweetDataExpression = tweetDataExpression;
}
public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
@Override
protected void onInit() throws Exception {
super.onInit();
if (this.evaluationContext == null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
if (typeLocator instanceof StandardTypeLocator) {
/*
* Register the twitter api package so they don't need a FQCN for TweetData.
*/
((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api");
}
}
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
Object value;
if (this.tweetDataExpression != null) {
value = this.tweetDataExpression.getValue(this.evaluationContext, message);
}
else {
value = message.getPayload();
}
Assert.notNull(value, "The tweetData cannot evaluate to 'null'.");
TweetData tweetData = null;
if (value instanceof TweetData) {
tweetData = (TweetData) value;
}
else if (value instanceof Tweet) {
tweetData = new TweetData(((Tweet) value).getText());
}
else if (value instanceof String) {
tweetData = new TweetData((String) value);
}
else {
throw new MessageHandlingException(message, "Unsupported tweetData: " + value);
}
this.twitter.timelineOperations().updateStatus(tweetData);
}
}

View File

@@ -1,160 +1,160 @@
/*
* Copyright 2018 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.twitter.outbound;
import java.util.Collections;
import java.util.List;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* The {@link AbstractReplyProducingMessageHandler} implementation to perform request/reply
* Twitter search with {@link SearchParameters} as the result of {@link #searchArgsExpression}
* expression evaluation.
*
* @author Gary Russell
*/
public class TwitterSearchOutboundGateway extends AbstractReplyProducingMessageHandler {
private static final int DEFAULT_PAGE_SIZE = 20;
private final Twitter twitter;
private volatile Expression searchArgsExpression;
private volatile EvaluationContext evaluationContext;
public TwitterSearchOutboundGateway(Twitter twitter) {
Assert.notNull(twitter, "'twitter' must not be null");
this.twitter = twitter;
}
/**
* An expression that is used to build the search; must resolve to a
* {@code SearchParameters} object, or a
* {@link String}, in which case the default page size of 20 is applied,
* or a list of up to 4 arguments, such as
* {@code "{payload, headers.pageSize, headers.sinceId, headers.maxId}"}.
* The first (required) argument must resolve to a String (query), the
* optional arguments must resolve to an Number and represent the
* page size, sinceId, and maxId respectively. Refer to the 'Spring
* Social Twitter' documentation for more details.
* <p> When using a {@code SearchParameters} directly, it is not necessary
* to include the package: {@code "new SearchParameters("#foo").count(20)")}.
* <p> Default: {@code "payload"}.
* @param searchArgsExpression The expression.
*/
public void setSearchArgsExpression(Expression searchArgsExpression) {
Assert.notNull(searchArgsExpression, "'searchArgsExpression' must not be null");
this.searchArgsExpression = searchArgsExpression;
}
public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
@Override
public String getComponentType() {
return "twitter:search-outbound-gateway";
}
protected Twitter getTwitter() {
return this.twitter;
}
@Override
protected void doInit() {
super.doInit();
if (this.evaluationContext == null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
if (typeLocator instanceof StandardTypeLocator) {
/*
* Register the twitter api package so they don't need a FQCN for SearchParameters.
*/
((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api");
}
}
}
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Object args;
if (this.searchArgsExpression != null) {
args = this.searchArgsExpression.getValue(this.evaluationContext, requestMessage);
}
else {
args = requestMessage.getPayload();
}
Assert.notNull(args, "The twitter search expression cannot evaluate to 'null'.");
SearchParameters searchParameters;
if (args instanceof SearchParameters) {
searchParameters = (SearchParameters) args;
}
else if (args instanceof String) {
searchParameters = new SearchParameters((String) args).count(DEFAULT_PAGE_SIZE);
}
else if (args instanceof List) {
List<?> list = (List<?>) args;
Assert.isTrue(list.size() > 0 && list.size() < 5, "Between 1 and 4 search arguments are required");
Assert.isInstanceOf(String.class, list.get(0), "The first search argument (query) must be a String");
searchParameters = new SearchParameters((String) list.get(0));
if (list.size() > 1) {
Assert.isInstanceOf(Number.class, list.get(1),
"The second search argument (pageSize) must be a Number");
searchParameters.count(((Number) list.get(1)).intValue());
if (list.size() > 2) {
Assert.isInstanceOf(Number.class, list.get(2),
"The third search argument (sinceId) must be a Number");
searchParameters.sinceId(((Number) list.get(2)).longValue());
}
if (list.size() > 3) {
Assert.isInstanceOf(Number.class, list.get(3),
"The fourth search argument (maxId) must be a Number");
searchParameters.maxId(((Number) list.get(3)).longValue());
}
}
}
else {
throw new IllegalArgumentException(
"Search Expression must evaluate to a 'SearchParameters', 'String' or 'List'.");
}
SearchResults results = this.getTwitter().searchOperations().search(searchParameters);
if (results != null) {
List<Tweet> tweets = (results.getTweets() != null ? results.getTweets() : Collections.<Tweet>emptyList());
return this.getMessageBuilderFactory().withPayload(tweets)
.setHeader(TwitterHeaders.SEARCH_METADATA, results.getSearchMetadata());
}
else {
return null;
}
}
}
/*
* Copyright 2018 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.twitter.outbound;
import java.util.Collections;
import java.util.List;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.util.Assert;
/**
* The {@link AbstractReplyProducingMessageHandler} implementation to perform request/reply
* Twitter search with {@link SearchParameters} as the result of {@link #searchArgsExpression}
* expression evaluation.
*
* @author Gary Russell
*/
public class TwitterSearchOutboundGateway extends AbstractReplyProducingMessageHandler {
private static final int DEFAULT_PAGE_SIZE = 20;
private final Twitter twitter;
private volatile Expression searchArgsExpression;
private volatile EvaluationContext evaluationContext;
public TwitterSearchOutboundGateway(Twitter twitter) {
Assert.notNull(twitter, "'twitter' must not be null");
this.twitter = twitter;
}
/**
* An expression that is used to build the search; must resolve to a
* {@code SearchParameters} object, or a
* {@link String}, in which case the default page size of 20 is applied,
* or a list of up to 4 arguments, such as
* {@code "{payload, headers.pageSize, headers.sinceId, headers.maxId}"}.
* The first (required) argument must resolve to a String (query), the
* optional arguments must resolve to an Number and represent the
* page size, sinceId, and maxId respectively. Refer to the 'Spring
* Social Twitter' documentation for more details.
* <p> When using a {@code SearchParameters} directly, it is not necessary
* to include the package: {@code "new SearchParameters("#foo").count(20)")}.
* <p> Default: {@code "payload"}.
* @param searchArgsExpression The expression.
*/
public void setSearchArgsExpression(Expression searchArgsExpression) {
Assert.notNull(searchArgsExpression, "'searchArgsExpression' must not be null");
this.searchArgsExpression = searchArgsExpression;
}
public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
}
@Override
public String getComponentType() {
return "twitter:search-outbound-gateway";
}
protected Twitter getTwitter() {
return this.twitter;
}
@Override
protected void doInit() {
super.doInit();
if (this.evaluationContext == null) {
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
if (typeLocator instanceof StandardTypeLocator) {
/*
* Register the twitter api package so they don't need a FQCN for SearchParameters.
*/
((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api");
}
}
}
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
Object args;
if (this.searchArgsExpression != null) {
args = this.searchArgsExpression.getValue(this.evaluationContext, requestMessage);
}
else {
args = requestMessage.getPayload();
}
Assert.notNull(args, "The twitter search expression cannot evaluate to 'null'.");
SearchParameters searchParameters;
if (args instanceof SearchParameters) {
searchParameters = (SearchParameters) args;
}
else if (args instanceof String) {
searchParameters = new SearchParameters((String) args).count(DEFAULT_PAGE_SIZE);
}
else if (args instanceof List) {
List<?> list = (List<?>) args;
Assert.isTrue(list.size() > 0 && list.size() < 5, "Between 1 and 4 search arguments are required");
Assert.isInstanceOf(String.class, list.get(0), "The first search argument (query) must be a String");
searchParameters = new SearchParameters((String) list.get(0));
if (list.size() > 1) {
Assert.isInstanceOf(Number.class, list.get(1),
"The second search argument (pageSize) must be a Number");
searchParameters.count(((Number) list.get(1)).intValue());
if (list.size() > 2) {
Assert.isInstanceOf(Number.class, list.get(2),
"The third search argument (sinceId) must be a Number");
searchParameters.sinceId(((Number) list.get(2)).longValue());
}
if (list.size() > 3) {
Assert.isInstanceOf(Number.class, list.get(3),
"The fourth search argument (maxId) must be a Number");
searchParameters.maxId(((Number) list.get(3)).longValue());
}
}
}
else {
throw new IllegalArgumentException(
"Search Expression must evaluate to a 'SearchParameters', 'String' or 'List'.");
}
SearchResults results = this.getTwitter().searchOperations().search(searchParameters);
if (results != null) {
List<Tweet> tweets = (results.getTweets() != null ? results.getTweets() : Collections.<Tweet>emptyList());
return this.getMessageBuilderFactory().withPayload(tweets)
.setHeader(TwitterHeaders.SEARCH_METADATA, results.getSearchMetadata());
}
else {
return null;
}
}
}

View File

@@ -1,4 +1,4 @@
/**
* Provides outbound Twitter components.
*/
package org.springframework.integration.twitter.outbound;
/**
* Provides outbound Twitter components.
*/
package org.springframework.integration.twitter.outbound;

View File

@@ -1,2 +1,2 @@
http\://www.springframework.org/schema/integration/twitter=org.springframework.integration.twitter.config.TwitterNamespaceHandler
http\://www.springframework.org/schema/integration/twitter=org.springframework.integration.twitter.config.TwitterNamespaceHandler

View File

@@ -1,2 +1,2 @@
http\://www.springframework.org/schema/integration/twitter/spring-integration-social-twitter-1.0.xsd=org/springframework/integration/twitter/config/spring-integration-social-twitter-1.0.xsd
http\://www.springframework.org/schema/integration/twitter/spring-integration-social-twitter.xsd=org/springframework/integration/twitter/config/spring-integration-social-twitter-1.0.xsd
http\://www.springframework.org/schema/integration/twitter/spring-integration-social-twitter-1.0.xsd=org/springframework/integration/twitter/config/spring-integration-social-twitter-1.0.xsd
http\://www.springframework.org/schema/integration/twitter/spring-integration-social-twitter.xsd=org/springframework/integration/twitter/config/spring-integration-social-twitter-1.0.xsd

View File

@@ -1,4 +1,4 @@
# Tooling related information for the integration twitter namespace
http\://www.springframework.org/schema/integration/twitter@name=integration twitter Namespace
http\://www.springframework.org/schema/integration/twitter@prefix=int-twitter
http\://www.springframework.org/schema/integration/twitter@icon=org/springframework/integration/twitter/config/spring-integration-twitter.gif
# Tooling related information for the integration twitter namespace
http\://www.springframework.org/schema/integration/twitter@name=integration twitter Namespace
http\://www.springframework.org/schema/integration/twitter@prefix=int-twitter
http\://www.springframework.org/schema/integration/twitter@icon=org/springframework/integration/twitter/config/spring-integration-twitter.gif

View File

@@ -1,322 +1,322 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/twitter"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/twitter"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-5.1.xsd"/>
<!--
INBOUND
-->
<xsd:element name="inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource' that consumes your
friends' timeline updates from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType >
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="mentions-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource' that consumes mentions
of your handle from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="search-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.SearchReceivingMessageSource' that consumes search
results for a given query from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type">
<xsd:attribute name="query" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Twitter search query (e.g, #springintegration).
For more info on Twitter queries please refer to this site: http://search.twitter.com/operators)
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="dm-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource' that consumes
direct messages from Twitter and sends Messages whose payloads are DirectMessage objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!--
OUTBOUND
-->
<xsd:element name="dm-outbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler'
that sends Direct Messages to a Twitter user as
specified in the header whose name is defined by the TwitterHeaders.DM_TARGET_USER_ID constant.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.StatusUpdatingMessageHandler'
that posts a status update to the authorized user's timeline.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attribute name="tweet-data-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression that evaluates to tweetData; the evaluation result type can be
an 'org.springframework.social.twitter.api.TweetData', a 'String' or
'org.springframework.social.twitter.api.Tweet'.
Default: "payload".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="search-outbound-gateway">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway'
that issues Twitter searches and produces their results.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The bean id of this gateway; the MessageHandler is also registered with this id
plus a suffix '.handler'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="search-args-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression that evaluates to search arguments; the evaluation result type can be
an 'org.springframework.social.twitter.api.SearchParameters', a 'String', in
which case the default page size of 20 is used, or the expression can evaluate to
a list of search
arguments, for example: "{payload, headers.pageSize, headers.sinceId, headers.maxId}".
Default: "payload".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="request-channel" use="required" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the request channel attached to this gateway.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the reply channel attached to this
gateway.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Allows you to specify how long this gateway will wait for
the reply message to be sent successfully to the reply channel
before throwing an exception. This attribute only applies when the
channel might block, for example when using a bounded queue channel that
is currently full.
Also, keep in mind that when sending to a DirectChannel, the
invocation will occur in the sender's thread. Therefore,
the failing of the send operation may be caused by other
components further downstream.
The "reply-timeout" attribute maps to the "sendTimeout" property of the
underlying 'MessagingTemplate' instance (org.springframework.integration.core.MessagingTemplate).
The attribute will default, if not specified, to '-1', meaning that
by default, the Gateway will wait indefinitely. The value is
specified in milliseconds.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!--
BASE TYPES
-->
<xsd:complexType name="inbound-twitter-type">
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The bean id of this Polling Endpoint; the MessageSource is also registered with this id
plus a suffix '.source'; also used as the
MetaDataStore key with suffix '.' + the profileId from the authorized Twitter user.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the channel the attached to this adapter, to which messages will be sent.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
<xsd:attribute name="twitter-template" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.social.twitter.api.Twitter"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Reference to a TwitterTemplate bean provided by the Spring Social project.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="metadata-store" use="optional" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a MetadataStore instance for storing metadata associated with
the retrieved feeds. If the implementation is persistent, it can help to
prevent duplicates between restarts. If shared, it can help coordinate multiple
instances of an adapter across different processes.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.metadata.MetadataStore" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="page-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Limits the number of tweets retrieved on each poll; default: 20.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="outbound-twitter-type">
<xsd:choice minOccurs="0" maxOccurs="2">
<xsd:element name="transactional" type="integration:transactionalType" minOccurs="0" maxOccurs="1" />
<xsd:element name="request-handler-advice-chain" type="integration:handlerAdviceChainType"
minOccurs="0" maxOccurs="1" />
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="twitter-template" use="required" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.social.twitter.api.Twitter"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Reference to a TwitterTemplate bean provided by the Spring Social project.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation>
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/twitter"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:integration="http://www.springframework.org/schema/integration"
targetNamespace="http://www.springframework.org/schema/integration/twitter"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-5.1.xsd"/>
<!--
INBOUND
-->
<xsd:element name="inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource' that consumes your
friends' timeline updates from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType >
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="mentions-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource' that consumes mentions
of your handle from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="search-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.SearchReceivingMessageSource' that consumes search
results for a given query from Twitter and sends Messages whose payloads are Tweet objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type">
<xsd:attribute name="query" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Twitter search query (e.g, #springintegration).
For more info on Twitter queries please refer to this site: http://search.twitter.com/operators)
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="dm-inbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Defines a Polling Channel Adapter for the
'org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource' that consumes
direct messages from Twitter and sends Messages whose payloads are DirectMessage objects.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="inbound-twitter-type"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!--
OUTBOUND
-->
<xsd:element name="dm-outbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler'
that sends Direct Messages to a Twitter user as
specified in the header whose name is defined by the TwitterHeaders.DM_TARGET_USER_ID constant.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="outbound-channel-adapter">
<xsd:annotation>
<xsd:documentation>
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.StatusUpdatingMessageHandler'
that posts a status update to the authorized user's timeline.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attribute name="tweet-data-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression that evaluates to tweetData; the evaluation result type can be
an 'org.springframework.social.twitter.api.TweetData', a 'String' or
'org.springframework.social.twitter.api.Tweet'.
Default: "payload".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="search-outbound-gateway">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures a Consumer Endpoint for the
'org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway'
that issues Twitter searches and produces their results.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="outbound-twitter-type">
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The bean id of this gateway; the MessageHandler is also registered with this id
plus a suffix '.handler'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="search-args-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A SpEL expression that evaluates to search arguments; the evaluation result type can be
an 'org.springframework.social.twitter.api.SearchParameters', a 'String', in
which case the default page size of 20 is used, or the expression can evaluate to
a list of search
arguments, for example: "{payload, headers.pageSize, headers.sinceId, headers.maxId}".
Default: "payload".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="request-channel" use="required" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the request channel attached to this gateway.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the reply channel attached to this
gateway.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reply-timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Allows you to specify how long this gateway will wait for
the reply message to be sent successfully to the reply channel
before throwing an exception. This attribute only applies when the
channel might block, for example when using a bounded queue channel that
is currently full.
Also, keep in mind that when sending to a DirectChannel, the
invocation will occur in the sender's thread. Therefore,
the failing of the send operation may be caused by other
components further downstream.
The "reply-timeout" attribute maps to the "sendTimeout" property of the
underlying 'MessagingTemplate' instance (org.springframework.integration.core.MessagingTemplate).
The attribute will default, if not specified, to '-1', meaning that
by default, the Gateway will wait indefinitely. The value is
specified in milliseconds.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!--
BASE TYPES
-->
<xsd:complexType name="inbound-twitter-type">
<xsd:sequence>
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
The bean id of this Polling Endpoint; the MessageSource is also registered with this id
plus a suffix '.source'; also used as the
MetaDataStore key with suffix '.' + the profileId from the authorized Twitter user.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.messaging.MessageChannel" />
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Identifies the channel the attached to this adapter, to which messages will be sent.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
<xsd:attribute name="twitter-template" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.social.twitter.api.Twitter"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Reference to a TwitterTemplate bean provided by the Spring Social project.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="metadata-store" use="optional" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a MetadataStore instance for storing metadata associated with
the retrieved feeds. If the implementation is persistent, it can help to
prevent duplicates between restarts. If shared, it can help coordinate multiple
instances of an adapter across different processes.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.metadata.MetadataStore" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="page-size" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Limits the number of tweets retrieved on each poll; default: 20.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="outbound-twitter-type">
<xsd:choice minOccurs="0" maxOccurs="2">
<xsd:element name="transactional" type="integration:transactionalType" minOccurs="0" maxOccurs="1" />
<xsd:element name="request-handler-advice-chain" type="integration:handlerAdviceChainType"
minOccurs="0" maxOccurs="1" />
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
<xsd:attribute name="twitter-template" use="required" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.social.twitter.api.Twitter"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
Reference to a TwitterTemplate bean provided by the Spring Social project.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order">
<xsd:annotation>
<xsd:documentation>
Specifies the order for invocation when this endpoint is connected as a
subscriber to a SubscribableChannel.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>

View File

@@ -1,83 +1,83 @@
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource;
import org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource;
import org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Gary Russell
* @author Rijnard van Tonder
*/
public class TestReceivingMessageSourceParserTests {
@Test
public void testReceivingAdapterConfigurationAutoStartup() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestReceivingMessageSourceParser-context.xml", getClass());
SourcePollingChannelAdapter spca = ac.getBean("mentionAdapter", SourcePollingChannelAdapter.class);
MentionsReceivingMessageSource ms = TestUtils.getPropertyValue(spca, "source",
MentionsReceivingMessageSource.class);
assertEquals(Integer.valueOf(23), TestUtils.getPropertyValue(ms, "pageSize", Integer.class));
assertNotNull(ms);
spca = ac.getBean("dmAdapter", SourcePollingChannelAdapter.class);
DirectMessageReceivingMessageSource dms = TestUtils.getPropertyValue(spca, "source",
DirectMessageReceivingMessageSource.class);
assertNotNull(dms);
assertEquals(Integer.valueOf(45), TestUtils.getPropertyValue(dms, "pageSize", Integer.class));
spca = ac.getBean("updateAdapter", SourcePollingChannelAdapter.class);
TimelineReceivingMessageSource tms = TestUtils.getPropertyValue(spca, "source",
TimelineReceivingMessageSource.class);
assertEquals(Integer.valueOf(67), TestUtils.getPropertyValue(tms, "pageSize", Integer.class));
assertNotNull(tms);
ac.close();
}
@Test
public void testThatMessageSourcesAreRegisteredAsBeans() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestReceivingMessageSourceParser-context.xml", this.getClass());
MentionsReceivingMessageSource ms = ac.getBean("mentionAdapter.source", MentionsReceivingMessageSource.class);
assertNotNull(ms);
DirectMessageReceivingMessageSource dms = ac.getBean("dmAdapter.source",
DirectMessageReceivingMessageSource.class);
assertNotNull(dms);
TimelineReceivingMessageSource tms = ac.getBean("updateAdapter.source", TimelineReceivingMessageSource.class);
assertNotNull(tms);
ac.close();
}
}
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.inbound.DirectMessageReceivingMessageSource;
import org.springframework.integration.twitter.inbound.MentionsReceivingMessageSource;
import org.springframework.integration.twitter.inbound.TimelineReceivingMessageSource;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Gary Russell
* @author Rijnard van Tonder
*/
public class TestReceivingMessageSourceParserTests {
@Test
public void testReceivingAdapterConfigurationAutoStartup() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestReceivingMessageSourceParser-context.xml", getClass());
SourcePollingChannelAdapter spca = ac.getBean("mentionAdapter", SourcePollingChannelAdapter.class);
MentionsReceivingMessageSource ms = TestUtils.getPropertyValue(spca, "source",
MentionsReceivingMessageSource.class);
assertEquals(Integer.valueOf(23), TestUtils.getPropertyValue(ms, "pageSize", Integer.class));
assertNotNull(ms);
spca = ac.getBean("dmAdapter", SourcePollingChannelAdapter.class);
DirectMessageReceivingMessageSource dms = TestUtils.getPropertyValue(spca, "source",
DirectMessageReceivingMessageSource.class);
assertNotNull(dms);
assertEquals(Integer.valueOf(45), TestUtils.getPropertyValue(dms, "pageSize", Integer.class));
spca = ac.getBean("updateAdapter", SourcePollingChannelAdapter.class);
TimelineReceivingMessageSource tms = TestUtils.getPropertyValue(spca, "source",
TimelineReceivingMessageSource.class);
assertEquals(Integer.valueOf(67), TestUtils.getPropertyValue(tms, "pageSize", Integer.class));
assertNotNull(tms);
ac.close();
}
@Test
public void testThatMessageSourcesAreRegisteredAsBeans() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestReceivingMessageSourceParser-context.xml", this.getClass());
MentionsReceivingMessageSource ms = ac.getBean("mentionAdapter.source", MentionsReceivingMessageSource.class);
assertNotNull(ms);
DirectMessageReceivingMessageSource dms = ac.getBean("dmAdapter.source",
DirectMessageReceivingMessageSource.class);
assertNotNull(dms);
TimelineReceivingMessageSource tms = ac.getBean("updateAdapter.source", TimelineReceivingMessageSource.class);
assertNotNull(tms);
ac.close();
}
}

View File

@@ -1,49 +1,49 @@
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.inbound.SearchReceivingMessageSource;
import org.springframework.social.twitter.api.Twitter;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TestSearchReceivingMessageSourceParserTests {
@Test
public void testSearchReceivingDefaultTemplate() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestSearchReceivingMessageSourceParser-context.xml", this.getClass());
SourcePollingChannelAdapter spca = ac.getBean("searchAdapterWithTemplate", SourcePollingChannelAdapter.class);
SearchReceivingMessageSource ms = (SearchReceivingMessageSource) TestUtils.getPropertyValue(spca, "source");
assertEquals(Integer.valueOf(23), TestUtils.getPropertyValue(ms, "pageSize", Integer.class));
Twitter template = (Twitter) TestUtils.getPropertyValue(ms, "twitter");
assertNotNull(template);
ac.close();
}
}
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.inbound.SearchReceivingMessageSource;
import org.springframework.social.twitter.api.Twitter;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TestSearchReceivingMessageSourceParserTests {
@Test
public void testSearchReceivingDefaultTemplate() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestSearchReceivingMessageSourceParser-context.xml", this.getClass());
SourcePollingChannelAdapter spca = ac.getBean("searchAdapterWithTemplate", SourcePollingChannelAdapter.class);
SearchReceivingMessageSource ms = (SearchReceivingMessageSource) TestUtils.getPropertyValue(spca, "source");
assertEquals(Integer.valueOf(23), TestUtils.getPropertyValue(ms, "pageSize", Integer.class));
Twitter template = (Twitter) TestUtils.getPropertyValue(ms, "twitter");
assertNotNull(template);
ac.close();
}
}

View File

@@ -1,91 +1,91 @@
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
* @author Gary Russell
*/
public class TestSendingMessageHandlerParserTests {
private static volatile int adviceCalled;
@Test
public void testSendingMessageHandlerSuccessfulBootstrap() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestSendingMessageHandlerParser-context.xml", this.getClass());
EventDrivenConsumer dmAdapter = ac.getBean("dmAdapter", EventDrivenConsumer.class);
MessageHandler handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
assertEquals(DirectMessageSendingMessageHandler.class, handler.getClass());
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
dmAdapter = ac.getBean("dmAdvised", EventDrivenConsumer.class);
handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
handler.handleMessage(new GenericMessage<String>("foo"));
assertEquals(1, adviceCalled);
MessageHandler handler2 = TestUtils.getPropertyValue(ac.getBean("advised"), "handler", MessageHandler.class);
assertNotSame(handler, handler2);
handler2.handleMessage(new GenericMessage<String>("foo"));
assertEquals(2, adviceCalled);
ac.close();
}
@Test
public void testInt2718FailForOutboundAdapterWithRequestHandlerAdviceChainWithinChainConfig() {
try {
new ClassPathXmlApplicationContext("OutboundAdapterWithRHACWithinChain-fail-context.xml", this.getClass())
.close();
fail("Expected BeanDefinitionParsingException");
}
catch (BeansException e) {
assertTrue(e instanceof BeanDefinitionParsingException);
assertTrue(e.getMessage().contains("'request-handler-advice-chain' isn't allowed " +
"for 'twitter:outbound-channel-adapter' within a <chain/>, because its Handler isn't an AbstractReplyProducingMessageHandler"));
}
}
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
adviceCalled++;
return null;
}
}
}
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
* @author Gary Russell
*/
public class TestSendingMessageHandlerParserTests {
private static volatile int adviceCalled;
@Test
public void testSendingMessageHandlerSuccessfulBootstrap() {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext(
"TestSendingMessageHandlerParser-context.xml", this.getClass());
EventDrivenConsumer dmAdapter = ac.getBean("dmAdapter", EventDrivenConsumer.class);
MessageHandler handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
assertEquals(DirectMessageSendingMessageHandler.class, handler.getClass());
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
dmAdapter = ac.getBean("dmAdvised", EventDrivenConsumer.class);
handler = TestUtils.getPropertyValue(dmAdapter, "handler", MessageHandler.class);
handler.handleMessage(new GenericMessage<String>("foo"));
assertEquals(1, adviceCalled);
MessageHandler handler2 = TestUtils.getPropertyValue(ac.getBean("advised"), "handler", MessageHandler.class);
assertNotSame(handler, handler2);
handler2.handleMessage(new GenericMessage<String>("foo"));
assertEquals(2, adviceCalled);
ac.close();
}
@Test
public void testInt2718FailForOutboundAdapterWithRequestHandlerAdviceChainWithinChainConfig() {
try {
new ClassPathXmlApplicationContext("OutboundAdapterWithRHACWithinChain-fail-context.xml", this.getClass())
.close();
fail("Expected BeanDefinitionParsingException");
}
catch (BeansException e) {
assertTrue(e instanceof BeanDefinitionParsingException);
assertTrue(e.getMessage().contains("'request-handler-advice-chain' isn't allowed " +
"for 'twitter:outbound-channel-adapter' within a <chain/>, because its Handler isn't an AbstractReplyProducingMessageHandler"));
}
}
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
adviceCalled++;
return null;
}
}
}

View File

@@ -1,81 +1,81 @@
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class TwitterSearchOutboundGatewayParserTests {
@Autowired
@Qualifier("defaultTSOG.handler")
private TwitterSearchOutboundGateway defaultTSOG;
@Autowired
@Qualifier("allAttsTSOG.handler")
private TwitterSearchOutboundGateway allAttsTSOG;
@Autowired
private PollingConsumer polledAndAdvisedTSOG;
@Autowired
private Twitter twitter;
@Test
public void testDefault() {
assertSame(twitter, TestUtils.getPropertyValue(defaultTSOG, "twitter"));
}
@Test
public void testAllAtts() {
assertSame(twitter, TestUtils.getPropertyValue(allAttsTSOG, "twitter"));
assertEquals("'foo'", TestUtils.getPropertyValue(allAttsTSOG, "searchArgsExpression.expression"));
}
@Test
public void testAdvised() {
assertSame(twitter, TestUtils.getPropertyValue(polledAndAdvisedTSOG, "handler.twitter"));
assertThat(TestUtils.getPropertyValue(polledAndAdvisedTSOG, "handler.adviceChain", List.class).get(0),
Matchers.instanceOf(RequestHandlerRetryAdvice.class));
}
}
/*
* Copyright 2018 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.twitter.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.handler.advice.RequestHandlerRetryAdvice;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGateway;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class TwitterSearchOutboundGatewayParserTests {
@Autowired
@Qualifier("defaultTSOG.handler")
private TwitterSearchOutboundGateway defaultTSOG;
@Autowired
@Qualifier("allAttsTSOG.handler")
private TwitterSearchOutboundGateway allAttsTSOG;
@Autowired
private PollingConsumer polledAndAdvisedTSOG;
@Autowired
private Twitter twitter;
@Test
public void testDefault() {
assertSame(twitter, TestUtils.getPropertyValue(defaultTSOG, "twitter"));
}
@Test
public void testAllAtts() {
assertSame(twitter, TestUtils.getPropertyValue(allAttsTSOG, "twitter"));
assertEquals("'foo'", TestUtils.getPropertyValue(allAttsTSOG, "searchArgsExpression.expression"));
}
@Test
public void testAdvised() {
assertSame(twitter, TestUtils.getPropertyValue(polledAndAdvisedTSOG, "handler.twitter"));
assertThat(TestUtils.getPropertyValue(polledAndAdvisedTSOG, "handler.adviceChain", List.class).get(0),
Matchers.instanceOf(RequestHandlerRetryAdvice.class));
}
}

View File

@@ -1,47 +1,47 @@
/*
* Copyright 2018 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.twitter.ignored;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*
*/
public class TestReceivingUsingNamespace {
@Test
@Ignore
/*
* In order to run this test you need to provide oauth properties in sample.properties on the classpath.
*/
public void testUpdatesWithRealTwitter() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ConfigurableApplicationContext ctx =
new ClassPathXmlApplicationContext("TestReceivingUsingNamespace-context.xml", this.getClass());
latch.await(10000, TimeUnit.SECONDS);
ctx.close();
}
}
/*
* Copyright 2018 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.twitter.ignored;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*
*/
public class TestReceivingUsingNamespace {
@Test
@Ignore
/*
* In order to run this test you need to provide oauth properties in sample.properties on the classpath.
*/
public void testUpdatesWithRealTwitter() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ConfigurableApplicationContext ctx =
new ClassPathXmlApplicationContext("TestReceivingUsingNamespace-context.xml", this.getClass());
latch.await(10000, TimeUnit.SECONDS);
ctx.close();
}
}

View File

@@ -1,50 +1,50 @@
/*
* Copyright 2018 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.twitter.ignored;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.SearchParameters;
/**
* @author Gary Russell
*/
public class TestSearchOutboundGateway {
@Test
@Ignore
/*
* In order to run this test you need to provide oauth properties in sample.properties on the classpath.
*/
public void testSearch() throws Exception {
ConfigurableApplicationContext ctx =
new ClassPathXmlApplicationContext("TestSearchOutboundGateway-context.xml", this.getClass());
MessageChannel search = ctx.getBean("search", MessageChannel.class);
search.send(new GenericMessage<String>("#springintegration"));
Thread.sleep(10000);
search.send(new GenericMessage<SearchParameters>(new SearchParameters("#springintegration").count(5)));
Thread.sleep(10000);
search.send(new GenericMessage<SearchParameters>(new SearchParameters("#jjjjunk").count(5)));
Thread.sleep(10000);
ctx.close();
}
}
/*
* Copyright 2018 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.twitter.ignored;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.SearchParameters;
/**
* @author Gary Russell
*/
public class TestSearchOutboundGateway {
@Test
@Ignore
/*
* In order to run this test you need to provide oauth properties in sample.properties on the classpath.
*/
public void testSearch() throws Exception {
ConfigurableApplicationContext ctx =
new ClassPathXmlApplicationContext("TestSearchOutboundGateway-context.xml", this.getClass());
MessageChannel search = ctx.getBean("search", MessageChannel.class);
search.send(new GenericMessage<String>("#springintegration"));
Thread.sleep(10000);
search.send(new GenericMessage<SearchParameters>(new SearchParameters("#springintegration").count(5)));
Thread.sleep(10000);
search.send(new GenericMessage<SearchParameters>(new SearchParameters("#jjjjunk").count(5)));
Thread.sleep(10000);
ctx.close();
}
}

View File

@@ -1,73 +1,73 @@
/*
* Copyright 2018 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.twitter.ignored;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.MessageChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.util.StringUtils;
/**
* @author Josh Long
* @author Oleg Zhurakouksy
* @author Artem Bilan
*/
@ContextConfiguration
public class TestSendingDMsUsingNamespace extends AbstractJUnit4SpringContextTests {
@Autowired
@Qualifier("inputChannel")
private MessageChannel inputChannel;
@Autowired
@Qualifier("dmOutboundWithinChain")
private MessageChannel dmOutboundWithinChain;
@Test
@Ignore
public void testSendigRealDirectMessage() throws Throwable {
String dmUsr = "z_oleg";
MessageBuilder<String> mb = MessageBuilder.withPayload("'Hello world!', from the Spring Integration outbound Twitter adapter "
+ System.currentTimeMillis());
if (StringUtils.hasText(dmUsr)) {
mb.setHeader(TwitterHeaders.DM_TARGET_USER_ID, dmUsr);
}
inputChannel.send(mb.build());
}
@Test
@Ignore
public void testSendigDirectMessageFromChain() throws Throwable {
String dmUsr = "z_oleg";
MessageBuilder<String> mb = MessageBuilder.withPayload("Hello world!");
if (StringUtils.hasText(dmUsr)) {
mb.setHeader(TwitterHeaders.DM_TARGET_USER_ID, dmUsr);
}
dmOutboundWithinChain.send(mb.build());
}
}
/*
* Copyright 2018 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.twitter.ignored;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.MessageChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.util.StringUtils;
/**
* @author Josh Long
* @author Oleg Zhurakouksy
* @author Artem Bilan
*/
@ContextConfiguration
public class TestSendingDMsUsingNamespace extends AbstractJUnit4SpringContextTests {
@Autowired
@Qualifier("inputChannel")
private MessageChannel inputChannel;
@Autowired
@Qualifier("dmOutboundWithinChain")
private MessageChannel dmOutboundWithinChain;
@Test
@Ignore
public void testSendigRealDirectMessage() throws Throwable {
String dmUsr = "z_oleg";
MessageBuilder<String> mb = MessageBuilder.withPayload("'Hello world!', from the Spring Integration outbound Twitter adapter "
+ System.currentTimeMillis());
if (StringUtils.hasText(dmUsr)) {
mb.setHeader(TwitterHeaders.DM_TARGET_USER_ID, dmUsr);
}
inputChannel.send(mb.build());
}
@Test
@Ignore
public void testSendigDirectMessageFromChain() throws Throwable {
String dmUsr = "z_oleg";
MessageBuilder<String> mb = MessageBuilder.withPayload("Hello world!");
if (StringUtils.hasText(dmUsr)) {
mb.setHeader(TwitterHeaders.DM_TARGET_USER_ID, dmUsr);
}
dmOutboundWithinChain.send(mb.build());
}
}

View File

@@ -1,66 +1,66 @@
/*
* Copyright 2018 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.twitter.ignored;
import java.util.Date;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
/**
* @author Josh Long
* @author Artem Bilan
*/
@ContextConfiguration
public class TestSendingUpdatesUsingNamespace extends AbstractJUnit4SpringContextTests {
private MessagingTemplate messagingTemplate = new MessagingTemplate();
@Value("#{out}")
private MessageChannel channel;
@Autowired
@Qualifier("outFromChain")
private MessageChannel outFromChain;
@Test
@Ignore
public void testSendingATweet() throws Throwable {
MessageBuilder<String> mb = MessageBuilder.withPayload("Early start today"
+ new Date(System.currentTimeMillis()));
Message<String> m = mb.build();
this.messagingTemplate.send(this.channel, m);
}
@Test
@Ignore
public void testSendingATweetFromChain() throws Throwable {
Message<String> m = MessageBuilder.withPayload("Early start today" + new Date(System.currentTimeMillis())).build();
this.outFromChain.send(m);
}
}
/*
* Copyright 2018 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.twitter.ignored;
import java.util.Date;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
/**
* @author Josh Long
* @author Artem Bilan
*/
@ContextConfiguration
public class TestSendingUpdatesUsingNamespace extends AbstractJUnit4SpringContextTests {
private MessagingTemplate messagingTemplate = new MessagingTemplate();
@Value("#{out}")
private MessageChannel channel;
@Autowired
@Qualifier("outFromChain")
private MessageChannel outFromChain;
@Test
@Ignore
public void testSendingATweet() throws Throwable {
MessageBuilder<String> mb = MessageBuilder.withPayload("Early start today"
+ new Date(System.currentTimeMillis()));
Message<String> m = mb.build();
this.messagingTemplate.send(this.channel, m);
}
@Test
@Ignore
public void testSendingATweetFromChain() throws Throwable {
Message<String> m = MessageBuilder.withPayload("Early start today" + new Date(System.currentTimeMillis())).build();
this.outFromChain.send(m);
}
}

View File

@@ -1,72 +1,72 @@
/*
* Copyright 2018 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.twitter.ignored;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.history.MessageHistory;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.stereotype.Component;
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*
*/
@Component
public class TwitterAnnouncer {
private final Log logger = LogFactory.getLog(getClass());
public void dm(DirectMessage directMessage) {
logger.info("A direct message has been received from " +
directMessage.getSender().getScreenName() + " with text " + directMessage.getText());
}
public void search(Message<?> search) {
MessageHistory history = MessageHistory.read(search);
Tweet tweet = (Tweet) search.getPayload();
logger.info("A search item was received " +
tweet.getCreatedAt() + " with text " + tweet.getText());
}
public void mention(Tweet s) {
logger.info("A tweet mentioning (or replying) to you was received having text "
+ s.getFromUser() + "-" + s.getText() + " from " + s.getSource());
}
public void searchResult(Collection<Tweet> tweets) {
if (tweets.size() == 0) {
logger.info("No results");
}
for (Tweet s : tweets) {
logger.info("Search result: "
+ s.getFromUser() + "-" + s.getText() + " from " + s.getSource());
}
}
public void updates(Tweet t) {
logger.info("Received timeline update: " + t.getText() + " from " + t.getSource());
}
}
/*
* Copyright 2018 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.twitter.ignored;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.history.MessageHistory;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.stereotype.Component;
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*
*/
@Component
public class TwitterAnnouncer {
private final Log logger = LogFactory.getLog(getClass());
public void dm(DirectMessage directMessage) {
logger.info("A direct message has been received from " +
directMessage.getSender().getScreenName() + " with text " + directMessage.getText());
}
public void search(Message<?> search) {
MessageHistory history = MessageHistory.read(search);
Tweet tweet = (Tweet) search.getPayload();
logger.info("A search item was received " +
tweet.getCreatedAt() + " with text " + tweet.getText());
}
public void mention(Tweet s) {
logger.info("A tweet mentioning (or replying) to you was received having text "
+ s.getFromUser() + "-" + s.getText() + " from " + s.getSource());
}
public void searchResult(Collection<Tweet> tweets) {
if (tweets.size() == 0) {
logger.info("No results");
}
for (Tweet s : tweets) {
logger.info("Search result: "
+ s.getFromUser() + "-" + s.getText() + " from " + s.getSource());
}
}
public void updates(Tweet t) {
logger.info("Received timeline update: " + t.getText() + " from " + t.getSource());
}
}

View File

@@ -1,63 +1,63 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class DirectMessageReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveDm() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
DirectMessageReceivingMessageSource tSource = new DirectMessageReceivingMessageSource(template, "foo");
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<DirectMessage> message = tSource.receive();
if (message != null) {
DirectMessage tweet = message.getPayload();
logger.info(tweet.getSender().getScreenName() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class DirectMessageReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveDm() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
DirectMessageReceivingMessageSource tSource = new DirectMessageReceivingMessageSource(template, "foo");
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<DirectMessage> message = tSource.receive();
if (message != null) {
DirectMessage tweet = message.getPayload();
logger.info(tweet.getSender().getScreenName() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
}

View File

@@ -1,182 +1,182 @@
/*
* Copyright 2018 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.twitter.inbound;
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.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.SearchMetadata;
import org.springframework.social.twitter.api.SearchOperations;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Gary Russell
* @author Artem Bilan
*/
public class SearchReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
private static final String SEARCH_QUERY = "#springsource";
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveSearchResults() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
SearchReceivingMessageSource tSource = new SearchReceivingMessageSource(template, "foo");
tSource.setQuery(SEARCH_QUERY);
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<Tweet> message = tSource.receive();
if (message != null) {
Tweet tweet = message.getPayload();
logger.info(tweet.getFromUser() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
/**
* Unit Test ensuring some basic initialization properties being set.
*/
@Test
public void testSearchReceivingMessageSourceInit() {
final SearchReceivingMessageSource messageSource =
new SearchReceivingMessageSource(new TwitterTemplate("test"), "foo");
messageSource.setComponentName("twitterSearchMessageSource");
final Object metadataStore = TestUtils.getPropertyValue(messageSource, "metadataStore");
final Object metadataKey = TestUtils.getPropertyValue(messageSource, "metadataKey");
assertNull(metadataStore);
assertNotNull(metadataKey);
messageSource.setBeanFactory(mock(BeanFactory.class));
messageSource.afterPropertiesSet();
final Object metadataStoreInitialized = TestUtils.getPropertyValue(messageSource, "metadataStore");
final Object metadataKeyInitialized = TestUtils.getPropertyValue(messageSource, "metadataKey");
assertNotNull(metadataStoreInitialized);
assertTrue(metadataStoreInitialized instanceof SimpleMetadataStore);
assertNotNull(metadataKeyInitialized);
assertEquals("foo", metadataKeyInitialized);
final Twitter twitter = TestUtils.getPropertyValue(messageSource, "twitter", Twitter.class);
assertFalse(twitter.isAuthorized());
assertNotNull(twitter.userOperations());
}
/**
* This test ensures that when polling for a list of Tweets null is never returned.
* In case of no polling results, an empty list is returned instead.
*/
@Test
public void testPollForTweetsNullResults() {
final TwitterTemplate twitterTemplate = mock(TwitterTemplate.class);
final SearchOperations so = mock(SearchOperations.class);
given(twitterTemplate.searchOperations()).willReturn(so);
given(twitterTemplate.searchOperations().search(SEARCH_QUERY, 20, 0, 0)).willReturn(null);
final SearchReceivingMessageSource messageSource = new SearchReceivingMessageSource(twitterTemplate, "foo");
messageSource.setQuery(SEARCH_QUERY);
final String setQuery = TestUtils.getPropertyValue(messageSource, "query", String.class);
assertEquals(SEARCH_QUERY, setQuery);
assertEquals("twitter:search-inbound-channel-adapter", messageSource.getComponentType());
final List<Tweet> tweets = messageSource.pollForTweets(0);
assertNotNull(tweets);
assertTrue(tweets.isEmpty());
}
/**
* Verify that a polling operation returns in fact 3 results.
*/
@Test
public void testPollForTweetsThreeResults() {
final TwitterTemplate twitterTemplate;
final SearchOperations so = mock(SearchOperations.class);
final List<Tweet> tweets = new ArrayList<Tweet>();
tweets.add(mock(Tweet.class));
tweets.add(mock(Tweet.class));
tweets.add(mock(Tweet.class));
final SearchResults results = new SearchResults(tweets, new SearchMetadata(111, 111));
twitterTemplate = mock(TwitterTemplate.class);
given(twitterTemplate.searchOperations()).willReturn(so);
SearchParameters params = new SearchParameters(SEARCH_QUERY).count(20).sinceId(0);
given(twitterTemplate.searchOperations().search(params)).willReturn(results);
final SearchReceivingMessageSource messageSource = new SearchReceivingMessageSource(twitterTemplate, "foo");
messageSource.setQuery(SEARCH_QUERY);
final List<Tweet> tweetSearchResults = messageSource.pollForTweets(0);
assertNotNull(tweetSearchResults);
assertEquals(3, tweetSearchResults.size());
}
}
/*
* Copyright 2018 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.twitter.inbound;
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.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.SearchMetadata;
import org.springframework.social.twitter.api.SearchOperations;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @author Gary Russell
* @author Artem Bilan
*/
public class SearchReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
private static final String SEARCH_QUERY = "#springsource";
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveSearchResults() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
SearchReceivingMessageSource tSource = new SearchReceivingMessageSource(template, "foo");
tSource.setQuery(SEARCH_QUERY);
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<Tweet> message = tSource.receive();
if (message != null) {
Tweet tweet = message.getPayload();
logger.info(tweet.getFromUser() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
/**
* Unit Test ensuring some basic initialization properties being set.
*/
@Test
public void testSearchReceivingMessageSourceInit() {
final SearchReceivingMessageSource messageSource =
new SearchReceivingMessageSource(new TwitterTemplate("test"), "foo");
messageSource.setComponentName("twitterSearchMessageSource");
final Object metadataStore = TestUtils.getPropertyValue(messageSource, "metadataStore");
final Object metadataKey = TestUtils.getPropertyValue(messageSource, "metadataKey");
assertNull(metadataStore);
assertNotNull(metadataKey);
messageSource.setBeanFactory(mock(BeanFactory.class));
messageSource.afterPropertiesSet();
final Object metadataStoreInitialized = TestUtils.getPropertyValue(messageSource, "metadataStore");
final Object metadataKeyInitialized = TestUtils.getPropertyValue(messageSource, "metadataKey");
assertNotNull(metadataStoreInitialized);
assertTrue(metadataStoreInitialized instanceof SimpleMetadataStore);
assertNotNull(metadataKeyInitialized);
assertEquals("foo", metadataKeyInitialized);
final Twitter twitter = TestUtils.getPropertyValue(messageSource, "twitter", Twitter.class);
assertFalse(twitter.isAuthorized());
assertNotNull(twitter.userOperations());
}
/**
* This test ensures that when polling for a list of Tweets null is never returned.
* In case of no polling results, an empty list is returned instead.
*/
@Test
public void testPollForTweetsNullResults() {
final TwitterTemplate twitterTemplate = mock(TwitterTemplate.class);
final SearchOperations so = mock(SearchOperations.class);
given(twitterTemplate.searchOperations()).willReturn(so);
given(twitterTemplate.searchOperations().search(SEARCH_QUERY, 20, 0, 0)).willReturn(null);
final SearchReceivingMessageSource messageSource = new SearchReceivingMessageSource(twitterTemplate, "foo");
messageSource.setQuery(SEARCH_QUERY);
final String setQuery = TestUtils.getPropertyValue(messageSource, "query", String.class);
assertEquals(SEARCH_QUERY, setQuery);
assertEquals("twitter:search-inbound-channel-adapter", messageSource.getComponentType());
final List<Tweet> tweets = messageSource.pollForTweets(0);
assertNotNull(tweets);
assertTrue(tweets.isEmpty());
}
/**
* Verify that a polling operation returns in fact 3 results.
*/
@Test
public void testPollForTweetsThreeResults() {
final TwitterTemplate twitterTemplate;
final SearchOperations so = mock(SearchOperations.class);
final List<Tweet> tweets = new ArrayList<Tweet>();
tweets.add(mock(Tweet.class));
tweets.add(mock(Tweet.class));
tweets.add(mock(Tweet.class));
final SearchResults results = new SearchResults(tweets, new SearchMetadata(111, 111));
twitterTemplate = mock(TwitterTemplate.class);
given(twitterTemplate.searchOperations()).willReturn(so);
SearchParameters params = new SearchParameters(SEARCH_QUERY).count(20).sinceId(0);
given(twitterTemplate.searchOperations().search(params)).willReturn(results);
final SearchReceivingMessageSource messageSource = new SearchReceivingMessageSource(twitterTemplate, "foo");
messageSource.setQuery(SEARCH_QUERY);
final List<Tweet> tweetSearchResults = messageSource.pollForTweets(0);
assertNotNull(tweetSearchResults);
assertEquals(3, tweetSearchResults.size());
}
}

View File

@@ -1,64 +1,64 @@
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TimelineReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveTimeline() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
TimelineReceivingMessageSource tSource = new TimelineReceivingMessageSource(template, "foo");
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<Tweet> message = tSource.receive();
if (message != null) {
Tweet tweet = message.getPayload();
logger.info(tweet.getFromUser() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
}
/*
* Copyright 2018 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.twitter.inbound;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Gary Russell
*/
public class TimelineReceivingMessageSourceTests {
private final Log logger = LogFactory.getLog(getClass());
@SuppressWarnings("unchecked")
@Test
@Ignore
public void demoReceiveTimeline() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
TimelineReceivingMessageSource tSource = new TimelineReceivingMessageSource(template, "foo");
tSource.afterPropertiesSet();
for (int i = 0; i < 50; i++) {
Message<Tweet> message = tSource.receive();
if (message != null) {
Tweet tweet = message.getPayload();
logger.info(tweet.getFromUser() + " - " + tweet.getText() + " - " + tweet.getCreatedAt());
}
}
}
}

View File

@@ -1,56 +1,56 @@
/*
* Copyright 2018 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.twitter.outbound;
import java.util.Properties;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*/
public class DirectMessageSendingMessageHandlerTests {
@Test
@Ignore
public void validateSendDirectMessage() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("spring_eip.oauth.consumerKey"),
prop.getProperty("spring_eip.oauth.consumerSecret"),
prop.getProperty("spring_eip.oauth.accessToken"),
prop.getProperty("spring_eip.oauth.accessTokenSecret"));
Message<?> message1 = MessageBuilder.withPayload("Polsihing SI Twitter migration")
.setHeader(TwitterHeaders.DM_TARGET_USER_ID, "z_oleg").build();
DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(template);
handler.afterPropertiesSet();
handler.handleMessage(message1);
}
}
/*
* Copyright 2018 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.twitter.outbound;
import java.util.Properties;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.messaging.Message;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
*/
public class DirectMessageSendingMessageHandlerTests {
@Test
@Ignore
public void validateSendDirectMessage() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("spring_eip.oauth.consumerKey"),
prop.getProperty("spring_eip.oauth.consumerSecret"),
prop.getProperty("spring_eip.oauth.accessToken"),
prop.getProperty("spring_eip.oauth.accessTokenSecret"));
Message<?> message1 = MessageBuilder.withPayload("Polsihing SI Twitter migration")
.setHeader(TwitterHeaders.DM_TARGET_USER_ID, "z_oleg").build();
DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(template);
handler.afterPropertiesSet();
handler.handleMessage(message1);
}
}

View File

@@ -1,110 +1,110 @@
/*
* Copyright 2018 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.twitter.outbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Collections;
import java.util.Properties;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.TimelineOperations;
import org.springframework.social.twitter.api.TweetData;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.MultiValueMap;
/**
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class StatusUpdatingMessageHandlerTests {
@Autowired
MessageChannel in1;
@Autowired
MessageChannel in2;
@Autowired
Twitter twitter;
@Test
@Ignore
public void demoSendStatusMessage() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
Message<?> message1 = new GenericMessage<>("Polishing #springintegration migration to Spring Social. test");
StatusUpdatingMessageHandler handler = new StatusUpdatingMessageHandler(template);
handler.afterPropertiesSet();
handler.handleMessage(message1);
}
@Test
public void testStatusUpdatingMessageHandler() {
TimelineOperations timelineOperations = Mockito.mock(TimelineOperations.class);
Mockito.when(this.twitter.timelineOperations()).thenReturn(timelineOperations);
ArgumentCaptor<TweetData> argument = ArgumentCaptor.forClass(TweetData.class);
this.in1.send(new GenericMessage<String>("foo"));
Mockito.verify(timelineOperations).updateStatus(argument.capture());
assertEquals("foo", argument.getValue().toRequestParameters().getFirst("status"));
Mockito.reset(timelineOperations);
ClassPathResource media = new ClassPathResource("log4j.properties");
this.in2.send(MessageBuilder.withPayload(Collections.singletonMap("foo", "bar"))
.setHeader("media", media)
.build());
Mockito.verify(timelineOperations).updateStatus(argument.capture());
TweetData tweetData = argument.getValue();
MultiValueMap<String, Object> requestParameters = tweetData.toRequestParameters();
assertEquals("bar", requestParameters.getFirst("status"));
assertNull(requestParameters.getFirst("media"));
MultiValueMap<String, Object> uploadMediaParameters = tweetData.toUploadMediaParameters();
assertEquals(media, uploadMediaParameters.getFirst("media"));
}
}
/*
* Copyright 2018 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.twitter.outbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Collections;
import java.util.Properties;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.TimelineOperations;
import org.springframework.social.twitter.api.TweetData;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.MultiValueMap;
/**
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class StatusUpdatingMessageHandlerTests {
@Autowired
MessageChannel in1;
@Autowired
MessageChannel in2;
@Autowired
Twitter twitter;
@Test
@Ignore
public void demoSendStatusMessage() throws Exception {
PropertiesFactoryBean pf = new PropertiesFactoryBean();
pf.setLocation(new ClassPathResource("sample.properties"));
pf.afterPropertiesSet();
Properties prop = pf.getObject();
TwitterTemplate template = new TwitterTemplate(prop.getProperty("z_oleg.oauth.consumerKey"),
prop.getProperty("z_oleg.oauth.consumerSecret"),
prop.getProperty("z_oleg.oauth.accessToken"),
prop.getProperty("z_oleg.oauth.accessTokenSecret"));
Message<?> message1 = new GenericMessage<>("Polishing #springintegration migration to Spring Social. test");
StatusUpdatingMessageHandler handler = new StatusUpdatingMessageHandler(template);
handler.afterPropertiesSet();
handler.handleMessage(message1);
}
@Test
public void testStatusUpdatingMessageHandler() {
TimelineOperations timelineOperations = Mockito.mock(TimelineOperations.class);
Mockito.when(this.twitter.timelineOperations()).thenReturn(timelineOperations);
ArgumentCaptor<TweetData> argument = ArgumentCaptor.forClass(TweetData.class);
this.in1.send(new GenericMessage<String>("foo"));
Mockito.verify(timelineOperations).updateStatus(argument.capture());
assertEquals("foo", argument.getValue().toRequestParameters().getFirst("status"));
Mockito.reset(timelineOperations);
ClassPathResource media = new ClassPathResource("log4j.properties");
this.in2.send(MessageBuilder.withPayload(Collections.singletonMap("foo", "bar"))
.setHeader("media", media)
.build());
Mockito.verify(timelineOperations).updateStatus(argument.capture());
TweetData tweetData = argument.getValue();
MultiValueMap<String, Object> requestParameters = tweetData.toRequestParameters();
assertEquals("bar", requestParameters.getFirst("status"));
assertNull(requestParameters.getFirst("media"));
MultiValueMap<String, Object> uploadMediaParameters = tweetData.toUploadMediaParameters();
assertEquals(media, uploadMediaParameters.getFirst("media"));
}
}

View File

@@ -1,238 +1,238 @@
/*
* Copyright 2018 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.twitter.outbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGatewayTests.TwitterConfig;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.SearchMetadata;
import org.springframework.social.twitter.api.SearchOperations;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
*/
@ContextConfiguration(classes = TwitterConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class TwitterSearchOutboundGatewayTests {
@Autowired
private SearchOperations searchOps;
@Autowired
private TwitterSearchOutboundGateway gateway;
@Autowired
private PollableChannel outputChannel;
@Test
public void testStringQuery() {
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(20), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testStringQueryCustomLimit() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("{payload, 30}"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(30), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testStringQueryCustomExpression() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("{'bar', 1, 2, 3}"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("bar", searchParameters.getQuery());
assertEquals(Integer.valueOf(1), searchParameters.getCount());
assertEquals(Long.valueOf(2), searchParameters.getSinceId());
assertEquals(Long.valueOf(3), searchParameters.getMaxId());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testSearchParamsQuery() {
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
final SearchParameters parameters = new SearchParameters("bar");
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertSame(parameters, searchParameters);
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<SearchParameters>(parameters));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testSearchParamsQueryCustomExpression() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("new SearchParameters('foo' + payload).count(5).sinceId(11)"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foobar", searchParameters.getQuery());
assertEquals(Integer.valueOf(5), searchParameters.getCount());
assertEquals(Long.valueOf(11), searchParameters.getSinceId());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("bar"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testEmptyResult() {
SearchMetadata searchMetadata = mock(SearchMetadata.class);
List<Tweet> empty = new ArrayList<Tweet>(0);
final SearchResults searchResults = new SearchResults(empty, searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(20), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(0, tweets.size());
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Configuration
@EnableIntegration
public static class TwitterConfig {
@Bean
public TwitterSearchOutboundGateway gateway() {
TwitterSearchOutboundGateway gateway = new TwitterSearchOutboundGateway(twitter());
gateway.setOutputChannel(outputChannel());
return gateway;
}
@Bean
public PollableChannel outputChannel() {
return new QueueChannel();
}
@Bean
public Twitter twitter() {
Twitter twitter = mock(Twitter.class);
given(twitter.searchOperations()).willReturn(searchOps());
return twitter;
}
@Bean
public SearchOperations searchOps() {
return mock(SearchOperations.class);
}
}
}
/*
* Copyright 2018 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.twitter.outbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.twitter.core.TwitterHeaders;
import org.springframework.integration.twitter.outbound.TwitterSearchOutboundGatewayTests.TwitterConfig;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.social.twitter.api.SearchMetadata;
import org.springframework.social.twitter.api.SearchOperations;
import org.springframework.social.twitter.api.SearchParameters;
import org.springframework.social.twitter.api.SearchResults;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
*/
@ContextConfiguration(classes = TwitterConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class TwitterSearchOutboundGatewayTests {
@Autowired
private SearchOperations searchOps;
@Autowired
private TwitterSearchOutboundGateway gateway;
@Autowired
private PollableChannel outputChannel;
@Test
public void testStringQuery() {
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(20), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testStringQueryCustomLimit() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("{payload, 30}"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(30), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testStringQueryCustomExpression() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("{'bar', 1, 2, 3}"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("bar", searchParameters.getQuery());
assertEquals(Integer.valueOf(1), searchParameters.getCount());
assertEquals(Long.valueOf(2), searchParameters.getSinceId());
assertEquals(Long.valueOf(3), searchParameters.getMaxId());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testSearchParamsQuery() {
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
final SearchParameters parameters = new SearchParameters("bar");
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertSame(parameters, searchParameters);
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<SearchParameters>(parameters));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testSearchParamsQueryCustomExpression() {
this.gateway.setSearchArgsExpression(new SpelExpressionParser()
.parseExpression("new SearchParameters('foo' + payload).count(5).sinceId(11)"));
Tweet tweet = mock(Tweet.class);
SearchMetadata searchMetadata = mock(SearchMetadata.class);
final SearchResults searchResults = new SearchResults(Collections.singletonList(tweet), searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foobar", searchParameters.getQuery());
assertEquals(Integer.valueOf(5), searchParameters.getCount());
assertEquals(Long.valueOf(11), searchParameters.getSinceId());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("bar"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(1, tweets.size());
assertSame(tweet, tweets.get(0));
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Test
public void testEmptyResult() {
SearchMetadata searchMetadata = mock(SearchMetadata.class);
List<Tweet> empty = new ArrayList<Tweet>(0);
final SearchResults searchResults = new SearchResults(empty, searchMetadata);
willAnswer(invocation -> {
SearchParameters searchParameters = invocation.getArgument(0);
assertEquals("foo", searchParameters.getQuery());
assertEquals(Integer.valueOf(20), searchParameters.getCount());
return searchResults;
}).given(this.searchOps).search(any(SearchParameters.class));
this.gateway.handleMessage(new GenericMessage<String>("foo"));
Message<?> reply = this.outputChannel.receive(0);
assertNotNull(reply);
@SuppressWarnings("unchecked")
List<Tweet> tweets = (List<Tweet>) reply.getPayload();
assertEquals(0, tweets.size());
assertSame(searchMetadata, reply.getHeaders().get(TwitterHeaders.SEARCH_METADATA));
}
@Configuration
@EnableIntegration
public static class TwitterConfig {
@Bean
public TwitterSearchOutboundGateway gateway() {
TwitterSearchOutboundGateway gateway = new TwitterSearchOutboundGateway(twitter());
gateway.setOutputChannel(outputChannel());
return gateway;
}
@Bean
public PollableChannel outputChannel() {
return new QueueChannel();
}
@Bean
public Twitter twitter() {
Twitter twitter = mock(Twitter.class);
given(twitter.searchOperations()).willReturn(searchOps());
return twitter;
}
@Bean
public SearchOperations searchOps() {
return mock(SearchOperations.class);
}
}
}