Orkut Application Platform

Introduction to the orkut Client Library

Bruno Oliveira - Developer Relations
December 2010

The orkut Client Library allows you to access orkut's data from an external application (as opposed to apps that run inside orkut). This article will give you a short introduction on how to use this library. For general information about the library, please check this page.

Contents:

Conventions

In order to save space and keep the code samples clean, we will use a few utility functions that encapsulate some common functionality that we will need a lot. In all of our code, we will assume the following functions are available to us:

  • say(s) - prints the string s to the console;
  • readline() - reads a line from the console and returns it, without a trailing newline character
  • nullsafe(s) - returns the string s if it's not null; returns the string "null" if s is null.

Here is a possible implementation for the utility functions:

public static void say(String s) { System.err.println(s); }

public static String readline() throws Exception {
   java.io.BufferedReader br = new java.io.BufferedReader(
                new java.io.InputStreamReader(System.in));
   return br.readLine();
}

public static String nullsafe(String s) { return (s == null) ? "null" : s; }

Environment Setup

Start out by downloading the client library from here. The package we will use is the binary only package, named orkut-os-client-bin-version.zip. This release is easier to use, since it consists of a single JAR file that you can add to your project in any suitable development environment.

After downloading the file, unzip it to your directory of choice and make a note of where it is. Then, start up your favorite development environment, start a new Java project, and add the orkut-os-client-bin-version.jar file to it. The precise way in which this can be accomplished varies from environment to environment, but it should be a simple operation.

In this article, we will take a rudimentary approach and compile the application directly from the command line.

For the purposes of this article, we'll assume you unzipped the client library binary package to /opt/orkut-os-client. And we'll assume you want to write an application, let's call it MyApp, in ~/src/myapp. So this is what we should have (approximately):

[/]$ cd /opt/orkut-os-client
[/opt/orkut-os-client-2.0.01]$ ls
README  orkut-os-client-bin-2.0.01.jar  samples/  doc/
[/opt/orkut-os-client-2.0.01]$ cd ~/src/myapp
[~/src/myapp]$ ls
MyApp.java
[~/src/myapp]$ _

Consumer Key and Secret

Since orkut uses OAuth for authentication, you will need to have a valid consumer key and consumer secret in order to use this library. Yes, this includes testing and debugging.

Be aware that in order to obtain credentials, you must be the administrator of a domain on the Internet, since your credentials will be tied to that domain.

So, if you have administrative access to your domain and don't already have these credentials, please visit visit this page to request your credentials.

For the purposes of this article, let's say your consumer key is "sampleapp.mydomain.com" and your consumer secret is "a1b2c3d4e5f6g7h8".

A Few Words About Authentication

If you are familiar with OAuth and three-legged authentication, feel free to skip this section.

OAuth is a mechanism designed so that an application (called the "consumer") can access a service's data on behalf of a user without having to handle the user's credentials directly. The user's login information travels directly from the user to the service, without making a stop at the application. Once on the server, the user will authorize the requesting application to access his information (or perhaps only parts of it), and this authorization will be reflected in an access token that the application will receive. This is the token that the application must present to the server in every request in order to be granted access privileges.

The orkut client library encapsulates the functionality necessary to authenticate to the orkut servers via OAuth.

Using OAuth means that you don't have to (in fact, must not) read the user's login and password yourself. Instead, this is the authentication process(*):

  • Your application connects to orkut and gives its credentials (consumer key and secret), and asks for an authentication URL
  • orkut gives you the authentication URL
  • Using a browser, your user must navigate to the URL
  • That URL is an orkut URL where the user will type is username and password
  • After authentication, orkut will redirect the browser to a page you indicated, supplying a verification code to it
  • You must take this verification code and reply back to orkut to finish the process. From then on, you are authenticated and authorized to perform transactions on behalf of the user who logged in.

(*) Note: this explanation deliberately summarizes or completely bypasses some technical OAuth concepts such as access tokens, request tokens, etc. The idea is to keep the explanation simple, since all the OAuth functionality is encapsulated by the library and you only need to know the basics so that you understand how to interact with the library.

Naturally, it's very important that you take this ritual (known as "the OAuth dance") into account when desigining your application.

Getting Started

Enough theory, let's get down to writing actual code. So, go to ~/src/myapp and create a file there named MyApp.java using your favorite editor or development environment.

Let's start simple. The main object necessary to access orkut is an OrkutAdapter. That's an abstract class that defines the interface, while the DefaultOrkutAdapter is the concrete class that provides the implementation. Therefore, the type you should use is OrkutAdapter, but the actual class you should instantiate is DefaultOrkutAdapter. You have to pass it your consumer key, your consumer secret and a callback URL:

import com.google.orkut.client.api.OrkutAdapter;
import com.google.orkut.client.api.DefaultOrkutAdapter;

public class MyApp {
   public void run() throws Exception {
      say("Setting up adapter...");
      OrkutAdapter orkad = new DefaultOrkutAdapter(
              "sampleapp.mydomain.com",                     // consumer key
              "a1b2c3d4e5f6g7h8",                           // consumer secret
              "https://sampleapp.mydomain.com/callback.php", // callback URL
              true,                                         // is production?
              null      // debug listener
      );
         
      say("End!");
   }

   public static void main(String[] args) {
      try {
         (new MyApp()).run();
      }
      catch (Exception e) {
         say("*** Houston, we have a problem.");
         e.printStackTrace();
      }
   }
}

So, this creates an OrkutAdapter that you can subsequently use to access orkut. The callback URL is the URL that the user will be redirected to after authenticating and authorizing your application to access his orkut data (this is part of the "OAuth dance").

The fourth parameter, for which we are supplying true, indicates whether or not we are running in the production environment. Setting this to false will direct the requests to the orkut sandbox (sandbox.orkut.com), while setting this to true will direct requests orkut's production environment (www.orkut.com).

So far, the application does nothing. In fact, it does not even connect to the orkut servers at all: it just sets up the adapter. However, this is a good time to compile the application and make sure that it does what it's supposed to: nothing.

Using the command line, here is how we would compile and run this application. You should be able to replicate this easily in your development environment, if you are using one:

[~/src/myapp]$ export CLASSPATH=".:/opt/orkut-os-client-2.0.01"
[~/src/myapp]$ javac MyApp.java
[~/src/myapp]$ java MyApp.java
Setting up adapter...
End!
[~/src/myapp]$ _

If you got compile errors or if for some other reason the application fails to run, please revise the library setup steps to make sure you installed it correctly. Also, please make sure you are using a compatible JDK (currently, 1.5 or 1.6).

Now, it would be nice if we could see the library's debug messages. So let's do that by passing the OrkutAdapter a debug listener, which will get called every time the library wants to print a debug message.

import com.google.orkut.client.api.OrkutAdapter;
import com.google.orkut.client.api.OrkutAdapterDebugListener;

public class MyApp implements OrkutAdapterDebugListener {
   public void run() throws Exception {
      say("Setting up adapter...");
      OrkutAdapter orkad = new DefaultOrkutAdapter(
         "sampleapp.mydomain.com",                     // consumer key
         "a1b2c3d4e5f6g7h8",                           // consumer secret
         "http://sampleapp.mydomain.com/callback.php", // callback URL
         true,                                         // is production?
         this                                          // debug listener
      );

      // TODO

      say("End!");
   }

   public void printOrkutAdapterMessage(String s) {
      say(s);
   }
   
   public static void main(String[] args) {
      try {
         (new MyApp()).run();
      }
      catch (Exception e) {
         say("*** Houston, we have a problem.");
         e.printStackTrace();
      }
   }
}

From this point on, we will only show you the code that you have to add to the main function, instead of showing you the whole code every time. The new code should go where the "TODO" comment is in the listing above.

Note about imports: As we write the code, we will reference other classes that we haven't added an import for in the above code. As you add a reference to each class, please remember to also add the corresponding import to the top of the file. We won't mention each fully classified class name for brevity, but in the end of this article, we will present the full source code for our sample, so you can get the correct import's from there.

Authenticating

Remember the "OAuth dance"? So, it's time to go to the dance floor. The first step in the dance is asking orkut for the URL where we should send the user to get the process started. This is really straightforward:

String authURL = orkad.requestAuthURL();

Now, here is where it gets tricky. You have to make the user visit this URL with a browser. How you do this is up to you! If you are writing a desktop application, you could launch the system's default web browser. If what you are writing is a web application, your job is even easier: just redirect the user to that URL (your web application development environment should provide you information on how to do that -- and it shouldn't be too hard to find, since this is a really basic operation).

Since this is just a sample application and we want to keep things simple, we will use the laziest method on the planet, which is just to tell the user to open up a browser and visit the URL. Naturally, no self-respecting application would do that, but we're just trying to show how the library works, not giving advice on application design!

So, let's be lazy:

say("Hey, user, please open your browser and visit this URL:");
say(authURL);

Now what? Well, when the user visits that URL, what she will see is the orkut login page. She can feel safe typing her username and password because that's an official Google page (https://www.google.com/...). As soon as she does that, her browser will be directed to https://sampleapp.mydomain.com/callback.php, our callback URL.

However, that's not all. The actual URL will be something like:

https://sampleapp.mydomain.com/callback.php?oauth_verifier=Ffj238lnc32m

The verifier argument is an arbitrary code sent by the server, which you must feed back into the library in order to finish the authentication process.

In our very simple sample application, we'll just continue to be lazy and ask the user to get it from the URL manually. We've actually set up a page for testing purposes that just prints that parameter for easy copy-and-paste. We hosted that on the orkut-os-client-test.appspot.com domain (using Google App Engine), so for testing purposes you can use the following callback URL, if you prefer (change the orkad initialization code to the version shown below to use this page):

OrkutAdapter orkad = new DefaultOrkutAdapter(
  "sampleapp.mydomain.com",                     // consumer key
  "a1b2c3d4e5f6g7h8",                           // consumer secret
  "https://orkut-os-client-test.appspot.com/debugcallback"
  true,                                         // is production?
  this      // debug listener
);

Again, any method that requires the user to copy-and-paste the verifier code would probably be unacceptable in a self-respecting production application!

So here we go:

say("Hey, user, please open your browser and visit this URL:");
say(authURL);


say("Okay, now see the URL you were redirected to?");
say("it has a 'verifier' parameter embedded in it.");
say("What is that code? Please type it here:");
String verifier = readline();

Okay, after we put the user through all this misery, the last thing we have to do is feed this verifier code back into the library. This is the last step in the dance:

orkad.authenticate(verifier);

say("Authenticated! Our access pass is: " + 
                orkad.getAccessPass());

Done! So what's this "access pass" business? Well, this is a string that you can save for later use, instead of making the user go through the whole process again. Instead, you just call orkad.setAccessPass(accessPass), rather than calling requestAuthURL() and autheticate(). Notice that this will fail if your access has expired.

Transactions and Batches

Each orkut request made by the client library is called a transaction. Examples of transactions are: getting the user's profile, getting the user's friends, posting a scrap, etc.

Server requests are costly operations. There is considerable delay involved in sending out the request data, waiting for the server to process it and receiving the reply. If you have experience with web programming, you already know this: ten separate requests of 10kB each take considerably longer to complete than a single 100kB request.

Therefore, in order to make communication more efficient, the client library allows you to group transactions into batches. You can only send requests in the form of batches. Naturally, you can send a batch consisting of a single request, but you should, as much as possible, try to batch your requests together.

The different types of requests are represented by the request classes in the library (all in the com.google.api.orkut.client.api namespace:

  • BirthdayNotificationTx
  • CreateAlbumTx
  • DeleteAlbumTx
  • DeletePhotoTx
  • FriendRequestTx
  • GetActivitiesTx
  • GetAlbumsTx
  • GetFriendTx
  • GetPhotoCommentsTx
  • GetPhotosTx
  • GetProfileTx
  • GetScrapsTx
  • GetVideosTx
  • PendingFriendRequestTx
  • PostActivityTx
  • UpdateAlbumShareTx
  • UpdateAlbumTx
  • UpdatePhotoTx
  • UpdateProfileTx
  • UploadPhotoTx
  • WritePhotoCommentsTx
  • WriteScrapTx

To create each transaction, you must use the corresponding transaction factory. For example, to create a GetProfileTx, you must call the getSelfProfile() method of a ProfileTxFactory. We will see how to do that in a bit.

Submitting a Transaction Batch

Let's finish up our code by adding some example functionality: it will print the user's name and a list of his friends. So we start by creating a GetProfileTx from the profile transaction factory that our adapter makes available through the getProfileTF() member function.

GetProfileTx profile = orkad.getProfileTF().getSelfProfile();

Let's also create a GetFriendTx by using the friend transaction factory provided by our adapter:

GetFriendTx friends = orkad.getFriendTF().getSelfFriends();
friends.setCount(20); // get up to 20 friends

Now that we have the transactions, let's batch them up into a BatchTransaction.

BatchTransaction btx = orkad.newBatch();
btx.add(profile);
btx.add(friends);

Important: always create batch transactions using the newBatch() method from OrkutAdapter, not with something like new BatchTransaction(). This is because newBatch() already sets up several of the batch's parameters for you.

We're now ready to submit the transaction batch. In order to do this, all we have to do is call the submitBatch method of the adapter:

orkad.submitBatch(btx);

We should also check for errors:

if (profile.hasError() || friends.hasError()) {
   say("*** Error!");
   if (profile.hasError()) say(profile.getError());
   if (friends.hasError()) say(friends.getError());
   return;
}

We will cover error handling in more detail in the Errors and Captchas section.

Reading the Results

Now that we have sent the transaction batch, we have to parse the response. The submitBatch() function is synchronous, that is, when it returns, we'll already have the data back from the server (or else an error will have occurred).

So let's start by reading the user's profile and printing his name:

OrkutPerson person = profile.getProfile();
say("Hello, " + person.getDisplayName());

Now let's list the user's friends:

int i;
say("Listing " + String.valueOf(friends.getFriendsCount()) +
                        " friend(s):");
for (i = 0; i < friends.getFriendsCount(); i++) {
   OrkutPerson f = friends.getFriend(i);
   say(f.getDisplayName());
}

Notice that we actually only requested the library to return at most 20 friends, so if the user has more than 20 friends, only 20 (arbitrarily picked) will be returned.

If you want to retrieve more than 20, simply use the setCount method of the transaction like we did, but pass it a bigger number. You can also paginate through friends by reading a few of them at a time, but this is a more advanced topic, so if you would like to do that, please consult the library's source code or the automatically generated documentation at the project's page.

Watch out for Errors! (and captchas!)

One detail that we must mention, although we didn't cover in this article, is that any orkut transaction may result in errors, or may result in the platform demanding that the user solve a captcha. Please read Errors and Captchas for more information about how to handle this kind of occurrence.

Full Source Code

Here is the full source code that we have written in this sample, for your reference.

import com.google.orkut.client.api.OrkutAdapter;
import com.google.orkut.client.api.OrkutAdapterDebugListener;

import com.google.orkut.client.api.GetProfileTx;
import com.google.orkut.client.api.GetFriendTx;
import com.google.orkut.client.api.OrkutPerson;
import com.google.orkut.client.api.BatchTransaction;

public class MyApp implements OrkutAdapterDebugListener {
   public void run() throws Exception {
      say("Setting up adapter...");
      OrkutAdapter orkad = new DefaultOrkutAdapter(
              "sampleapp.mydomain.com",                     // consumer key
              "a1b2c3d4e5f6g7h8",                           // consumer secret
              "https://orkut-os-client-test.appspot.com/debugcallback",
              true,                                         // is production?
              this      // debug listener
      );

      String authURL = orkad.requestAuthURL();
      say("Hey, user, please open your browser and visit this URL:");
      say(authURL);

      say("Okay, now see the URL you were redirected to?");
      say("it has a 'verifier' parameter embedded in it.");
      say("What is that code? Please type it here:");
      String verifier = readline();
      
      orkad.authenticate(verifier);

      say("Authenticated! Our access pass is: " +
                      orkad.getAccessPass());

      GetProfileTx profile = orkad.getProfileTF().getSelfProfile();
      GetFriendTx friends = orkad.getFriendTF().getSelfFriends();
      friends.setCount(20); // get up to 20 friends

      BatchTransaction btx = orkad.newBatch();
      btx.add(profile);
      btx.add(friends);
      say("Fetching data...");
      orkad.submitBatch(btx);

      if (profile.hasError() || friends.hasError()) {
         say("*** Error!");
         if (profile.hasError()) say(profile.getError());
         if (friends.hasError()) say(friends.getError());
         return;
      }

      OrkutPerson person = profile.getProfile();
      say("Hello, " + person.getDisplayName());
      
      int i;
      say("You have " + String.valueOf(friends.getFriendsCount()) +
                              " friend(s):");
      for (i = 0; i < friends.getFriendsCount(); i++) {
         OrkutPerson f = friends.getFriend(i);
         say(f.getDisplayName());
      }

      say("End!");
   }


   public void printOrkutAdapterMessage(String s) {
      say(s);
   }
   
   public static void main(String[] args) {
      try {
         (new MyApp()).run();
      }
      catch (Exception e) {
         say("*** Houston, we have a problem.");
         e.printStackTrace();
      }
   }

   public static void say(String s) { System.err.println(s); }
   
   public static String readline() throws Exception {
      java.io.BufferedReader br = new java.io.BufferedReader(
                   new java.io.InputStreamReader(System.in));
      return br.readLine();
   }
   
   public static String nullsafe(String s) { return (s == null) ? "null" : s; }
}

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.