|
||||||||||
the first part, I covered a very high-level, idiot-guide to getting started with writing a Facebook app in java. This part will cover the details of how to architect your own code for basic Facebook authentication, and include code samples you can use to get up and running more quickly. It will also explain in more detail precisely how Facebook’s servers interact with your code, and what you can expect (and what their servers expect of you!). NB: if the quoted source code is unreadable because it disappears
off the edge of the screen, select it and copy/paste (or view source of
the page to see it). The most useful stuff is put together into one
class you can download here - source code for FacebookLoginServlet.java. iFrames vs FBMLFacebook apps can be implemented one of two ways, iframes, or FBML.
*** - NB: actually, the way Facebook have designed their system, you need your own webserver anyway, they won’t let you make a Facebook App without one. So, although in theory FBML would be a faster and simpler way to get a basic app up and running, in practice, it doesn’t save you any time or effort at all. Mostly, I’ll be assuming you want to write your app using iframes instead of FBML. FBML is great, and for some parts of your app you will want to use it, but the fact you can’t debug it makes life extremely difficult. If you can get all your code working with iframes first, then it will be relatively easy to switch some bits to FBML when the time comes. It’s much harder to try things the other way around. Facebook Apps: Detailed explanationWhat happens when a Facebook user tries to use your Facebook App?
…but what does this look like to the user?
So, the first thing to understand, especially if you’ve used FB a lot yourself, is that there’s a lot more going on behind the scenes than appears to the user. This will become especially clear when you make a mistake and start trying to debug your app. AuthenticationThere are two “modes” in which you can create a webpage to display as part of your app:
In the default mode, i.e. if you do nothing special, you have NO ACCESS to any of Facebook’s data. You cannot find out ANYTHING about the Facebook user - you can’t find their name, you can’t find their friends, you can’t post items on their Wall, nothing. In the authenticated mode, you have full access to:
Authenticating in javaFB provides you with a java class, FB has partially documented the way that authentication works, but
there are lots of missing details. In particular, there is no
documentation on how to use the In brief, you need to:
Authenticating your servletsNow, you may notice a problem with the above sequence of events. Traditionally, when writing a J2EE app, you have multiple servlets, one for each “page” of your website - but in order to authenticate, the servlet MUST redirect the user back to Facebook, which will then ALWAYS send the user back to your Callback URL page, which means they will be sent to the “wrong” page. Note: just because you redirect the user to Facebook’s login page doesn’t actually mean the user SEES a login page - if they are already logged-in to Facebook, FB just automatically sends them straight back to your site (but this time, it gives your site the login information, which doesn’t otherwise do!) So, effectively, Facebook ONLY ALLOWS ONE SERVLET to authenticate with Facebook - whichever servlet you gave the address of when you filled in the “Callback URL” field when creating your app on Facebook’s Developer page. That’s not a big problem, though. J2EE servlets have the Session
object, automatically maintained by your J2EE container, that will take
care of this: if you ever want the user to be authenticated when using
your app, just make the Callback URL page force the user to login once
(as noted above, if already logged in to FB, the user won’t be asked to
login again, but you still have to force FB to make the check), and
then store the authenticated instance of protected void doGet(HttpServletRequest request, HttpServletResponse response) { ... FacebookRestClient authenticatedClient = new FacebookRestClient( apiKey, secret ); authenticatedClient.setIsDesktop(false); request.getSession().setAttribute( "auth", authenticatedClient ); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) { FacebookRestClient authenticatedClient = (FacebookRestClient) request.getSession().getAttribute( "auth" ); ... }
Old sessionsYou also have to handle the situation where a player leaves their
web browser open for a long time, long enough that the J2EE Session
timesout and/or the Facebook authentication timesout, and then they hit
“refresh”. If you’re merely starting every doGet / doPost method in
your servlets with the For this, I currently just surround all my doGet’s with a big try/catch: protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { ... } catch( FacebookException e ) { logger.error( "Facebook exception, probably due to timeout on authentication; sending error page to user", e ); String loginPage = "http://www.facebook.com/login.php?api_key="+apiKey+"&v=1.0"; response.getWriter().println( "<h1>Error: Couldn't talk to Facebook</h1>" ); response.getWriter().println( "Your Facebook session has probably timed out" ); response.getWriter().println( "Please <a ref=\""+loginPage+"\">click here</a> to login again"); } } Testing…And, again, time to finish off with some basic tests, so you can be
sure all this stuff above is working. For my basic testing, I created a
servlet that would fetch the user-id of the currently-logged-in
Facebook user, and ask Facebook for a list of all their friends’ names.
This is the same basic test that Facebook uses in their one and only
piece of sample java code in their API. public class TestFaceBookServlet extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws IOException, FacebookException { FacebookRestClient client = (FacebookRestClient) request.getSession().getAttribute("facebookClient"); client.setDebug(true); logger.info( "Fetching friends for user to prove that our auth to FB's server worked OK ... should see a list of \"uid\"s now, with NO java-exceptions!"); Document d = client.friends_get(); FacebookRestClient.printDom(d, " "); } } ConclusionBy now you should have:
In the next part, I’ll probably stop to cover likely problems and gotchas you’ll run into, since there’s quite a few you’re likely to hit by this point. If there’s anything else you’d like to see covered, add a comment at the bottom and I’ll try to fit it in as well. |
||||||||||
© Lynne Grewe |