Dear Java, I hate you – accessing the Facebook API with Java


So, I’m pretty open minded when it comes to technology, especially diving head-first into programming languages but for some reason I’ve always had a personal vendetta and hatred towards Java even though I’ve never touched the language. I think it comes from my line-of-work; clients ringing up complaining that this Java plugin isn’t working or their browser crashes because of a Java applet. Anyhow, vendettas aside I decided to dive in – fueled with wine gums and semi-naked…

The main reason for playing around with Java was because it’s an upcoming unit in the honours degree I’m studying but also the DLNA server I use, PS3 Media Server (PMS), for streaming movies to my PS3 implemented third-party plugin support – hello!

My aim was to allow users to automatically publish what they are watching/playing on their PlayStation3 via Facebook by creating a PMS plugin.

My first poision of a Java Facebook client was facebook-java-api as it seems to be the most stable, documented and actively developed. After playing around for over a day I couldn’t get a working application, the examples I found around the ‘net were all out of date – functions had been depreciated, Facebook changed it’s API and all sorts of headaches.

38 (thirty-eight!) imports later I had a working application and when I played a movie on my PlayStation it was published on my Facebook wall.

As I dove into the Facebook Java API more and more I decided I didn’t like it. It was crude, heavy, un-logical – something just wasn’t right. For example to simply get a list of friends I had to write 25-or-so lines of code, create a SECOND Facebook object but this time using the Jaxb client which, guess what, equaled more imports to handle Jaxb.

My bitching aside, I looked around a little more and came across RestFB. RestFB’s goals? Simple:

  • Minimal public API
  • Maximal extensibility
  • Robustness in the face of frequent Facebook API changes
  • Simple metadata-driven configuration
  • A single dependency, Apache Log4j

Exactly what I’m looking for, perfect! I found RestFB a dream to work with putting aside my diminishing Java hatred. To get to the point below is some code to retrieve the user ID of the currently logged in user.

// I've removed the imports to keep the size down

public class Main {
	// define our strings
	private static final String FACEBOOK_API_KEY = "xxxxx";
	private static final String FACEBOOK_APPLICATION_SECRET = "xxxxx";
	private FacebookClient facebookClient;
	private String facebookAuthToken = null;
	private String facebookSessionKey = null;

	public static void main(String[] args) throws FacebookException {
		facebookClient = new DefaultFacebookClient(FACEBOOK_API_KEY, FACEBOOK_APPLICATION_SECRET);

		// I always call facebookAuthorise
		// First time users would click a button that calls facebookConnect() first to grab the session key.
		facebookAuthorise();
	}

	private void facebookConnect() throws FacebookException {
		// auth.createToken returns a string
		// http://wiki.developers.facebook.com/index.php/Auth.createToken
		facebookAuthToken = facebookClient.execute("auth.createToken", String.class);
		String url = "http://www.facebook.com/login.php"
			+ "?api_key=" + FACEBOOK_API_KEY
			+ "&fbconnect=true" + "&v=1.0"
			+ "&connect_display=page" + "&session_key_only=true"
			+ "&req_perms=read_stream,publish_stream,offline_access"
			+ "&auth_token=" + facebookAuthToken;

		// Here we launch a browser with the above URL so the user can login to Facebook, grant our requested permissions and send our token for pickup later
		if (Desktop.isDesktopSupported()) {
			Desktop desktop = Desktop.getDesktop();

			if (desktop.isSupported(Desktop.Action.BROWSE)) {
				try {
					desktop.browse(new URI(url));
				}
				catch(IOException ioe) {
					ioe.printStackTrace();
				}
				catch(URISyntaxException use) {
					use.printStackTrace();
				}
			}
		}
	}

	private void facebookAuthorise() throws FacebookException {
		// I saved my session key to a .properties file for future use so the user doesn't keep have to authorising my app!
		// auth.getSession returns JSON so we need to decode it just to grab the session key
		// http://wiki.developers.facebook.com/index.php/Auth.getSession
		// Here we pickup the session key and define the authToken we used above in facebookConnect()
		JSONObject json = new JSONObject(facebookClient.execute("auth.getSession", String.class, Parameter.with("auth_token", facebookAuthToken)));
		facebookSessionKey = json.getString("session_key");

		// An example call, you can literally use anything from the REST API
		Long uid = facebookClient.execute("users.getLoggedInUser", facebookSessionKey, Long.class);
		System.out.println("FB User ID: " + uid);
	}
}

So, excluding the methods to get a session we managed to use one line of code, simples!

I still hate Java; it complains all the time, it needs dependency after dependency and it seems a little restrictive (like a women). I guess I’ll have to learn to get along with it. AS for the plugin, I’m still developing it and hope to publish it to the PMS community ASAP :)

Share

Related posts:

  1. Accessing Facebook within Unity

29 Responses to “Dear Java, I hate you – accessing the Facebook API with Java”

  1. Traroth  on April 8th, 2010

    I don’t really understand here what’s the matter with Java.

    You seem to have a problem with a Facebook API, but that’s third-party code…

    Reply

    • Paul Price  on April 8th, 2010

      Traroth, you’re right. I tried to keep this post mostly Facebook API orientated to keep away the Java fan boys because I know they’re brutal – heh.

      I think, as I mentioned, the reason I dislike Java is from end-user experience rather then development. I’ve never, ever touched Java before and coming from a PHP background I just found things to be a little crude. For example, adding an import to handle most basic things such as Arrays – I can see this is a benefit in some ways as there’s no point loading the lib into memory if you’re not going to use it.

      Anyhow, I guess it’s a learning curve and the more I use it the more I’m liking it so we’ll see.. ;)

      Reply

      • Traroth  on April 9th, 2010

        Hi Paul,

        Yeah, if by end-user experience, you mean “applets”, even if I could be considered as a “Java fan-boy”, I’m ok to say it’s simply awful (at least for the century long loading times), but with Swing, it’s possible to make really great GUIs. Check out the new default look&feel, Nimbus, and the skinnable Synth look&feel…

        Reply

        • funny_with_java  on October 1st, 2010

          I am tired of people bringing up applets. NO ONE uses them and NO ONE likes them. They were cool in 1997 because it was the only way to have any sort of dynamic app in a browser. I hate it when people bring this old shitty API up that NO ONE uses anymore.

          Reply

      • max  on March 31st, 2011

        i think its more of the fb api problem than java itself..lol,if u r from php background(just a scripting lang),u still need to know a powerful system level programming language like .net,java or python.u simply cant hate java for another api mistake .:-)

        Reply

  2. Hass  on April 9th, 2010

    Hey Paul
    First of all, thank u so much for this info.
    And, you’re right about “the examples I found around the ‘net were all out of date – functions had been depreciated”…
    im having problem with Java too but i need to get it over it since i need to get my project done..

    here are my question to you rdg your codes
    1. the FacebookClient : is that a class or from the API itself coz in the API, it has FacebookJsonRestClient, FacebookJaxbRestClient and FacebookXMLRestClient?
    2. the DefaultFacebookClient : can you explain abt this too.

    do need your help to survive Java ;)
    Thank you again

    Reply

    • Paul Price  on April 9th, 2010

      Hey Hass, I feel your pain! It seems ever since Facebook dropped official support for their Java API it’s been downhill.

      The code examples use RestFB (http://restfb.com) which is a third-party library, just like Facebook-Java-API but I found it easier to use.

      I’d recommend visiting the RestFB website and just having a little play with the code, it really is simple and in my opinion wipes the floor with Facebook-Java-API.

      I’d be glad to help! :D

      Reply

  3. Traroth  on April 14th, 2010

    I tried your code, and instead of the Facebook login page (for the browser part), I get a Facebook page with “An invalid next parameter was specified.” and an com.restfb.FacebookResponseStatusException saying “Received Facebook error response (code 100): Invalid parameter”. Do you have any clue?

    Reply

    • Paul Price  on April 16th, 2010

      Hi Traroth, usually “Invalid parameter” means that the you haven’t created an Auth Token via auth.createToken and passed it in the login URL (&auth_token) – could you share your code and I’ll take a look for you…

      Reply

      • Traroth  on April 16th, 2010

        Ok, here is my code. It’s actually only a dummy app, just to see how things work. I slightly modified yours:

        public final static void main(String [] args) {
        String sessionKey = null;
        FacebookClient facebookClient = new DefaultFacebookClient(MY_API_KEY, MY_SECRET_KEY);
        String facebookAuthToken = null;
        try {
        facebookAuthToken = facebookClient.execute(“auth.createToken”, String.class);

        System.out.println(“facebookAuthToken : “+facebookAuthToken);

        if (FIRST) {
        String url = “http://www.facebook.com/login.php”
        + “?api_key=” + MY_API_KEY
        + “&fbconnect=true” + “&v=1.0″
        //+ “&return_session=true”
        + “&connect_display=page” + “&session_key_only=true”
        + “&req_perms=read_stream,publish_stream,offline_access”
        + “&auth_token=” + facebookAuthToken;
        System.out.println(“step 1″);
        if (Desktop.isDesktopSupported()) {
        Desktop desktop = Desktop.getDesktop();

        if (desktop.isSupported(Desktop.Action.BROWSE)) {
        try {
        desktop.browse(new URI(url));
        }
        catch(IOException ioe) {
        ioe.printStackTrace();
        }
        catch(URISyntaxException use) {
        use.printStackTrace();
        }
        }
        }
        System.out.println(“step 2″);
        JSONObject json = new JSONObject(facebookClient.execute(“auth.getSession”, String.class, Parameter.with(“auth_token”, facebookAuthToken)));
        System.out.println(“step 3″);
        sessionKey = json.getString(“session_key”);
        System.out.println(“sessionKey : “+sessionKey);
        } else {
        JSONObject json = new JSONObject(facebookClient.execute(“auth.getSession”, String.class, Parameter.with(“auth_token”, facebookAuthToken)));
        sessionKey = json.getString(“session_key”);
        Long uid = facebookClient.execute(“users.getLoggedInUser”, sessionKey, Long.class);
        System.out.println(“uid : “+uid);
        }
        } catch (FacebookResponseStatusException e) {
        System.err.println(“code : “+e.getErrorCode()+” message : “+e.getErrorMessage());
        e.printStackTrace();
        } catch (Exception e) {
        e.printStackTrace();
        }
        }

        static final public boolean FIRST = true;

        Reply

        • Traroth  on April 16th, 2010

          One more thing: my code is stopping a between step 2 and step 3, and I get the folowing stack:

          com.restfb.FacebookResponseStatusException: Received Facebook error response (code 100): Invalid parameter
          at com.restfb.DefaultFacebookClient.throwFacebookResponseStatusExceptionIfNecessary(DefaultFacebookClient.java:357)
          at com.restfb.DefaultFacebookClient.makeRequest(DefaultFacebookClient.java:320)
          at com.restfb.DefaultFacebookClient.execute(DefaultFacebookClient.java:188)
          at com.restfb.DefaultFacebookClient.execute(DefaultFacebookClient.java:178)
          at com.kizoa.facebook.FBTester.main(FBTester.java:54)

          Reply

        • Paul Price  on April 16th, 2010

          Hmmm, I think I found the problem. If you take a look after

          System.out.println(“step 2″);

          you pretty much request the infinitie session key straight away, not giving time for the user to login to Facebook and grant permissions to your application. For example, your application flow is as so;

          1. Request an AUTH TOKEN from Facebooks server
          2. Pass the AUTH TOKEN to /login.php and open in a browser for the user to login/request permissions manually and generate a SESSION KEY
          3. Straight away we attempt to get the SESSION KEY created from step 2 but because we haven’t gave the user enough time to login and generate a session key the Facebook server sends the “Invalid parameter” response.

          So, what we would need to change is just give time for a user to login to facebook. In my example I open the URL in the browser and then WAIT for the user to push a button which then triggers my auth.getSession()

          I hope this make sense! :-)

          Reply

          • Traroth  on April 19th, 2010

            Yeah, I did this in the meantime. I don’t get the exception anymore. But I still have the message on Facebook.

          • Traroth  on April 19th, 2010

            Actually I added the following line to my parameters :

            + “&next=http://www.facebook.com/connect/login_success.html”

            and now, it works.

          • Paul Price  on April 19th, 2010

            Glad you got it working. It’s strange that you have to include NEXT in the URI for it to work.

  4. Raibaz  on April 16th, 2010

    Hi, i’ve been struggling with the Facebook API to get a session key to use with RestFB all day, then i found your post and it saved my day…thnks a lot! :)

    Reply

  5. bruno  on May 3rd, 2010

    Cool tip ;)

    worked perfectly with me. But you tell me how do I get the AUTH_TOKEN user with the login and password it?

    Reply

    • Paul Price  on May 4th, 2010

      Hi Bruno, if I read your comment right you want to get the Facebook username after sending your AUTH_TOKEN but before you call auth.getSession? Unfortunately you can’t do this and you need to be authenticated..

      Reply

  6. Bruno Oliveira de Alcântara  on May 4th, 2010

    Yes, I understand I need to be logged in to facebook to post a photo, but I have some way to authenticate the user at all on facebook backend?

    Example:

    I get the login and password and submit to facebook and get the auth_token to configure my application and send the photo.

    In the API eg twitpic this is possible with just calling a method, but on facebook I need the user to allow my application facebook collect the data from it to post the photo. What I was wondering is if it is somehow easier for me to do this in the backend (background) with no views?

    Reply

    • Paul Price  on May 4th, 2010

      I don’t think there is. The user HAS to authorize your application for it to use it which involves them physically clicking “allow” on the authorize button – if you can do this transparently (in the background) then I believe Facebook has a huge security flaw…

      If you’re developing a Java web-app it’s probably wiser to use Facebook Connect; http://wiki.developers.facebook.com/index.php/Facebook_Connect

      Reply

  7. Bruno Oliveira de Alcântara  on May 4th, 2010

    Okay, thanks for the replies, actually I need to do is send in the same background, no web interface, or any view, because I get the image on my server that uses Java and I have to send it to my facebook through this server.

    Thank you for the posts so far, and congratulations on your tip restFB really all I have researched this is the best tip.

    Regards,

    Bruno.

    Reply

  8. Jagdeep  on September 17th, 2010

    This is a great link to start with the facebook apis.
    I want to ligin to a facebook and save the Wall/Home page as a image on my machine. I need to refresh the image every 5 mins so I dont need any windoe prompt.
    Someone pleas help.

    Reply

  9. maling  on November 12th, 2010

    Your code doesn;t work

    Reply

  10. saqs  on January 3rd, 2011

    Would be nice if U could update this ;)

    Reply

  11. guna  on April 7th, 2011

    Hi Paul

    Thank u so much for this info.

    here are my question to you rdg your codes
    1. is it possible getting friends facebook account?
    2. if we get friends list, is it possible to get friends phone number and email?

    do need your help to survive android
    Thank you again and regrards

    sekar

    Reply

  12. summu  on April 29th, 2011

    Hi Paul,

    Do u have any idea regarding this exception “Managing advertisements requires the extended permission ads_management”

    Reply

  13. Chetan6033  on July 11th, 2011

    i was able to connect to the fb by using the above code but i need to retrieve my friend’s(user’s on fb) comments. Is this possible by my application??

    Reply

  14. matthias  on November 6th, 2011

    Hello Paul,

    it seems that “facebookClient.execute” does not exist anymore in the latest version of the restfb library.
    How can I make the example working with the newest version of restfb ?

    Thanks very much in advance!

    BR,
    Matthias

    Reply

  15. Craig  on December 21st, 2011

    Great article Paul. Best example of doing this I have been able to find.

    Funnily enough, I did the same thing in C# in about 5 minutes, but Java on the other hand….phew, but like you I am about to take a Java course and was determined to do it this way.

    Reply


Leave a Reply