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!

  1. 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
  2. Update the generated "pom.xml" with the following fragments:
    glassfish-repository Java.net Repository for Glassfish http://download.java.net/maven/2/ junit junit 3.8.1 test com.sun.jersey jersey-client 1.1.2-ea-SNAPSHOT com.sun.jersey jersey-json 1.1.2-ea-SNAPSHOT com.sun.jersey.oauth oauth-signature 1.1.2-ea-SNAPSHOT com.sun.jersey.oauth oauth-client 1.1.2-ea-SNAPSHOT net.sf.json-lib json-lib 2.3 jdk15 org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.5 1.5
    The Jersey dependencies add the core Jersey libraries and OAuth functionality in Jersey. json-lib allows to nicely navigate the JSON tree using standard JSON APIs.
  3. 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.
  4. 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.
    1. Request temporary credentials, a.k.a request token, from Twitter using oauth/request_token.
      1. 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()); }
      2. 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.
      3. Edit "AppTest.java" and change "testApp" method such that it looks like: public void testApp() { App app = new App(); app.getRequestToken(); }
      4. 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.
    2. Authorize the user and obtain PIN
      1. Go to "https://twitter.com/oauth/authorize?oauth_token=REQUEST_OAUTH_TOKEN" in a browser window.
      2. If not already logged in, enter your twitter credentials and click "Allow".
      3. Copy the PIN.
    3. Request permanent credentials, a.k.a access token, from Twitter using oauth/access_token.
      1. 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.
      2. Invoke this method by editing "AppTest.java" as:
        public void testApp() { App app = new App(); // app.getRequestToken(); app.getAccessToken(); }
      3. 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.*
  5. Get the last 20 status messages for the user from Twitter
    1. 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); // make the request and print out the result String timeline = (String) resource.get(String.class); System.out.println(getTimelineElements(timeline)); } private String getTimelineElements(String timeline) { JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON(timeline); List statuses = new ArrayList(); for (int i = 0; i < jsonArray.size(); 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()); } return statuses.toString(); } 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.
    2. Edit "AppTest.java" as:
      public void testApp() { App app = new App(); // app.getRequestToken(); // app.getAccessToken(); app.getUserTimeline(); }
    3. Finally get the last 20 status updates by giving the command:

      mvn test

      and seeing 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,
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



Read More about [TOTD #143: Retrieve twitter user timeline using using Jersey and OAuth...