Persistent Data

Most OpenSocial calls involve building a DataRequest object, sending it to Ning, and processing the response. Reading and writing Application data is included in this flow. An application can only write to the data of the OWNER object. While this policy is fairly restrictive, it is to prevent malicious users from writing data to arbitrary users. With most OpenSocial-based applications such as Ning Apps, the best practice is to use a remote storage system and use persistent data for caching purposes or small amounts of data.

Saving Data

To write a value to a specific key, create a DataRequest and add the result of calling newUpdatePersonAppDataRequest to it:

var req = opensocial.newDataRequest();
req.add(req.newUpdatePersonAppDataRequest("VIEWER", "myKey", "myValue"), "set_data");
req.send(set_callback);

The previous piece of code attempts to save the string myValue under the key of myKey. It also specifies a callback function named set_callback that will get a DataResponse object indicating whether the update failed or succeeded.

Note

Ning allows a maximum of 10k of serialized data stored, including keys, values and serialization overhead.

Retrieving Data

To retrieve the value of myKey you must create another DataRequest. This time, include a newFetchPersonAppDataRequest result:

var req = opensocial.newDataRequest();
var idspec = opensocial.newIdSpec({'userId':'VIEWER', 'groupId':'SELF'});

req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), 'viewer');
req.add(req.newFetchPersonAppDataRequest(idspec, 'myKey'), 'get_data');
req.send(get_callback);

To specify who you want to retrieve data for, you can pass any of the following as the first parameter to the newFetchPersonAppDataRequest function:

  • opensocial.IdSpec.PersonId.VIEWER
  • opensocial.IdSpec.PersonId.OWNER
  • opensocial.IdSpec.Group.VIEWER_FRIENDS
  • opensocial.IdSpec.Group.OWNER_FRIENDS

The meaning of each of these values will be covered in depth later in this article.

The callback specified by this function gets a DataResponse object back that contains the data that was stored, or an error message if something went wrong. A callback function implementation could look something like this:

function get_callback(response) {
  if (response.get("get_data").hadError()) {
    // the fetch failed ... insert code to handle the error
  } else {
    var data = response.get("get_data").getData();
    // the fetch was successful ... "data" contains the app data
  }
};

Assuming that the request succeeded, the data variable in the function above will be assigned a JSON object with the following layout:

{
  XXXXXXXXXXXXXXXXXXX : { myKey : "<value of myKey for user XXXXXX...>" }
}

where XXXXXXXXXXXXXXXXXXXXX is the ID number of the user who the data belongs to. If your request specifies many people to fetch data for, then the result will look like this:

{
  XXXXXXXXXXXXXXXXXXXX : { myKey : "<value of myKey for user XXXXXX...>" },
  YYYYYYYYYYYYYYYYYYYY : { myKey : "<value of myKey for user YYYYYY...>" },
  ZZZZZZZZZZZZZZZZZZZZ : { myKey : "<value of myKey for user ZZZZZZ...>" }
}

If you request multiple keys for each person, the keys will be scoped to each person’s ID in the returned data object:

{
  XXXXXXXXXXXXXXXXXXXX : { myKey1 : "<value of myKey1 for user XXXXXX...>",
                           myKey2 : "<value of myKey2 for user XXXXXX...>" },
  YYYYYYYYYYYYYYYYYYYY : { myKey1 : "<value of myKey1 for user YYYYYY...>",
                           myKey2 : "<value of myKey2 for user YYYYYY...>" },
  ZZZZZZZZZZZZZZZZZZZZ : { myKey1 : "<value of myKey1 for user ZZZZZZ...>",
                           myKey2 : "<value of myKey2 for user ZZZZZZ...>" }
}

Example of Saving and Retrieving Data

The following code snippet is a prototype that gets and saves a piece of persistent data in an OpenSocial Application. Note that the output function is a testing method used with an application such as OpenSocial Dev App, and any output function such as alert() can also work:

// Default OpenSocial Dev App Sample Code
function get_callback(response) {

// response.get("oViewer").getData().getId();
var userid = response.get("oViewer").getData().getId();

  if (response.get("get_data").hadError()) {
    // the fetch failed ... insert code to handle the error
    output("get callback failed");
  } else {
    var data = response.get("get_data").getData();
    output(data[userid]["myKey"]);

    // the fetch was successful ... "data" contains the app data
    output("get callback suceeded");
  }
};


function set_callback(response) {
  if (response.get("set_data").hadError()) {
    // The update failed ... insert code to handle the error
    output("set callback failed");
  } else {
    // The update was successful ... continue execution
    output("set callback succeeded");
    get_request();
  }
};

function get_request() {
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest("VIEWER"), "oViewer");
  req.add(req.newFetchPersonAppDataRequest("VIEWER", "myKey"), "get_data");
  req.send(get_callback);
};

function request() {
  var req = opensocial.newDataRequest();
  req.add(req.newUpdatePersonAppDataRequest("VIEWER", "myKey", "myValue"), "set_data");
  req.send(set_callback);
};

// Sets a value, and then gets that same value.
request();