The Basic Authentication for authorizing with Twitter API will be turned off on Aug 16th. After that OAuth will be the only way to invoke the API.
Beginner’s guide to OAuth provide an excellent explanation to OAuth. The typical analogy for OAuth is a "valet key" to the car which is a stripped down version of your regular key. These keys are meant for valet drivers who don’t need to open trunk or glove compartment and don’t need to drive the car for longer distance. So even though they have access to the entire car but are restricted to the limited functionality.
OAuth is used to share your resources (photos, videos, bank accounts, etc) stored on one site with another site without having to share your username and password. The site storing the resources is "Service Provider", the site requesting the access is "Consumer", you are the "User", "Tokens" are "valet key" that provide required access to the resources.
This Tip Of The Day (TOTD) explains how Jersey, the Reference Implementation for JAX-RS, provides seamless support for OAuth by creating a simple desktop application that retrieves user timeline on Twitter using OAuth. This blog is going to combine the instructions outlined in Understanding the guts of Twitter’s OAuth for client apps and Using Jersey client OAuth support with Smugmug to achieve that.
Lets get started!
- Create a Maven project as:
mvn -DarchetypeVersion=1.0 -DgroupId=org.glassfish.samples -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0-SNAPSHOT -DarchetypeGroupId=org.apache.maven.archetypes -Dpackage=org.glassfish.samples.twitter -DartifactId=twitter
- Update the generated "pom.xml" with the following fragments:
<repositories> <repository> <id>glassfish-repository</id> <name>Java.net Repository for Glassfish</name> <url>http://download.java.net/maven/2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.1.3-SNAPSHOT</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.1.3-SNAPSHOT</version> </dependency> <dependency> <groupId>com.sun.jersey.oauth</groupId> <artifactId>oauth-signature</artifactId> <version>1.1.2-ea-SNAPSHOT</version> </dependency> <dependency> <groupId>com.sun.jersey.oauth</groupId> <artifactId>oauth-client</artifactId> <version>1.1.2-ea-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build>
The Jersey dependencies add the core Jersey libraries and OAuth functionality in Jersey.
- Register your app with Twitter – Register your application with Twitter by clicking on Register a new application >>. The complete list of registered applications can be seen at Applications using Twitter. Select "Client" as the app type, select "Yes, use Twitter for login" and leave the "Callback URL" empty. The registration gives you "consumer key" and "consumer secret". These are used to obtain temporary credentials (or request tokens) from Twitter.
- Obtain Twitter OAuth credentials – Each OAuth request is an HTTP request with "Authorization" header specifying the information by OAuth service provider. Jersey provides a OAuthClientFilter to add this header to the outbound client request. Twitter API Wiki explains the authentication as multiple step process for desktop applications. Each step involves sending some parameters to twitter and getting a result back and the intent of each method/request is clearly explained in Understanding the guts of Twitter’s OAuth for client apps. In our case, each request is created by using Jersey Client API and attaching OAuthClientFilter and is explained next.
- Request temporary credentials, a.k.a request token, from Twitter using oauth/request_token.
- In "App.java", create an instance of Jersey client in the constructor and attach a LoggingFilter to dump inbound/outbound messages as:
public App() { // Create a Jersey client client = Client.create(); client.addFilter(new LoggingFilter()); }
- Request temporary credentials by adding the following method:
public void getRequestToken() { client.removeAllFilters(); // Create a resource to be used to make Twitter API calls WebResource resource = client.resource(REQUEST_TOKEN_URL); // Set the OAuth parameters OAuthSecrets secrets = new OAuthSecrets().consumerSecret(CONSUMER_SECRET); OAuthParameters params = new OAuthParameters().consumerKey(CONSUMER_KEY). signatureMethod("HMAC-SHA1").version("1.0"); // Create the OAuth client filter OAuthClientFilter oauthFilter = new OAuthClientFilter(client.getProviders(), params, secrets); // Add the filter to the resource resource.addFilter(oauthFilter); // make the request and print out the result System.out.println(resource.get(String.class)); }
Note, "OAuthClientFilter" is used to populate the "Authorization" header instead of handcrafting it. The REQUEST_TOKEN_URL is "http://twitter.com/oauth/request_token", CONSUMER_SECRET and CONSUMER_KEY are the values obtained from registering your application.
- Edit "AppTest.java" and change "testApp" method such that it looks like:
public void testApp() { App app = new App(); app.getRequestToken(); }
- Obtain the temporary credentials by running this application as:
mvn test
and see an output as:
oauth_token=REQUEST_OAUTH_TOKEN&oauth_token_secret=REQUEST_OAUTH_TOKEN_SECRET&oauth_callback_confirmed=true
REQUEST_OAUTH_TOKEN, a temporary token, is used to authorize on twitter.com.
- In "App.java", create an instance of Jersey client in the constructor and attach a LoggingFilter to dump inbound/outbound messages as:
- Authorize the user and obtain PIN
- Go to "https://twitter.com/oauth/authorize?oauth_token=REQUEST_OAUTH_TOKEN" in a browser window.
- If not already logged in, enter your twitter credentials and click "Allow".
- Copy the PIN.
- Request permanent credentials, a.k.a access token, from Twitter using oauth/access_token.
- Request permanent credentials by adding the following method in "App.java"
public void getAccessToken() { client.removeAllFilters(); // Set the OAuth parameters OAuthSecrets secrets = new OAuthSecrets().consumerSecret(CONSUMER_SECRET); OAuthParameters params = new OAuthParameters().consumerKey(CONSUMER_KEY). signatureMethod("HMAC-SHA1"). version("1.0"). token(REQUEST_OAUTH_TOKEN). verifier(PIN); // Create the OAuth client filter OAuthClientFilter oauthFilter = new OAuthClientFilter(client.getProviders(), params, secrets); // Create a resource to be used to make Twitter API calls WebResource resource = client.resource(ACCESS_TOKEN_URL); // Add the filter to the resource resource.addFilter(oauthFilter); // make the request and print out the result System.out.println(resource.get(String.class)); }
REQUEST_OAUTH_TOKEN is the temporary token obtained earlier, ACCESS_TOKEN_URL is "https://twitter.com/oauth/access_token".
Notice, REQUEST_OAUTH_TOKEN and PIN are now added to the OAuthClientFilter.
- Invoke this method by editing "AppTest.java" as:
public void testApp() { App app = new App(); // app.getRequestToken(); app.getAccessToken(); }
- Obtain the permanent credentials by running this application as:
mvn test
and see an output as:
oauth_token=ACCESS_OAUTH_TOKEN&oauth_token_secret=ACCESS_OAUTH_TOKEN_SECRET&user_id=USER_ID&screen_name=USER_NAME
ACCESS_OAUTH_TOKEN is the authorized token that can be used for making any future requests, USER_ID and USER_NAME are identifiers for the user who signed in on twitter.com.
- Request permanent credentials by adding the following method in "App.java"
- Request temporary credentials, a.k.a request token, from Twitter using oauth/request_token.
- Get the last 20 status messages for the user from Twitter
- Add the following method in "App.java:
public void getUserTimeline() { client.removeAllFilters(); // Set the OAuth parameters OAuthSecrets secrets = new OAuthSecrets().consumerSecret(CONSUMER_SECRET); OAuthParameters params = new OAuthParameters().consumerKey(CONSUMER_KEY). signatureMethod("HMAC-SHA1"). version("1.0"). token(ACCESS_OAUTH_TOKEN); // Create the OAuth client filter OAuthClientFilter oauthFilter = new OAuthClientFilter(client.getProviders(), params, secrets); // Create a resource to be used to make Twitter API calls WebResource resource = client.resource(USER_TIMELINE_URL); // Add the filter to the resource resource.addFilter(oauthFilter);
// Parse the JSON array JSONArray jsonArray = resource.get(JSONArray.class); List<String> statuses = new ArrayList<String>(); try { for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = (JSONObject) jsonArray.get(i); StringBuilder builder = new StringBuilder(); builder.append(jsonObject.getString("text")). append(jsonObject.getString("created_at")); statuses.add(builder.toString()); } } catch (JSONException ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } }USER_TIMELINE_URL is "http://api.twitter.com/1/statuses/user_timeline.json". The "getTimelineElements" method can be updated to pick other elements from the return JSON object. The complete JSON schema for the response is described here.
- Edit "AppTest.java" as:
public void testApp() { App app = new App(); // app.getRequestToken(); // app.getAccessToken(); app.getUserTimeline(); }
- Finally get the last 20 status updates by giving the command:
mvn test
and see the output similar to:
Running org.glassfish.samples.twitter.AppTest [Developing OSGi-Enabled Java EE Applications- http://bit.ly/aOim34 (via @JavaOneConf) #javaone10Wed Aug 04 23:53:13 +0000 2010, Google Wave goes bye bye (via @google:)Update on Google Wave http://bit.ly/bIoDWAWed Aug 04 21:16:07 +0000 2010, @gdaniels Yeah, I expected #wave to bye bye as well, but this is fairly quick!Wed Aug 04 21:15:41 +0000 2010,
- Add the following method in "App.java:
And that’s it!
This Tip Of The Day explained how to use Jersey to retrieve last 20 status messages that a user posted on twitter. Here are some other future possible additions:
- POST status update
- Integrate Search API using OAuth (is it possible ?)
- Integrate Streaming API (need more investigation)
- Create a web-base client that automatically redirects the user from application to twitter.com and then back to the application.
Jersey and OAuth wiki provides more details about how to use OAuth with Jersey.
Technorati: totd jaxrs jersey restful webservices oauth twitter glassfish
Related posts:- TOTD #57: Jersey Client API – simple and easy to use
- TOTD #58: Jersey and GlassFish – how to process POST requests ?
- TOTD #56: Simple RESTful Web service using Jersey and Embeddable GlassFish – Text and JSON output
- TOTD #8: Generating JSON using JAXB annotations in Jersey
- TOTD #59: How to add Twitter feeds to blogs.sun.com ? + Other Twitter Tools