The Spring Social Twitter project is an extension to Spring Social that enables integration with Twitter.
1. Introduction
Twitter is a popular micro-blogging and social networking service, enabling people to communicate with each other 140 characters at a time.
Spring Social Twitter enables integration with Twitter with TwitterConnectionFactory
, a connection factory that can be plugged into Spring Social’s service provider connection framework, and with an API binding to Twitter’s REST API.
1.1. How to get
The following Gradle dependency will add Spring Social Twitter to your project:
compile "org.springframework.social:spring-social-twitter:1.1.2.RELEASE"
Or in Maven:
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-twitter</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
As an extension to Spring Social, Spring Social Twitter depends on Spring Social. Spring Social’s core module will be transitively resolved from the Spring Social Twitter dependency. If you’ll be using Spring Social’s web module, you’ll need to add that dependency yourself. In Gradle:
compile "org.springframework.social:spring-social-web:1.1.0.RELEASE"
Or in Maven:
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-web</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
Note that Spring Social Twitter may release on a different schedule than Spring Social. Consequently, Spring Social’s version may differ from that of Spring Social Twitter.
Consult Spring Social’s reference documentation for more information on Spring Social dependencies.
2. Configuring Twitter Connectivity
Spring Social’s ConnectController
works with one or more provider-specific ConnectionFactory
instances to exchange authorization details with the provider and to create connections.
Spring Social Twitter provides TwitterConnectionFactory
, a ConnectionFactory
for creating connections with Twitter.
So that ConnectController
can find TwitterConnectionFactory
, it must be registered with a ConnectionFactoryRegistry
.
The following configuration class uses Spring Social’s Java configuration support to register a ConnectionFactory
for Twitter:
@Configuration
public class SocialConfig implements SocialConfigurer {
@Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
cfConfig.addConnectionFactory(new TwitterConnectionFactory(
env.getProperty("twitter.consumerKey"),
env.getProperty("twitter.consumerSecret")));
}
...
}
If we wanted to add support for connecting to other providers, we would simply register their connection factories here in the same way as TwitterConnectionFactory
.
Because client IDs and secrets may be different across environments (e.g., test, production, etc) it is recommended that these values be externalized. As shown here, Spring’s Environment
abstraction is provided as a parameter to addConnectionFactories()
so that it can look up the application’s client ID and secret.
Optionally, you may also configure TwitterConnectionFactory
in XML.
Using Spring Social Twitter’s XML configuration namespace:
<twitter:config app-id="${twitter.consumerKey}"
app-secret="${twitter.consumerSecret}" />
This is roughly equivalent to the Java-based configuration of ConnectionFactoryRegistry
shown before.
As in the Java-based configuration, the application’s client ID and secret are externalized (shown here as property placeholders).
Refer to
Spring Social’s reference documentation for complete details on configuring ConnectController
and its dependencies.
3. Twitter API Binding
Spring Social Twitter offers integration with Twitter’s REST API through the Twitter
interface and its implementation, TwitterTemplate
.
Creating an instance of TwitterTemplate
involves invoking its constructor, passing in the application’s OAuth credentials and an access token/secret pair authorizing the application to act on a user’s behalf.
For example:
String consumerKey = "..."; // The application's consumer key
String consumerSecret = "..."; // The application's consumer secret
String accessToken = "..."; // The access token granted after OAuth authorization
String accessTokenSecret = "..."; // The access token secret granted after OAuth authorization
Twitter twitter = new TwitterTemplate(consumerKey, consumerSecret, accessToken, accessTokenSecret);
In addition, TwitterTemplate
has two more constructors that creates an instance for working with non-user-centric data.
The first takes only an access token:
String clientToken = "..."; // A client access token
Twitter twitter = new TwitterTemplate(clientToken);
What’s important to note here is that the access token given must be a client token, obtained via an OAuth 2 client credentials grant.
Spring Social’s OAuth2Template
can help you obtain a client token via its authenticateClient()
method.
When you construct TwitterTemplate
this way, it will be limited to performing operations that aren’t on behalf of a specific user.
For instance, you can do search operations, fetch a specific tweet, or even fetch the profile for a given user.
You cannot, however, post a tweet or read a user’s direct messages.
Alternatively, you can construct a TwitterTemplate
using only the client credentials:
String consumerKey = "..."; // The application's consumer key
String consumerSecret = "..."; // The application's consumer secret
Twitter twitter = new TwitterTemplate(consumerKey, consumerSecret);
When constructed in this way, TwitterTemplate
will use the client credentials to obtain a client access token on its own.
The end result is the same as if you had constructed it with a client token.
If you are using Spring Social’s
service provider framework, you can get an instance of Twitter from a
Connection
. For example, the following snippet calls getApi() on a
connection to retrieve a Twitter:
Connection<Twitter> connection = connectionRepository.findPrimaryConnection(Twitter.class);
Twitter twitter = connection != null ?
connection.getApi() :
new TwitterTemplate(
env.getProperty("twitter.consumerKey"),
env.getProperty("twitter.consumerSecret"));
Here, ConnectionRepository
is being asked for the primary connection that the current user has with Twitter.
If connection to Twitter is found, a call to getApi()
retrieves a Twitter
instance that is configured with the connection details received when the connection was first established.
If there is no connection, a client instance of TwitterTemplate is created using the client credentials obtained via the Environment
abstraction.
Once you have a Twitter
instance, you can perform a several operations against Twitter’s API.
The Twitter
interface is defined as follows:
public interface Twitter {
BlockOperations blockOperations();
DirectMessageOperations directMessageOperations();
FriendOperations friendOperations();
GeoOperations geoOperations();
ListOperations listOperations();
SearchOperations searchOperations();
StreamingOperations streamingOperations();
TimelineOperations timelineOperations();
UserOperations userOperations();
RestOperations restOperations();
}
Each method returns sub-APIs, partitioning the Twitter service API into divisions targeting specific facets of Twitter functionality. These sub-APIs are defined by interfaces described in Twitter’s Sub-APIs.
Sub-API Interface | Description |
---|---|
BlockOperations |
Block and unblock users |
DirectMessageOperations |
Reading and sending direct messages. |
FriendOperations |
Retrieving a user’s list of friends and followers and following/unfollowing users. |
GeoOperations |
Working with locations. |
ListOperations |
Maintaining, subscribing to, and unsubscribing from user lists |
SearchOperations |
Searching tweets and viewing search trends |
StreamingOperations |
Receive tweets as they are created via Twitter’s Streaming API. |
TimelineOperations |
Reading timelines and posting tweets. |
UserOperations |
Retrieving user profile data. |
In addition to the Twitter-specific sub-APIs described in table Twitter’s Sub-APIs, Twitter
also has a restOperations()
method that returns a RestOperations
(e.g., RestTemplate
).
The RestOperations
returned is instrumented to add an OAuth Authorization
header for all requests it sends to Twitter.
What follows is a survey of common tasks you may perform with Twitter and its sub-APIs. For complete details on the Spring Social’s entire Twitter API binding, refer to the JavaDoc.
3.1. Retrieving a user’s Twitter profile data
To get a user’s Twitter profile, call UserOperations
' getUserProfile()
:
TwitterProfile profile = twitter.userOperations().getUserProfile();
This returns a TwitterProfile
object containing profile data for the authenticated user.
This profile information includes the user’s Twitter screen name, their name, location, description, and the date that they created their Twitter account.
Also included is a URL to their profile image.
If you want to retrieve the user profile for a specific user other than the authenticated user, you can so do by passing the user’s screen name as a parameter to getUserProfile()
:
TwitterProfile profile = twitter.userOperations().getUserProfile("habuma");
If all you need is the screen name for the authenticating user, then call UserOperations.getScreenName()
:
String profileId = twitter.userOperations().getScreenName();
3.2. Tweeting
To post a message to Twitter the simplest thing to do is to pass the message to the updateStatus()
method provided by TimelineOperations
:
twitter.timelineOperations().updateStatus("Spring Social is awesome!")
It’s also possible to include additional metadata about a Tweet, such as the location (latitude and longitude) from which the Tweet was sent.
To provide this additional metadata, you can construct and post a TweetData
object.
For example, to post the location of a Tweet:
twitter.timelineOperations().updateStatus(
new TweetData("I'm tweeting from London!")
.atLocation(-0.126f, 51.502f));
To have Twitter display the location in a map (on the Twitter web site) then you should also set the displayCoordinates
property to true
:
twitter.timelineOperations().updateStatus(
new TweetData("I'm tweeting from London!")
.atLocation(-0.126f, 51.502f)
.displayCoordinates(true));
If you’d like to retweet another tweet (perhaps one found while searching or reading the Twitter timeline), call the retweet()
method, passing in the ID of the tweet to be retweeted:
long tweetId = tweet.getId();
twitter.timelineOperations().retweet(tweetId);
Note that Twitter disallows repeated tweets.
Attempting to tweet or retweet the same message multiple times will result in a DuplicateTweetException
being thrown.
3.3. Reading Twitter timelines
From a Twitter user’s perspective, Twitter organizes tweets into two different timelines:
-
User - Includes tweets posted by the user.
-
Home - Includes tweets from the user’s timeline and the timeline of anyone that they follow.
getHomeTimeline()
retrieves the 20 most recent tweets from the user’s home timeline:
List<Tweet> tweets = twitter.timelineOperations().getHomeTimeline();
To get tweets from the authenticating user’s own timeline, call the getUserTimeline()
method:
List<Tweet> tweets = twitter.timelineOperations().getUserTimeline();
If you’d like to retrieve the 20 most recent tweets from a specific user’s timeline (not necessarily the authenticating user’s timeline), pass the user’s screen name in as a parameter to getUserTimeline()
:
List<Tweet> tweets = twitter.timelineOperations().getUserTimeline("rclarkson");
In addition to the four Twitter timelines, you may also want to get a list of tweets mentioning the user.
The getMentions()
method returns the 20 most recent tweets that mention the authenticating user:
List<Tweet> tweets = twitter.timelineOperations().getMentions();
3.4. Friends and Followers
A key social concept in Twitter is the ability for one user to "follow" another user.
The followed user’s tweets will appear in the following user’s home and friends timelines.
To follow a user on behalf of the authenticating user, call the FriendOperations
' follow()
method:
twitter.friendOperations().follow("habuma");
Similarly, you may stop following a user using the unfollow()
method:
twitter.friendOperations().unfollow("habuma");
If you want to see who a particular user is following, use the getFriends()
method:
List<TwitterProfile> friends = twitter.friendOperations().getFriends("habuma");
On the other hand, you may be interested in seeing who is following a given user. In that case the getFollowers()
method may be useful:
List<TwitterProfile> followers = twitter.friendOperations().getFollowers("habuma");
3.5. Twitter User Lists
In addition to following other users, Twitter provides the ability for users to collect users in lists, regardless of whether or not they are being followed. These lists may be private to the use who created them or may be public for others to read and subscribe to.
To create a new list, use ListOperations
' createList()
method:
UserList familyList = twitter.listOperations().createList(
"My Family", "Tweets from my immediate family members", false);
createList()
takes three parameters and returns a UserList
object representing the newly created list.
The first parameter is the name of the list.
The second parameter is a brief description of the list.
The final parameter is a boolean indicating whether or not the list is public.
Here, false indicates that the list should be private.
Once the list is created, you may add members to the list by calling the addToList()
method:
twitter.listOperations().addToList(familyList.getSlug(), "artnames");
The first parameter given to addToList()
is the list slug (which is readily available from the UserList
object).
The second parameter is the screen name of a user to add to the list.
To remove a member from a list, pass the same parameters to removeFromList()
:
twitter.listOperations().removeFromList(familyList.getSlug(), "artnames");
You can also subscribe to a list on behalf of the authenticating user.
Subscribing to a list has the effect of including tweets from the list’s members in the user’s home timeline.
The subscribe()
method is used to subscribe to a list:
twitter.listOperations().subscribe("habuma", "music");
Here, subscribe()
is given the list owner’s screen name ("habuma") and the list slug ("music").
Similarly, you may unsubscribe from a list with the unsubscribe()
method:
twitter.listOperations().unsubscribe("habuma", "music");
3.6. Searching Twitter
SearchOperations
enables you to search the public timeline for tweets containing some text through its search()
method.
For example, to search for tweets containing "#spring":
SearchResults results = twitter.searchOperations().search("#spring");
The search()
method will return a SearchResults
object that includes a list of 50 most recent matching tweets as well as some metadata concerning the result set.
The metadata includes the maximum tweet ID in the search results list as well as the ID of a tweet that precedes the
resulting tweets.
The sinceId
and maxId
properties effectively define the boundaries of the result set.
Additionally, there’s a boolean lastPage
property that, if true
, indicates that this result set is
the page of results.
To gain better control over the paging of results, you may choose to pass in the page and results per page to search()
:
SearchResults results = twitter.searchOperations().search("#spring", 2, 10);
Here, we’re asking for the 2nd page of results where the pages have 10 tweets per page.
Finally, if you’d like to confine the bounds of the search results to fit between two tweet IDs, you may pass in the since and maximum tweet ID values to search()
:
SearchResults results = twitter.searchOperations().search("#spring", 2, 10, 145962, 210112);
This ensures that the result set will not contain any tweets posted before the tweet whose ID is 146962 nor any tweets posted after the tweet whose ID is 210112.
3.7. Advanced search
For more enhanced search you can also use SearchParameters
object and pass it to search()
method.
It allows you to specify more search keys.
For example, searching tweets containing "#spring" keyword in Dutch language:
SearchParameters params = new SearchParameters("#spring");
params.setLang("nl");
SearchResults results = twitter.searchOperations().search(params);
There are some more search parameters available:
SearchResults results = twitter.searchOperations().search(
new SearchParameters("#spring")
.geoCode(new GeoCode(52.379241, 4.900846, 100, GeoCode.Unit.MILE))
.lang("nl")
.resultType(SearchParameters.ResultType.RECENT)
.count(25)
.includeEntities(false));
3.8. Sending and receiving direct messages
In addition to posting tweets to the public timelines, Twitter also supports sending of private messages directly to a given user.
DirectMessageOperations
' sendDirectMessage()
method can be used to send a direct message to another user:
twitter.directMessageOperations().sendDirectMessage("kdonald", "You going to the Dolphins game?")
DirectMessageOperations
can also be used to read direct messages received by the authenticating user through its getDirectMessagesReceived()
method:
List<DirectMessage> twitter.directMessageOperations().getDirectMessagesReceived();
getDirectMessagesReceived()
will return the 20 most recently received direct messages.