using parameterized types

This commit is contained in:
Mark Fisher
2011-09-15 14:22:43 -04:00
parent e5ce83329f
commit 00ed21cbae
7 changed files with 54 additions and 52 deletions

View File

@@ -18,9 +18,9 @@
</para>
<para>
<important>
Previous versions of Spring Integration were dependent on <link linkend="http://twitter4j.org/en/index.html">Twitter4J API</link>,
but after the release of <link linkend="http://www.springsource.org/spring-social">Spring Social 1.0 GA</link>
Spring Integration 2.1 and all future releases are now depending on Spring Social framework's Twitter support.
Previous versions of Spring Integration were dependent upon the <link linkend="http://twitter4j.org/en/index.html">Twitter4J API</link>,
but with the release of <link linkend="http://www.springsource.org/spring-social">Spring Social 1.0 GA</link>,
Spring Integration, as of version 2.1, now builds directly upon Spring Social's Twitter support, instead of Twitter4J.
</important>
</para>
@@ -72,13 +72,14 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration/twitter
<title>Twitter Template</title>
<para>
Spring Integration uses the same familiar template pattern to interact with Twitter and Spring Social provides <classname>org.springframework.social.twitter.api.impl.TwitterTemplate</classname>
For anonymous operations (e.g., search), you don't have to define <classname>TwitterTemplate</classname> explicitly, since a default
instance will be created and injected into the endpoint. However, for authenticated operation
(update status, send direct message, etc.), you must configure <classname>TwitterTemplate</classname> as a bean and
inject it explicitly into the endpoint, because the authentication configuration is required.
Below is a sample configuration of TwitterTemplate:
As mentioned above, Spring Integration relies upon Spring Social, and that library provides an implementation of the template
pattern, <classname>org.springframework.social.twitter.api.impl.TwitterTemplate</classname> to interact with Twitter.
For anonymous operations (e.g., search), you don't have to define an instance of <classname>TwitterTemplate</classname> explicitly,
since a default instance will be created and injected into the endpoint. However, for authenticated operations
(update status, send direct message, etc.), you must configure a <classname>TwitterTemplate</classname> as a bean and
inject it explicitly into the endpoint, because the authentication configuration is required.
Below is a sample configuration of TwitterTemplate:
<programlisting language="xml"><![CDATA[<bean id="twitterTemplate" class="org.springframework.social.twitter.api.impl.TwitterTemplate">
<constructor-arg value="4XzBPacJQxyBzzzH"/>
<constructor-arg value="AbRxUAvyCtqQtvxFK8w5ZMtMj20KFhB6o"/>

View File

@@ -16,13 +16,14 @@
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.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.twitter.outbound.DirectMessageSendingMessageHandler;
import org.springframework.integration.twitter.outbound.StatusUpdatingMessageHandler;
import org.w3c.dom.Element;
/**
* Parser for all outbound Twitter adapters

View File

@@ -60,7 +60,7 @@ abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport
private volatile String metadataKey;
private final Queue<Object> tweets = new LinkedBlockingQueue<Object>();
private final Queue<T> tweets = new LinkedBlockingQueue<T>();
private volatile int prefetchThreshold = 0;
@@ -127,7 +127,7 @@ abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport
}
public Message<?> receive() {
Object tweet = this.tweets.poll();
T tweet = this.tweets.poll();
if (tweet == null) {
long currentTime = System.currentTimeMillis();
long elapsedTime = currentTime - this.lastPollForTweet;
@@ -147,14 +147,14 @@ abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport
return null;
}
private void enqueueAll(List<?> tweets) {
private void enqueueAll(List<T> tweets) {
Collections.sort(tweets, this.tweetComparator);
for (Object tweet : tweets) {
for (T tweet : tweets) {
enqueue(tweet);
}
}
private void enqueue(Object tweet) {
private void enqueue(T tweet) {
synchronized (this.lastEnqueuedIdMonitor) {
long id = this.getIdForTweet(tweet);
if (id > this.lastEnqueuedId) {
@@ -167,7 +167,7 @@ abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport
private void refreshTweetQueueIfNecessary() {
try {
if (tweets.size() <= prefetchThreshold) {
List<?> tweets = pollForTweets(lastEnqueuedId);
List<T> tweets = pollForTweets(lastEnqueuedId);
if (!CollectionUtils.isEmpty(tweets)) {
enqueueAll(tweets);
}
@@ -185,49 +185,48 @@ abstract class AbstractTwitterMessageSource<T> extends IntegrationObjectSupport
* Subclasses must implement this to return tweets.
* The 'sinceId' value will be negative if no last id is known.
*/
protected abstract List<?> pollForTweets(long sinceId);
protected abstract List<T> pollForTweets(long sinceId);
private static class TweetComparator implements Comparator<Object> {
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);
}
}
public int compare(Object tweet1, Object tweet2) {
// hopefully temporary logic. Will suggest improvement to SpringSocial to have a common base class for DM and Tweet
if (tweet1 instanceof Tweet && tweet2 instanceof Tweet){
private class TweetComparator implements Comparator<T> {
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. Can not compare");
Assert.notNull(t2CreatedAt, "Tweet is missing 'createdAt' date. Can not compare");
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. Can not compare");
Assert.notNull(d2CreatedAt, "DirectMessage is missing 'createdAt' date. Can not compare");
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);
}
}
}
private long getIdForTweet(Object twitterMessage){
if (twitterMessage instanceof Tweet){
Tweet t = (Tweet) twitterMessage;
return t.getId();
}
else if (twitterMessage instanceof DirectMessage){
DirectMessage d = (DirectMessage) twitterMessage;
return d.getId();
}
else {
throw new IllegalArgumentException("Unrecognized Twitter object: " + twitterMessage );
}
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.integration.twitter.inbound;
import java.util.List;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.DirectMessage;
import org.springframework.social.twitter.api.Twitter;
/**
@@ -29,7 +29,7 @@ import org.springframework.social.twitter.api.Twitter;
* @author Mark Fisher
* @since 2.0
*/
public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource<DirectMessage> {
public DirectMessageReceivingMessageSource(Twitter twitter) {
super(twitter);
@@ -42,7 +42,7 @@ public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageS
}
@Override
protected List<?> pollForTweets(long sinceId) {
protected List<DirectMessage> pollForTweets(long sinceId) {
return this.getTwitter().directMessageOperations().getDirectMessagesReceived(1, 20, sinceId, 0);
}

View File

@@ -30,18 +30,18 @@ import org.springframework.social.twitter.api.Twitter;
*/
public class MentionsReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public MentionsReceivingMessageSource(Twitter twitter){
public MentionsReceivingMessageSource(Twitter twitter) {
super(twitter);
}
@Override
public String getComponentType() {
return "twitter:mention-inbound-channel-adapter";
return "twitter:mentions-inbound-channel-adapter";
}
@Override
protected List<?> pollForTweets(long sinceId) {
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getMentions(1, 20, sinceId, 0);
}

View File

@@ -16,6 +16,7 @@
package org.springframework.integration.twitter.inbound;
import java.util.Collections;
import java.util.List;
import org.springframework.social.twitter.api.SearchResults;
@@ -49,9 +50,9 @@ public class SearchReceivingMessageSource extends AbstractTwitterMessageSource<T
}
@Override
protected List<?> pollForTweets(long sinceId) {
protected List<Tweet> pollForTweets(long sinceId) {
SearchResults results = this.getTwitter().searchOperations().search(query, 1, 20, sinceId, 0);
return (results != null) ? results.getTweets() : null;
return (results != null) ? results.getTweets() : Collections.<Tweet>emptyList();
}
}

View File

@@ -31,7 +31,7 @@ import org.springframework.social.twitter.api.Twitter;
*/
public class TimelineReceivingMessageSource extends AbstractTwitterMessageSource<Tweet> {
public TimelineReceivingMessageSource(Twitter twitter){
public TimelineReceivingMessageSource(Twitter twitter) {
super(twitter);
}
@@ -42,7 +42,7 @@ public class TimelineReceivingMessageSource extends AbstractTwitterMessageSource
}
@Override
protected List<?> pollForTweets(long sinceId) {
protected List<Tweet> pollForTweets(long sinceId) {
return this.getTwitter().timelineOperations().getHomeTimeline(1, 20, sinceId, 0);
}