Developing the Facebook Music Explaura

In order to try to get a little more interest in the Music Explaura, I decided that I'd try making a Facebook app that uses some of the data available on Facebook to get you started with your exploration. Facebook would provide the UI and input, and the Search Inside the Music application built on Aura would provide the data. The live system would run on a grid/compute cloud that was developed as a research project inside Sun. I had hoped to pull in and accumulate some of the social data in order to help with the recommendations, but sadly that turned out to be against Facebook's terms of service. Still, when a user runs an app, I can get access to the user's "Favorite Music" in their profile, and I can get access to their friends and their friends' "Favorite Music". This was enough to go on.

After finding the Java API, it was mostly a matter of learning what you can and can't do with JavaScript inside the Facebook page. Facebook intercepts all traffic between the browser and your site (which gets around the cross-site scripting issue) and rewrites your JavaScript to make sure you're only doing things that are on the up-and-up. They call their JavaScript environment FBJS. Despite the frequent frustrations that I had while bumping my head against the frobbed code, I will give Facebook credit that they've taken a pretty hard problem (trusting third party code to run in your app) and created a workable solution. Facebook does allow AJAX calls (using its fairly easy to use wrappers), so I could include some level of interactivity.

For the interactivity, I needed some servlets that would provide answers to the queries I was running. We've been working on some web services for the music features, but I had some specific needs. In particular, there are certain things that need to be returned in a special format for Facebook to allow (for example, code for special Facebook markup tags needs to be frobbed by facebook before it gets back to the JavaScript running in the browser). So custom servlets it was.

The first thing I wanted to do was generate a tag cloud that represented the user's taste. This would involve getting the user's favorite music, finding band names in it, then pulling out and combining the most distinctive tags of those bands. The communication process here is kind of interesting. First, the user loads the Facebook app. Facebook hits our web server(s) and requests the "canvas" page to display the app. As the UI is displayed to the user, an AJAX call is made to fetch the tag cloud. So the client sends the AJAX to Facebook and Facebook forwards it to us. To answer the request, we first send a query to facebook asking for the "Favorite Music" in their profile (and some other data that we'll short-term cache for later use). We get a String back, then we can parse that and search our data store for matching band names. We get the matching bands and their associated distinctive tags, combine their weights, and return a JSON object with term/weight pairs back to the Facebook AJAX proxy. Facebook checks it over to make sure it is legit, and finally returns the JSON to the client. A bit of JavaScript then renders the tags and weights as a cloud and displays it to the user. Finally, a link is added below the tag cloud to load the cloud into the Steering interface in the Music Explaura.

I wanted to be able to display my tag cloud on my Profile, so next up was the "Add to Profile" button. I figured that when you click the button, Facebook would request the content of the profile box then insert it. Not so. The Add button (inserted with FBML that Facebook controls the rendering of) doesn't render unless there's already a field set in Facebook with the HTML for the profile box. I want the button to show up when the page loads, but it won't render it unless I've already filled in the data, and I can't fill in the data until the page loads! I needed to get Facebook to render the "Add to Profile" button after I fetched the user's cloud (and had a chance to post the profile markup to Facebook). Since Facebook will render markup in your AJAX results, I added a field to the JSON I return to build the cloud that contains the FBML necessary for creating an "Add to Profile" button. Then I just get that data in the client (now rendered by Facebook) and put it into a DIV for display. Hacky? Yes, but it works!

There were some other interesting issues as well. For example, the Facebook Java API (not actually maintained by Facebook) will return JSON objects for some things, but the format isn't specified. Some calls will return a JSONObject and some a JSONArray, depending on the data returned at runtime. This isn't very helpful when you're trying to cast to the correct type to get at your data. I was also a little surprised to see that Facebook doesn't have any more of a developer "sandbox". I'd love to see something that lets me (or more than one codeveloper at a time) test a dev version of the app without us each having to create a new application listing. It'd also be great to be able to create ad-hoc users (basically profiles that are only accessible by my app) for testing. This would let me have a few users with different bands and compare their tastes without having to create fake Facebook accounts. As it was, I generally tested by changing my own favorite music.

This has turned into a fairly long winded post, so I'll leave it at that for now. Try out the Facebook Music Explaura and see what you think!


Post a Comment:
  • HTML Syntax: NOT allowed

Jeff Alexander is a member of the Information Retrieval and Machine Learning group in Oracle Labs.


« July 2016