2. Getting Basic MySpace Data

In this chapter we’ll start with a very basic version of the Tic-Tac-Toe application and then expand on it to include examples of how you might fetch a user’s name, address, and gender. We’ll then show you how to use that information in your application. On the way, we’ll cover how MySpace and OpenSocial define an opensocial.Person object and how to use that information to enrich your application.

We’ll also get to really play with our Tic-Tac-Toe game. This will be our example app, and over the course of the book we’ll take you from a basic game to a fully functional and feature-rich application.

At each step along the way we’ll teach you new methods and programming tricks for accessing and using the OpenSocial API. Code examples will be shown in full and then broken down into segments for further explanation, allowing you to zero in on a specific feature or trouble spot.

The Two Concepts That Every Developer Should Know

Before we begin, there are two basic concepts that every MySpace and OpenSocial app developer should know about:

• In the world of MySpace apps, everyone is either an Owner or a Viewer.

• The MySpace permission model is a complex and confusing beast that will likely leave you frustrated and angry.

On that note, let’s get started!

Basic Concepts: Owner and Viewer

The concept of Owner and Viewer is central to OpenSocial, and it boils down to

Owner = the MySpace user on whose surface the application is running

Viewer = the MySpace user who is currently interacting with the application

Once you start accessing MySpace data, all the requests you make are made in the context of the Owner and the Viewer.

For example, let’s say John has the app installed and Jane is viewing John’s MySpace Profile. John is the Owner and Jane is the Viewer. Alternatively, if John is looking at the app on his own MySpace Profile, he is both the Owner and the Viewer.

When you request data, you’ll be asking for information about either the Owner or the Viewer.

Basic Concepts: Permissions for Accessing MySpace Data

Not all user data is accessible to apps, and the data that is accessible is subject to a sometimes convoluted permission model. The key idea behind the MySpace permission model (dubbed Open Canvas) is that under certain circumstances an app can access a user’s data even if that user hasn’t installed the app. However, this access can happen only on the app’s Canvas surface and not on the Home or Profile surfaces.

Under this model there are essentially three core questions used to determine whether an app can access a piece of data:

1. Does the Viewer have the app installed?

2. Is the Viewer logged in?

3. Has the Viewer blocked the app? Blocking an app prevents any and all access to the Viewer’s data.

Figure 2.1 is a quick reference chart for Open Canvas; remember, though, that these permissions can change. So stay on your toes and watch out for permission traps when accessing user data.

Figure 2.1 MySpace Open Canvas permission model for accessing user data.

image

Starting Our Tic-Tac-Toe App

The first thing we need to do is to get the basic Tic-Tac-Toe app started. Since this app is just scaffolding on which to hang OpenSocial concepts, we’re going to gloss over a lot of the details. At this initial level our app could just as easily be a JavaScript game embedded in a Web page. It is the OpenSocial code that we will add later that will make the game come alive.

Note

Before we start, you should have the basic version of Tic-Tac-Toe installed as an app on your MySpace developer account. You will find the code on our Google Code page at http://code.google.com/p/opensocialtictactoe/source/browse/trunk/chapter2/chapter2ttt.html. For instructions on how to create, publish, and edit an app, please refer to Chapter 1, Your First MySpace App.

The game is a simple table grid of nine squares. Each square has a click handler to record player moves. Underneath the surface is a state-of-the-art computer AI (i.e., random-move engine) to play against.

The remainder of this chapter will introduce some basic concepts that are central to OpenSocial and apply them to our Tic-Tac-Toe app. At the end of this chapter, our app will display the current player’s name, gender, current location, and Profile image.

Accessing MySpace User Data

MySpace Profile data is represented in OpenSocial by the opensocial.Person object. Essentially,

opensocial.Person = a MySpace Profile

The opensocial.Person object contains the methods shown in Table 2.1.

Table 2.1 opensocial.Person Methods*

image

*Portions of this chart are modifications based on work created and shared by Google (http://code.google.com/apis/opensocial/docs/0.8/reference/#opensocial.Person) and used according to terms described in the Creative Commons 2.5 Attribution License (http://creativecommons.org/licenses/by/2.5/).

In addition, the opensocial.Person object supports a wide range of data fields, such as a user’s ID, Profile picture, or favorite movies. Table 2.2 presents all of the supported person fields along with their return types.

Table 2.2 MySpace opensocial.Person Fields*

image

image

image

image

image

Accessing Profile Information Using the opensocial.Person Object

The first thing we’re going to add to our basic Tic-Tac-Toe app is the ability to get the default fields for our Viewer by fetching the corresponding opensocial.Person object using an opensocial.DataRequest. MySpace defines these default opensocial.Person.Field values for the Person object:

• Profile URL, or opensocial.Person.Field.PROFILE_URL

• Image URL, or opensocial.Person.Field.THUMBNAIL_URL

• Display name, or opensocial.Person.Field.NAME

• User ID, or opensocial.Person.Field.ID

These are the bare-minimum default fields that, as long as you have access to the Person object, will always be returned.

One thing to note is that all requests to the MySpace API are asynchronous, meaning you launch them as “fire and forget” requests. Typically you make a request and specify a callback function; when the server is done processing your request, it passes the results as a parameter into your callback function. One result of this is that you’re probably going to want to put your data requests at the start of the code. That way the MySpace API can start processing your request as soon as possible, and your app won’t be stuck waiting for data to come back.

Let’s take a look at a function that does the following:

1. Instantiates an opensocial.DataRequest object

2. Calls newFetchPersonRequest to create a generic request object, passing in the VIEWER as a parameter

3. Adds the request to the queue by calling add(), passing in a key to name the request

The following code shows this function:

image

The first line of the function simply returns an opensocial.DataRequest object. The DataRequest object is designed to take care of all your requesting needs. While developing our app, we’ll make heavy use of it.

opensocial.IdSpec.PersonId.VIEWER is one of many enums you’ll encounter in OpenSocial. In JavaScript this actually resolves into a string, and on MySpace specifically it is equal to the string VIEWER. You can use the string and enum interchangeably, but we recommend using the enum for two reasons:

• If you mistype the enum, your mistake triggers a JavaScript error, but if you mistype the string, it isn’t immediately obvious that something went wrong, so it is harder to debug.

• The values to which the enums resolve aren’t yet clearly outlined in the OpenSocial spec, so different containers might resolve enums to different strings.

We use opensocial.IdSpec.PersonId.VIEWER here to state that we want to fetch the Viewer’s data. Had we wanted to fetch the Owner’s data, we would have used opensocial.IdSpec.PersonId.OWNER.

newFetchPersonRequest takes the ID of the user you want to request as a parameter (in this case the Viewer) and returns an object. That object is actually unnamed by OpenSocial, and the documentation simply refers to it as a “request.” This object is never used directly beyond how it’s used here—passed into DataRequest’s add() function.

Essentially, the DataRequest object creates “request” objects that are passed into its own add function. It may seem a little confusing, but remember—you’ll never have to use that mysterious, unnamed “request” object directly, and all OpenSocial API calls follow this general pattern.

The add function takes that request and adds it to a queue that is stored in the DataRequest object. We also give the request a key and, in this case, the string "v". This key is used to identify the response of a specific request; we’ll use this key later when we talk about how to parse responses.

The last line tells the container to start processing the request queue by calling send(). We pass the name of our callback function into send() as a parameter; when the server is done processing our request, it calls this function while passing in the response. You can see the flow of the OpenSocial data request and response pattern in Figure 2.2.

Figure 2.2 Basic request and response pattern for OpenSocial.

image

Getting More than Just the Default Profile Data

Fields beyond the default person fields typically follow a slightly different request pattern and may also require higher permission levels for access.

As an example of this, we’ll be requesting our Viewer’s status message (like a headline or shout-out), address, and gender. We’ve modified the function shown previously to now specify that we want this additional data:

image

Let’s take a look at what’s changed. The first line is the same; we instantiate an opensocial.DataRequest object. In the next line we create an array of opensocial.Person.Field enums; this list corresponds to the specific Person fields we want from the API.

Next, an empty object is created called opt_params. This is another OpenSocial pattern that you’ll see repeated in many places. Requests typically have some default action, and if you want to modify the default action, you need to supply some parameters to define what you want to do. You do this by adding certain properties to an object and passing that object into the request.

When the MySpace container is processing a request for Viewer or Owner data, it checks the parameters sent in for a property named profileDetail. If it finds such a property, it knows that additional fields were requested. So let’s take a look at that line again:

// Add the list of fields to the parameters
opt_params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = fields;

On MySpace, opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS resolves to the string profileDetail. We’re creating that property and setting it equal to the array of opensocial.Person.Field values we created earlier. The container now knows that additional fields were requested.

The rest of the function is the same as before—we create the request, add it to the queue, and send it off.

opensocial.DataResponse and opensocial.ResponseItem (aka, Using MySpace User Data)

The various person fields are returned in different ways, but there are essentially three types of responses:

• A literal, such as a string or a number. For example, opensocial.Person.Field.STATUS returns a string.

• An object. For example, opensocial.Person.Field.CURRENT_LOCATION returns an opensocial.Address object.

• An enum. For example, opensocial.Person.Field.GENDER returns an opensocial.Enum enum object.

All responses from the API come in the form of an opensocial.DataResponse object. The DataResponse object contains some number of opensocial.ResponseItem objects; each ResponseItem corresponds to the requests we added to the DataRequest queue. For now, we just have the one request for the Viewer; we’ll look at dealing with multiple requests and ResponseItem objects in the next chapter.

To get a particular ResponseItem object from an opensocial.DataResponse, you need to use a key. If you already provided an optional key, use that. Otherwise, you can use the default key created by the MySpace container.

Tip: Use an Optional Key

It’s recommended that you always use an optional key, as the default keys can be tricky to use. But, if you’re curious, the container-generated keys are found in the MyOpenSpace.RequestType namespace.

image

Let’s take a look at this function more closely. The first thing to notice is that it is the function we specified when we called send() in our previous request function.

// Start processing the request and specify the callback function
req.send(getDataCallback);

The function getDataCallback is executed when the server has processed our request and prepared a response. The first line in getDataCallback takes that DataResponse object and calls the get() function, passing in our key. Above we named our Viewer request "v"; here we use that key to get the ResponseItem that corresponds to that request.

The function call data.get("v") returns the ResponseItem object that contains the Viewer’s opensocial.Person object; we get the Person by calling getData(). Now the variable viewer contains an object of type opensocial.Person, which in turn contains the details of the Viewer, specifically the four default fields plus the current location, gender, and status. Table 2.3 shows the methods available for the ResponseItem object.

Table 2.3 opensocial.ResponseItem Methods*

image

*Portions of this chart are modifications based on work created and shared by Google (http://code.google.com/apis/opensocial/docs/0.8/reference/#opensocial.ResponseItem) and used according to terms described in the Creative Commons 2.5 Attribution License (http://creativecommons.org/licenses/by/2.5/).

The next section of our code calls the function printPerson(), which is a helper function that we use to parse out the details of our Viewer and output them to the screen. Here we will parse out all three types of responses—enums, strings, and objects:

image

image

Let’s break down this code. To access the data from the viewer variable, which is of type opensocial.Person, we’ll typically need to use the getField() function. After we confirm that viewer isn’t null, we call getField(), pass in the field we want as a parameter, and set that value to the src attribute of an image tag. The field we asked for, opensocial.Person.Field.THUMBNAIL_URL, is returned as a string, so we can just access it directly. That’s really all there is to parsing out a Person field that is returned as a string. For details on the return type for every supported Person field, refer back to Table 2.2 in this chapter.

The next line uses a shortcut to retrieve the Viewer’s display name. Another shortcut, getID(), exists to retrieve the Viewer’s ID. All other fields are accessed using getField(), as you’ll see in the next few lines. We could have used getField(opensocial.Person.Field.NICKNAME) to retrieve the display name, but the shortcut is cleaner.

Next, we parse out the Viewer’s current location; this field is returned as an opensocial.Address object. You’ll notice that the opensocial.Address object behaves similarly to the opensocial.Person object. Both have fields that describe the types of data you can retrieve, which in turn are fetched using the getField() function. Many of the objects in OpenSocial follow this pattern.

Finally, we parse out the gender, which is an opensocial.Enum object. There are two useful types of data in each opensocial.Enum: the display value and the key. The display value is retrieved using getDisplayValue() and is a string that is defined by each container as it sees fit. For example, the display value for the female gender, depending on the container, could be “female” or “It’s a girl!” or even “http://example.com/girl.jpg.” Because these display values can be different from container to container, the key is typically used when making comparisons as the key values are defined in the OpenSocial spec.

In our code, we output the display value to the surface but use the key to make a logical comparison; we set the background color to pink if the gender is female (i.e., it’s equal to opensocial.Enum.Gender.FEMALE), or blue otherwise.

In the full code listing for the chapter, which you can find at http://code.google.com/p/opensocialtictactoe/source/browse/#svn/trunk/chapter2, we added a function that goes through each Person field and parses it. If you’re wondering how to parse a particular field that wasn’t covered here, take a look at the code and you should be able to find what you need.

Error Handling

JavaScript errors from apps seem to be an all-too-common occurrence, but they don’t have to be. Most developers don’t expect errors to occur, and so they don’t test or prepare for them as a result, but errors do happen. Your best defense against them is to admit that yes, they do occur, and yes, you need to be ready for them.

OpenSocial offers a few functions you can use to deal with errors. In the following example we check for errors before we parse the response for data. If an error is found, the response data isn’t parsed.

image

image

First, we check if the response is null or undefined, and then check if the global error flag was set in the DataResponse object by calling the object’s hadError() function. This flag is set if any of the requests had an error. Each ResponseItem has an error flag as well, so we’ll need to check each ResponseItem in order to find out which request had the error, if the global flag was set. We do this by calling the ResponseItem’s hadError() function. In this case we had only one request, so there is only one ResponseItem, but in the event of multiple ResponseItem objects we would check each one in turn to determine its error state.

Similar to an opensocial.Enum object that has two types of data, one for display and one for logical comparisons, each opensocial.ResponseItem that encounters an error also has two types of data. The error message, accessed by getErrorMessage(), is an arbitrary string that should describe the error and help you debug what happened. The error code, accessed by getErrorCode(), matches up to one of the codes found in the opensocial.ResponseItem.Error enum. Common causes for each type of error code may be found in Table 2.4.

Table 2.4 Common Error Code Causes

image

image

You’ll notice that we also attempted to retry the request in the event of an INTERNAL_ERROR. This is because an INTERNAL_ERROR can sometimes occur because of network congestion or other temporary problems. Your request might succeed if you wait a second or so and try again.

Handling errors offers two benefits:

• There are no embarrassing JavaScript errors when you try to retrieve objects that don’t exist.

• There’s a possibility that you can recover from your error by retrying the request.

Warning

When retrying your request after an error, be careful you don’t code yourself into an infinite loop! It’s best to keep a retry counter as we do in the code shown previously.

Summary

In this chapter we covered the basic flow of an OpenSocial application, focusing on the process of accessing data on the API and OpenSocial’s request/response pattern. We also defined an opensocial.Person object—what it is, how to get it, and what to do with it.

This request/response pattern is the foundation of any OpenSocial app. You will use it every time you request data from the server, so we hope you were paying attention.

Note

Code listings and/or code examples for this chapter and every other chapter can be found on our Google Code page under http://opensocialtictactoe.googlecode.com.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.162.87