SlideShare une entreprise Scribd logo
1  sur  90
Télécharger pour lire hors ligne
OpenSocial
   Korea - November 2008


Arne Roomann-Kurrik
Developer Relations

Yung Choi
Software Engineer




                           1
Gadgets
Not widgets, not sprockets, not gidgets, not wadgets




                                                       2
Gadgets
A gadget spec:
  • Is an XML file.
  • Defines metadata about an OpenSocial app.
  • Is highly cacheable and does not need a high performance server.

Gadgets use existing web standards
 • XML to define metadata.
 • HTML for markup.
 • JavaScript for interactivity.
 • CSS for presentation.




                                                                       3
Gadgets
A gadget server:
  • Takes the gadget spec as input.
  • Performs optimizations on the gadget spec.
  • Outputs HTML, JavaScript, and CSS as one document.




                                                         4
Gadgets

A container:
  • Displays the social network’s user interface.
  • Opens an IFrame to the rendered gadget.




                                                    5
Gadgets
Example gadget XML spec:
 • Uses HTML to print “Hello World”.
 • Colors the text red with CSS.
 • Dynamically adjusts the height of the gadget with JavaScript.
     <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?>
     <Module>
       <ModulePrefs title=quot;Hello World!quot;>
         <Require feature=quot;dynamic-heightquot; />
       </ModulePrefs>
       <Content type=quot;htmlquot;>
         <![CDATA[
           <h1>Hello World</h1>
           <style type=quot;text/cssquot;>
             h1 { color: #dd0000; }
           </style>
           <script type=quot;text/javascriptquot;>
             gadgets.window.adjustHeight();
           </script>
         ]]>
       </Content>
     </Module>
                                                                   6
Gadgets

Content sections:
 • Define the current view:

    <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?>
    <Module>
      <ModulePrefs title=quot;Hello World!quot;>
        <Require feature=quot;dynamic-heightquot; />
      </ModulePrefs>
      <Content type=quot;htmlquot; view=quot;canvasquot;>
        <![CDATA[
          <h1>Hello World</h1>
          <style type=quot;text/cssquot;>
            h1 { color: #dd0000; }
          </style>
          <script type=quot;text/javascriptquot;>
            gadgets.window.adjustHeight();
          </script>
        ]]>
      </Content>
    </Module>
                                               7
Gadgets

What are views?
 • Gadgets can render in different locations on a container.
 • Rendering area changes from small to large.
 • Certain pages might be public, some are private.
 • Containers may have different policies depending on the page,
   especially when the gadget displays ads.
 • Views provide a way for gadgets to provide different functionality
   depending on where it is rendered.




                                                                        8
Gadgets




iGoogle quot;homequot; view:
  • On iGoogle, the quot;homequot; view is a small,
    private page that does not allow ads.

                                              9
Gadgets




          iGoogle quot;canvasquot; view:
            • Large private view, allows ads.


                                                10
Gadgets
Working with views in the gadget XML:
 • <Content> sections are repeated for each view.
 • Add a view=quot;view namequot; attribute to each section.
 • Content sections may support multiple views, for example
   view=quot;home,canvasquot;
    <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?>
    <Module>
      <ModulePrefs title=quot;Hello World!quot;>
        <Require feature=quot;dynamic-heightquot; />
      </ModulePrefs>
      <Content type=quot;htmlquot; view=quot;homequot;>
        <![CDATA[
          ...
        ]]>
      </Content>
      <Content type=quot;htmlquot; view=quot;canvasquot;>
        <![CDATA[
          ...
        ]]>
      </Content>
    </Module>
                                                              11
Gadgets

Add extra features to your gadget:
 • dynamic-height - Change the size of your gadget in the container.
 • views - Navigate between different surfaces of the container.
 • skins - Make your gadget change its styles to match the container.
 • Containers may offer custom features...
           <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?>
           <Module>
             <ModulePrefs title=quot;Hello World!quot;>
               <Require feature=quot;dynamic-heightquot; />
             </ModulePrefs>
             <Content type=quot;htmlquot;>
               <![CDATA[
                 ...
               ]]>
             </Content>
           </Module>




                                                                        12
Gadgets



          <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?>
          <Module>
            <ModulePrefs title=quot;Hello Social!quot;>
              <Require feature=quot;opensocial-0.8quot; />
            </ModulePrefs>
            <Content type=quot;htmlquot;>
              <![CDATA[
                ...
              ]]>
            </Content>
          </Module>




    The OpenSocial JavaScript API is a gadget feature, too!




                                                              13
Gadgets
Requesting the gadget XML spec:
 1. The client requests an app to be rendered.




                                                 14
Gadgets
Requesting the gadget XML spec:
 1. The client requests an app to be rendered.
 2. The container fetches the gadget XML spec from its host.




                                                               15
Gadgets
Requesting the gadget XML spec:
 1. The client requests an app to be rendered.
 2. The container fetches the gadget XML spec from its host.
 3. The container renders the gadget into HTML, which is displayed
   to the client.




                                                                     16
Gadgets
Scaling is hard:
 • Easy to start and get some users.




                                       17
Gadgets
Scaling is hard:
 • Being popular on one social network
   can push your server to the limit...




                                          18
Gadgets
Scaling is hard:
 • ...being popular on many networks
   can be disastrous.

Caching can help!




                                       19
Gadgets
Requesting a cached gadget XML spec:
 1.The client requests an app to be rendered. The container already
   has a copy of the spec stored in its cache.




                                                                      20
Gadgets
Requesting a cached gadget XML spec:
 1.The client requests an app to be rendered. The container already
   has a copy of the spec stored in its cache.
 2.The container renders the gadget into HTML, which is displayed
   to the client.




                                                                      21
Gadgets
Requesting a cached gadget XML spec:
  1.The client requests an app to be rendered. The container already
    has a copy of the spec stored in its cache.
  2.The container renders the gadget into HTML, which is displayed
    to the client.
Your server does not even get a request!




                                                                       22
Gadgets
Optimizations?
 • Cache, cache, cache.
 • Rewrite links to use content proxies.
 • Rewrite relative links to full paths.
 • Concatenate JS and CSS.
 • Return only content for the current view.




                                               23
The JavaScript APIs




                      24
Gadgets JavaScript

gadgets.* utility functions:
  • gadgets.io.makeRequest()
    Make cross-domain AJAX calls to remote servers.




                                                      25
Gadgets JavaScript

gadgets.* utility functions:
  • gadgets.io.makeRequest()
    Make cross-domain AJAX calls to remote servers.
  • gadgets.json.parse() and gadgets.json.stringify()
    Native JSON support.




                                                        26
Gadgets JavaScript

gadgets.* utility functions:
  • gadgets.io.makeRequest()
    Make cross-domain AJAX calls to remote servers.
  • gadgets.json.parse() and gadgets.json.stringify()
    Native JSON support.
  • gadgets.util.escapeString()
    Make text safe for display via innerHTML.




                                                        27
Gadgets JavaScript

gadgets.* utility functions:
  • gadgets.io.makeRequest()
    Make cross-domain AJAX calls to remote servers.
  • gadgets.json.parse() and gadgets.json.stringify()
    Native JSON support.
  • gadgets.util.escapeString()
    Make text safe for display via innerHTML.
  • gadgets.util.registerOnLoadHandler()
    Execute code when the page is finished loading.




                                                        28
Gadgets JavaScript

gadgets.io.makeRequest():
  • Make cross-domain AJAX calls to remote servers.


Remote content:
 • Work with different servers.
 • AJAX is not cross-domain!
 • JSONP is only one-way.
 • Data needs to be cached for millions
   of users.




                                                      29
Gadgets JavaScript
Requesting remote content:
 1.The rendered app calls gadgets.io.makeRequest() to fetch
   remote content.




                                                              30
Gadgets JavaScript
Requesting remote content:
 1.The rendered app calls gadgets.io.makeRequest() to fetch
   remote content.
 2.The container requests content from the specified URL.




                                                              31
Gadgets JavaScript
Requesting remote content:
 1.The rendered app calls gadgets.io.makeRequest() to fetch
   remote content.
 2.The container requests content from the specified URL.
 3.The container returns the response to the application, which renders
   the data.




                                                                      32
The OpenSocial JavaScript API
Representing users:
 • Client-side, users must work with the VIEWER and the OWNER.




                                                                 33
The OpenSocial JavaScript API
Multiple personalities:
 • When you visit your own profile, you are both the VIEWER and the
   OWNER.




                                                                      34
The OpenSocial JavaScript API
Representing users:
 • Sometimes, containers allow anonymous browsing.


                 ??


                                                     35
The OpenSocial JavaScript API
 OpenSocial requests:
  • An OpenSocial DataRequest is created.
  • Requests are added to the DataRequest.
  • The DataRequest is sent to the server asynchronously.
  • When the request finishes, the supplied callback will be called.

function request() {
   var req = opensocial.newDataRequest();
   req.add(...);
   ...
   req.send(response);
};

function response(data) { ... };

gadgets.util.registerOnLoadHandler(request);




                                                                       36
The OpenSocial JavaScript API
 OpenSocial requests:
  • An OpenSocial DataRequest is created.
  • Requests are added to the DataRequest.
  • The DataRequest is sent to the server asynchronously.
  • When the request finishes, the supplied callback will be called.
function request() {
   var req = opensocial.newDataRequest();
   req.add(req.newFetchPersonRequest(quot;OWNERquot;), quot;get_ownerquot;);
   req.add(req.newFetchPersonRequest(quot;VIEWERquot;), quot;get_viewerquot;);
   req.add(req.newFetchActivitiesRequest(quot;VIEWERquot;), quot;vactivitiesquot;);
   req.add(req.newFetchPersonAppDataRequest(quot;OWNERquot;, quot;*quot;), quot;odataquot;);
   ...
   req.send(response);
};

function response(data) { ... };

gadgets.util.registerOnLoadHandler(request);



                                                                       37
The OpenSocial JavaScript API
OpenSocial responses:
 • Responses are bundled according to the keys specified in the request.
 • Check for an error at the global response level.
 • Check for an error at the specific response level.
 • Use getData() to retrieve the actual information in a request.

         function response(data) {
           if (data.hadError()) {
             if (data.get(quot;get_ownerquot;).hadError()) {
               ...
             }
             if (data.get(quot;get_viewerquot;).hadError()) {
               ...
             }
             ...
           }
           var owner = data.get(quot;get_ownerquot;).getData();
           var viewer = data.get(quot;get_viewerquot;).getData();
         };


                                                                      38
The OpenSocial JavaScript API
Working with people:
 • opensocial.Person - JavaScript representation of a user.




                                                              39
The OpenSocial JavaScript API
Request one person:
   req.add(req.newFetchPersonRequest(idspec, opt_params), quot;keyquot;);

 • idspec can be either “VIEWER”, “OWNER” or an ID number.
 • opt_params contains extra request parameters, such as which profile
   fields to fetch.

newFetchPersonRequest responses:
   var owner = data.get(quot;keyquot;).getData();
   alert(owner.getDisplayName());

 • Data contains a single opensocial.Person
   object.
 • Person objects can contain lots of information,
   such as addresses, companies, phone numbers,
   favorite movies, and thumbnail urls.


                                                                     40
The OpenSocial JavaScript API
Methods available on an OpenSocial Person:

• getDisplayName()
  Gets a text display name for this person; guaranteed to return a useful
  string.
• getField(key, opt_params)
  Gets data for this person that is associated with the specified key.
• getId()
  Gets an ID that can be permanently associated with this person.
• isOwner()
  Returns true if this person object represents the owner
  of the current page.
• isViewer()
  Returns true if this person object represents the
  currently logged in user.




                                                                            41
The OpenSocial JavaScript API
 An OpenSocial Person's fields:
• ABOUT_ME         • JOB_INTERESTS         •   SEXUAL_ORIENTATION
• ACTIVITIES       • JOBS                  •   SMOKER
• ADDRESSES        • LANGUAGES_SPOKEN      •   SPORTS
• AGE              • LIVING_ARRANGEMENT    •   STATUS
• BODY_TYPE        • LOOKING_FOR           •   TAGS
• BOOKS            • MOVIES                •   THUMBNAIL_URL
• CARS             • MUSIC                 •   TIME_ZONE
• CHILDREN         • NAME                  •   TURN_OFFS
• CURRENT_LOCATION • NETWORK_PRESENCE      •   TURN_ONS
• DATE_OF_BIRTH    • NICKNAME              •   TV_SHOWS
• DRINKER          • PETS                  •   URLS
• EMAILS           • PHONE_NUMBERS
• ETHNICITY        • POLITICAL_VIEWS
• FASHION          • PROFILE_SONG
• FOOD             • PROFILE_URL
• GENDER           • PROFILE_VIDEO
• HAPPIEST_WHEN    • QUOTES
• HAS_APP          • RELATIONSHIP_STATUS
• HEROES           • RELIGION
• HUMOR            • ROMANCE
• ID               • SCARED_OF
• INTERESTS        • SCHOOLS
                                                                    42
The OpenSocial JavaScript API
Working with people:
 • A Collection represents many opensocial.Person objects.




                                                             43
The OpenSocial JavaScript API
IdSpec:
  • idspec is an object that can represent groups of people.
   var idspec = opensocial.newIdSpec({
     quot;userIdquot; : quot;OWNERquot;,
     quot;groupIdquot; : quot;FRIENDSquot;
   });


IdSpec can represent only one person:
   var idspec = opensocial.newIdSpec({
     quot;userIdquot; : quot;OWNERquot;,
     quot;groupIdquot; : quot;SELFquot;
   });



Or specific data:
   var idspec = opensocial.newIdSpec({
     quot;userIdquot; : quot;1234567890quot;,
     quot;groupIdquot; : quot;familyquot;
   });
                                                               44
The OpenSocial JavaScript API
Request many people:
   var idspec = opensocial.newIdSpec({
     quot;userIdquot; : quot;OWNERquot;,
     quot;groupIdquot; : quot;FRIENDSquot;
   });
   req.add(req.newFetchPeopleRequest(idspec, opt_params), quot;keyquot;);

 • Pass an idspec object to the newFetchPeopleRequest function.
 • opt_params contains extra request parameters, such as which profile
   fields to fetch, and how to order or filter the returned people.


newFetchPersonRequest responses:
   var owner_friends = data.get(quot;keyquot;).getData();
   owner_friends.each(function (person) {
     alert(person.getDisplayName());
   });
 • Data contains a Collection of opensocial.Person
  objects. Iterate over these by using the each() method.
                                                                      45
The OpenSocial JavaScript API
Working with data:
 • Persistent data gives apps key, value storage directly on the container.
 • String only, but conversion to JSON allows for storage of complex
   objects.
 • Storage per app per user - scales well with growth.
 • Ideal for settings, customizations.




                                                                        46
The OpenSocial JavaScript API
Set persistent data:
   req.add(req.newUpdatePersonAppDataRequest(idspec, key, value));

 • idspec can only be “VIEWER”.
 • key is the name under which this data will be stored.
 • value is a string representing the data to store.




                                                                47
The OpenSocial JavaScript API
Fetch persistent data:
   var idspec = opensocial.newIdSpec({
     quot;userIdquot; : quot;OWNERquot;,
     quot;groupIdquot; : quot;SELFquot;
   });
   req.add(req.newFetchPersonAppDataRequest(idspec, keys),
       quot;keyquot;);
   req.add(req.newFetchPersonRequest(quot;OWNERquot;), quot;ownerkeyquot;);

 • idspec is an object that can represent groups of people, the same as
   newFetchPeopleRequest.
 • keys is a list of persistent data keys to retrieve the data for.
 • The owner is requested because the data returned is indexed by user ID
   and we want the owner’s data.

newFetchPersonAppDataRequest responses:
   var app_data = data.get(quot;keyquot;).getData();
   var value = app_data[owner.getId()][key];

                                                                      48
The OpenSocial JavaScript API
Fetch persistent data:

 • Data is returned as an object indexed by ID number, then as an object
   indexed by key name, even if there is only data returned for one user!
   { quot;1234567890quot; : { quot;key1quot; : quot;value1quot; } }


 • One person, multiple keys:
   {
       quot;1234567890quot; : {
                          quot;key1quot; : quot;value1quot;,
                          quot;key2quot; : quot;value2quot;
                      }
   }


 • Multiple people:
   {
       quot;1234567890quot; : { quot;key1quot; : quot;value1quot; },
       quot;2345678901quot; : { quot;key1quot; : quot;value2quot; }
   }
                                                                       49
The OpenSocial JavaScript API
Working with activities:
 • API to post information about what users are doing with your app.
 • Many containers have support for images and some HTML.
 • Channel to grow your application.




 orkut                     MySpace                   hi5




                                                                       50
The OpenSocial JavaScript API
Post an activity:
   function postActivity(text) {
      var params = {};
      params[opensocial.Activity.Field.TITLE] = text;
      var activity = opensocial.newActivity(params);
      opensocial.requestCreateActivity(activity,
        opensocial.CreateActivityPriority.HIGH, callback);
   };

  • Assign the activity text to the TITLE field.
  • Call opensocial.newActivity() to create a new Activity instance.
  • Call opensocial.requestCreateActivity() to post the activity to the
   container.




                                                                          51
Building apps across containers




                                  52
Challenges

Cross container development is still tricky:
 • Containers may not follow the standard.
 • Containers may follow the standard but have different policies.
 • Follow best practices:
   http://tinyurl.com/4nuzll




                                                                     53
Robustness - Be Explicit

 • Spot the bug in this code!   Let's request the owner:
 function request() {
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest(
      quot;VIEWERquot;),
      quot;reqquot;);
  req.send(response);
 };




 function response(data) {
   var url = data.get(quot;reqquot;).getData().getField(
        opensocial.Person.Field.PROFILE_URL));
 • And access their profile URL:
   ...
 }

                                                           54
Robustness - Be Explicit

 • On hi5, url is:
       http://www.hi5.com/friend/profile/
           displayProfile.do?userid=XXXXXXXXXX

 • On orkut, url is:
       null

 • The OpenSocial specification only states the following about fields
  available on Person objects:

              quot;The server will always include ID,
               NAME, and THUMBNAIL_URL.quot;*
                                                 *http://rurl.org/qoo


                                                                         55
Robustness - Be Explicit

 • Introducing
     opensocial.DataRequest
         .PeopleRequestFields.PROFILE_DETAILS


 • Assign an array of properties you want to access to this optional
  parameter

   var params = {};
    params[opensocial.DataRequest
        .PeopleRequestFields.PROFILE_DETAILS] = [
       opensocial.Person.Field.ABOUT_ME,
       opensocial.Person.Field.ADDRESSES,
       opensocial.Person.Field.AGE
    ];



                                                                       56
Robustness - Be Explicit

 • Fixing the request: From this...
function request() {
 var req = opensocial.newDataRequest();

 req.add(req.newFetchPersonRequest(
     quot;VIEWERquot;),
     quot;reqquot;);
 req.send(response);
};




                                          57
Robustness - Be Explicit

 • ...to this:
function request() {
 var req = opensocial.newDataRequest();
 var params = {};
 params[opensocial.DataRequest.PeopleRequestFields
     .PROFILE_DETAILS] = [
    opensocial.Person.Field.PROFILE_URL
 ];
 req.add(req.newFetchPersonRequest(
     quot;VIEWERquot;, params),
     quot;reqquot;);
 req.send(response);
};




                                                     58
Robustness - Be Explicit



 • On hi5, url is:
       http://www.hi5.com/friend/profile/
           displayProfile.do?userid=XXXXXXXXXX


 • On orkut, url is:
       http://www.orkut.com/
           Profile.aspx?uid=YYYYYYYYY




                                                 59
Robustness - Check For Errors




                                60
Robustness - Check For Errors

 • Why is the following code brittle?   Request a user by ID:
 function request() {
  var req = opensocial.newDataRequest();
  req.add(req.newFetchPersonRequest(
      quot;14088281537290874435quot;),
      quot;reqquot;);
  req.send(response);
 };

 • And get the display name:

 function response(data) {
  var name = data.get(quot;reqquot;).getData()
      .getDisplayName();
  ...
 };

                                                                61
Robustness - Check For Errors

 • If the passed ID is invalid for any reason, the previous code throws a
  JavaScript error:

             data.get(quot;reqquot;).getData()
                 has no properties
 • Check for problems! DataRequest.send callbacks get
  DataResponse arguments with hadError methods:

      function response(data) {
       if (!data.hadError()) {
         var name = data.get(quot;reqquot;).getData()
             .getDisplayName();
         ...
       }
      };

                                                                            62
Robustness - Check For Errors

 • Inside of these DataResponse objects are nested ResponseItem
  objects, which also have hadError methods:

     function response(data) {
      if (!data.hadError()) {
        ...
      } else {
        if (data.get(quot;reqquot;).hadError()) {
          ...
        }
      }
     };

 • You can check each response individually to see where the point of
  failure is.



                                                                        63
Robustness - Check For Errors
 • Handling errors gracefully:
      function response(data) {
       if (!data.hadError()) {
         ...
       } else if (data.get(quot;reqquot;).hadError()) {
         alert(data.get(quot;reqquot;).getErrorMessage());
       } else {
         alert(quot;An unknown error occurredquot;);
       }
      };

 • getErrorMessage() provides a human-readable error message,
  but varies by container.

 • This may not be ideal for display to an end user.


                                                                64
Robustness - Check For Errors

 • getErrorCode() provides an enum indicating the type of error

      data.get(quot;reqquot;).getErrorCode()


 • Check for the type of error and fall back where possible.




                                                                  65
Robustness - Check For Errors

 • opensocial.ResponseItem.Error.BAD_REQUEST
    • The request was invalid
 • opensocial.ResponseItem.Error.FORBIDDEN
    • The gadget can never have access to this data
 • opensocial.ResponseItem.Error.INTERNAL_ERROR
    • Server problem
 • opensocial.ResponseItem.Error.LIMIT_EXCEEDED
    • Over quota
 • opensocial.ResponseItem.Error.NOT_IMPLEMENTED
    • No container support

                                                      66
Robustness - Check For Errors

  • Check for error types at runtime:

function response(data) {
 if (!data.hadError()) {
   ...
 } else if (data.get(quot;reqquot;).hadError()) {
   switch (data.get(quot;reqquot;).getErrorCode()) {
      case opensocial.ResponseItem.Error.BAD_REQUEST:
        ...
        break;
      case opensocial.ResponseItem.Error.INTERNAL_ERROR:
        ...
        break;
   }
 } else {
  ...



                                                       67
Robustness - Check For Errors

 • Not all errors need to be fatal!
 • An appropriate response to UNAUTHORIZED would be to call
  opensocial.requestPermission()


 switch (data.get(quot;reqquot;).getErrorCode()) {
   case opensocial.ResponseItem.Error.UNAUTHORIZED:
     opensocial.requestPermission(
         [ quot;VIEWERquot; ],
         quot;Share a gift with your friendquot;,
         callback);
     break;
 }




                                                              68
Robustness - Off Track For A Second

 • While you can react to an UNAUTHORIZED error, there’s also the
  opensocial.hasPermission()method, which you can check
  before making the request:


 var has_permission = opensocial.hasPermission(
     opensocial.Permission.VIEWER);


 • has_permission will be boolean true or false




                                                                    69
Robustness - Check For Errors

 • Let’s go back to that requestPermission call:

 opensocial.requestPermission(
     [ opensocial.Permission.VIEWER ],
     “Share a gift with your friend”,
     callback);


 • callback will be called when this request completes and get a
  ResponseItem as a parameter.
 • What happens if the container doesn’t support
  requestPermission?




                                                                   70
Robustness - Check For Errors

  • Unimplemented methods will get an NOT_IMPLEMENTED error
   code:
function callback(data) {
  if (!data.hadError()) {
    ...
  } else {
    switch(data.getErrorCode()) {
      case opensocial.ResponseItem.Error.NOT_IMPLEMENTED:
         ...
         break;
    }
  }
};




                                                              71
Robustness - Check For Errors

 • A container may not implement any method and still remain spec
  compliant as long as they return the NOT_IMPLEMENTED error
  code.
 • This applies to any method where the callback receives a
  DataResponse or ResponseItem, including:
    •   requestCreateActivity
    •   requestPermission
    •   requestSendMessage
    •   requestShareApp
    •   all new*Request calls
 • So be sure to check for such cases!




                                                                    72
Robustness - Check For Support




                                 73
Robustness - Check For Support

 • Containers have different purposes.   Not every field may be
  available.

 opensocial.Person.Field.LOOKING_FOR
    • hi5: not supported
    • MySpace: not supported
    • orkut: supported

 MyOpenSpace.Person.Field.DESIRE_TO_MEET
    • hi5: not supported
    • MySpace: supported
    • orkut: not supported

 hi5.PersonField.PRESENCE
    • hi5: supported
    • MySpace: not supported
    • orkut: not supported

                                                                  74
Robustness - Check For Support

 • Your impulse may be to write code like this:
if (MySpace) {
  ...
} else if (hi5) {
  ...
} else if (orkut) {
  ...
} else {
  ...
}

 • This is brittle! How do you scale to new containers
  automatically?




                                                         75
Robustness - Check For Support

 • Sounds like a job for capabilities querying:
var supports_lookingfor =
    opensocial.getEnvironment().supportsField(
         opensocial.Environment.ObjectType.PERSON,
         opensocial.Person.Field.LOOKING_FOR);


 • Now supports_lookingfor has the following value:
     • on hi5: false
     • on MySpace: false
     • on orkut: true

 • Goal: Build apps that programatically utilize extra functionality based
  on such booleans

 • Why is this approach brittle?

                                                                             76
Robustness - Check For Support

 • Try a container-specific profile field:
var supports_desiretomeet =
    opensocial.getEnvironment().supportsField(
         opensocial.Environment.ObjectType.PERSON,
         MyOpenSpace.Person.Field.DESIRE_TO_MEET);


 • Now supports_desiretomeet has the following value:
     • on hi5: JavaScript error
     • on MySpace: true
     • on orkut: JavaScript error

 • Oops!




                                                        77
Robustness - Check For Support

 • What about:
var supports_desiretomeet = false;
if (MyOpenSpace) {
  var supports_desiretomeet =
      opensocial.getEnvironment().supportsField(
           opensocial.Environment.ObjectType.PERSON,
           MyOpenSpace.Person.Field.DESIRE_TO_MEET);
}

 • Now supports_desiretomeet has the following value:
     • on hi5: false
     • on MySpace: true
     • on orkut: false

 • This approach defeats the purpose of querying!


                                                        78
Robustness - Check For Support

 • You should be able to see that:
var supports_desiretomeet = false;
if (MyOpenSpace) {
  var supports_desiretomeet =
      opensocial.getEnvironment().supportsField(
           opensocial.Environment.ObjectType.PERSON,
           MyOpenSpace.Person.Field.DESIRE_TO_MEET);
}

 • Is really the same as:
var supports_desiretomeet =
    (MyOpenSpace) ? true : false;




                                                       79
Robustness - Check For Support

 • Remember, we don't want to write code like this:
if (MyOpenSpace) {
  ...
} else if (hi5) {
  ...
} else {
  ...
}


 • Apps should query by capability, not container name




                                                         80
Robustness - Check For Support

 • Don't do this:

var env = opensocial.getEnvironment();
var supports_presence = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    hi5.PersonField.PRESENCE);

var supports_desiretomeet = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    MyOpenSpace.Person.Field.DESIRE_TO_MEET);

var supports_lookingfor = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    opensocial.Person.Field.LOOKING_FOR);



                                                 81
Robustness - Check For Support

 • A workaround is to ignore the enums and go for string
  representations:

var env = opensocial.getEnvironment();
var supports_presence = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    quot;presencequot;);

var supports_desiretomeet = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    quot;DESIRE_TO_MEETquot;);

var supports_lookingfor = env.supportsField(
    opensocial.Environment.ObjectType.PERSON,
    quot;lookingForquot;);



                                                           82
Robustness - Check For Support




          Wait a sec, isn’t this a worst practice?




                                                     83
Robustness - Check For Support

 • Thankfully, the specification addresses this issue:




   “Extra person, activity or other object fields should be
   defined in an enum under the container's namespace,
   and the environment should allow applications to
   discover these fields.”




                                                              84
Robustness - Check For Support

 • Thankfully, the specification addresses this issue:

 “For example, if the field orkut.PersonField.SPECIAL_FIELD is
 defined as 'orkut.specialPersonField', then
  opensocial.getEnvironment().supportsField(
     quot;personquot;,
     quot;orkut.specialPersonFieldquot;)
                                  and
  opensocial.getEnvironment().supportsField(
      opensocial.Environment.ObjectType.PERSON,
      orkut.PersonField.SPECIAL_FIELD)

 should both return true.”*
                                                   *http://rurl.org/qr4



                                                                          85
Robustness - Check For Support

 • We now have runtime access to capabilities across all containers:

                                    hi5     MySpace      orkut


              supports_presence    TRUE      FALSE      FALSE


          supports_desiretomeet    FALSE     TRUE       FALSE


             supports_lookingfor   FALSE     FALSE       TRUE



  • Drawback: Now we have to be sensitive to the underlying string
   value for Profile field enums

                                                                       86
Robustness - Check For Support

 • Now, instead of:       • Use:


if (MyOpenSpace) {        if (supports_presence) {
  ...                       ...
} else if (hi5) {         }
  ...                     if (supports_desiretomeet) {
} else {                    ...
  ...                     }
}                         if (supports_lookingfor) {
                            ...
                          }




                                                     87
Resources / Questions?




                         88
Resources

•   OpenSocial Tutorial: http://rurl.org/ss3

•   OpenSocial Spec, Foundation, Reference: http://opensocial.org

•   Caja: http://code.google.com/p/google-caja/

•   Shindig: http://incubator.apache.org/shindig/

•   OpenSocial Across Containers video: http://tinyurl.com/4nuzll

•   OpenSocial Templates: http://ostemplates-demo.appspot.com/

•   OpenSocial Dev App: http://osda.appspot.com

•   Partuza: http://partuza.nl

•   OpenSocial Specification Proposals:
    http://groups.google.com/group/opensocial-and-gadgets-spec/topics


                                                                        89
Hacking!
Beginner (http://is.gd/7W05):
 • Write a gadget to display quot;Hello Worldquot; in your favorite container.
 • Display a list of your friends.
 • Display the OWNER's favorite movies.
 • Post an activity update.
 • Write an app that uses AppData to store preferences (http://is.gd/7W0g)
Intermediate:
  • Make an app that works on two containers using the same XML.
  • Use makeRequest to list the OWNER's favorite movies and
    information from a web API such as amazon.com or imdb.com
  • Write a gift giving app using AppData: (http://is.gd/7W0v)
Advanced:
 • Write a server-side app that uses the Java (http://is.gd/7W0E) or
   PHP (http://is.gd/7W0K) client libraries.

                                                                       90

Contenu connexe

Tendances

How to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialHow to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialKaty Slemon
 
Adam Peller Interoperable Ajax Tools And Mashups
Adam Peller Interoperable Ajax Tools And MashupsAdam Peller Interoperable Ajax Tools And Mashups
Adam Peller Interoperable Ajax Tools And MashupsAjax Experience 2009
 
Web Applications and Deployment
Web Applications and DeploymentWeb Applications and Deployment
Web Applications and DeploymentBG Java EE Course
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsAgnieszka Figiel
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Coursepeter_marklund
 
MVC Demystified: Essence of Ruby on Rails
MVC Demystified: Essence of Ruby on RailsMVC Demystified: Essence of Ruby on Rails
MVC Demystified: Essence of Ruby on Railscodeinmotion
 
Getting started with Catalyst and extjs
Getting started with Catalyst and extjsGetting started with Catalyst and extjs
Getting started with Catalyst and extjsPeter Edwards
 

Tendances (19)

Jsp
JspJsp
Jsp
 
How to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorialHow to dockerize rails application compose and rails tutorial
How to dockerize rails application compose and rails tutorial
 
Hibernate
HibernateHibernate
Hibernate
 
Ugo Cei Presentation
Ugo Cei PresentationUgo Cei Presentation
Ugo Cei Presentation
 
Data Access with JDBC
Data Access with JDBCData Access with JDBC
Data Access with JDBC
 
Struts N E W
Struts N E WStruts N E W
Struts N E W
 
Adam Peller Interoperable Ajax Tools And Mashups
Adam Peller Interoperable Ajax Tools And MashupsAdam Peller Interoperable Ajax Tools And Mashups
Adam Peller Interoperable Ajax Tools And Mashups
 
Apache Cordova 4.x
Apache Cordova 4.xApache Cordova 4.x
Apache Cordova 4.x
 
Web Applications and Deployment
Web Applications and DeploymentWeb Applications and Deployment
Web Applications and Deployment
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
 
JSP Directives
JSP DirectivesJSP Directives
JSP Directives
 
MVC Demystified: Essence of Ruby on Rails
MVC Demystified: Essence of Ruby on RailsMVC Demystified: Essence of Ruby on Rails
MVC Demystified: Essence of Ruby on Rails
 
Getting started with Catalyst and extjs
Getting started with Catalyst and extjsGetting started with Catalyst and extjs
Getting started with Catalyst and extjs
 
Java Server Pages
Java Server PagesJava Server Pages
Java Server Pages
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
Jsp
JspJsp
Jsp
 
10 jsp-scripting-elements
10 jsp-scripting-elements10 jsp-scripting-elements
10 jsp-scripting-elements
 
Jsp element
Jsp elementJsp element
Jsp element
 

Similaire à Open Social Summit Korea

Developing for LinkedIn's Application Platform
Developing for LinkedIn's Application PlatformDeveloping for LinkedIn's Application Platform
Developing for LinkedIn's Application PlatformTaylor Singletary
 
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008Association Paris-Web
 
Open Social Summit Korea Overview
Open Social Summit Korea OverviewOpen Social Summit Korea Overview
Open Social Summit Korea OverviewChris Schalk
 
OpenSocial Intro
OpenSocial IntroOpenSocial Intro
OpenSocial IntroPamela Fox
 
IPhone Web Development With Grails from CodeMash 2009
IPhone Web Development With Grails from CodeMash 2009IPhone Web Development With Grails from CodeMash 2009
IPhone Web Development With Grails from CodeMash 2009Christopher Judd
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Shankar Gowda
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009shankar_mbn
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Shankar Gowda
 
Learn to Internationalize your Application
Learn to Internationalize your ApplicationLearn to Internationalize your Application
Learn to Internationalize your Applicationshankar_mbn
 
Google Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocialGoogle Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocialPatrick Chanezon
 
Moving from Web 1.0 to Web 2.0
Moving from Web 1.0 to Web 2.0Moving from Web 1.0 to Web 2.0
Moving from Web 1.0 to Web 2.0Estelle Weyl
 
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...goodfriday
 
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014Gil Irizarry
 
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13Fred Sauer
 
Shindig Apachecon Asia 09
Shindig Apachecon Asia 09Shindig Apachecon Asia 09
Shindig Apachecon Asia 09Nuwan Bandara
 
Real-World AJAX with ASP.NET
Real-World AJAX with ASP.NETReal-World AJAX with ASP.NET
Real-World AJAX with ASP.NETgoodfriday
 
Plugins 2.0: The Overview
Plugins 2.0: The OverviewPlugins 2.0: The Overview
Plugins 2.0: The OverviewAtlassian
 
Writing Gadgets with the WSO2 Gadget Server
Writing Gadgets with the WSO2 Gadget ServerWriting Gadgets with the WSO2 Gadget Server
Writing Gadgets with the WSO2 Gadget ServerWSO2
 
Make Mobile Apps Quickly
Make Mobile Apps QuicklyMake Mobile Apps Quickly
Make Mobile Apps QuicklyGil Irizarry
 
Getting Started with Android - OSSPAC 2009
Getting Started with Android - OSSPAC 2009Getting Started with Android - OSSPAC 2009
Getting Started with Android - OSSPAC 2009sullis
 

Similaire à Open Social Summit Korea (20)

Developing for LinkedIn's Application Platform
Developing for LinkedIn's Application PlatformDeveloping for LinkedIn's Application Platform
Developing for LinkedIn's Application Platform
 
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
 
Open Social Summit Korea Overview
Open Social Summit Korea OverviewOpen Social Summit Korea Overview
Open Social Summit Korea Overview
 
OpenSocial Intro
OpenSocial IntroOpenSocial Intro
OpenSocial Intro
 
IPhone Web Development With Grails from CodeMash 2009
IPhone Web Development With Grails from CodeMash 2009IPhone Web Development With Grails from CodeMash 2009
IPhone Web Development With Grails from CodeMash 2009
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009
 
Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009Learn to Internationalize your Applications - Sun Tech Days 2009
Learn to Internationalize your Applications - Sun Tech Days 2009
 
Learn to Internationalize your Application
Learn to Internationalize your ApplicationLearn to Internationalize your Application
Learn to Internationalize your Application
 
Google Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocialGoogle Devfest Singapore - OpenSocial
Google Devfest Singapore - OpenSocial
 
Moving from Web 1.0 to Web 2.0
Moving from Web 1.0 to Web 2.0Moving from Web 1.0 to Web 2.0
Moving from Web 1.0 to Web 2.0
 
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
 
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
Make Cross-platform Mobile Apps Quickly - SIGGRAPH 2014
 
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
SF JUG - GWT Can Help You Create Amazing Apps - 2009-10-13
 
Shindig Apachecon Asia 09
Shindig Apachecon Asia 09Shindig Apachecon Asia 09
Shindig Apachecon Asia 09
 
Real-World AJAX with ASP.NET
Real-World AJAX with ASP.NETReal-World AJAX with ASP.NET
Real-World AJAX with ASP.NET
 
Plugins 2.0: The Overview
Plugins 2.0: The OverviewPlugins 2.0: The Overview
Plugins 2.0: The Overview
 
Writing Gadgets with the WSO2 Gadget Server
Writing Gadgets with the WSO2 Gadget ServerWriting Gadgets with the WSO2 Gadget Server
Writing Gadgets with the WSO2 Gadget Server
 
Make Mobile Apps Quickly
Make Mobile Apps QuicklyMake Mobile Apps Quickly
Make Mobile Apps Quickly
 
Getting Started with Android - OSSPAC 2009
Getting Started with Android - OSSPAC 2009Getting Started with Android - OSSPAC 2009
Getting Started with Android - OSSPAC 2009
 

Dernier

"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 

Dernier (20)

"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 

Open Social Summit Korea

  • 1. OpenSocial Korea - November 2008 Arne Roomann-Kurrik Developer Relations Yung Choi Software Engineer 1
  • 2. Gadgets Not widgets, not sprockets, not gidgets, not wadgets 2
  • 3. Gadgets A gadget spec: • Is an XML file. • Defines metadata about an OpenSocial app. • Is highly cacheable and does not need a high performance server. Gadgets use existing web standards • XML to define metadata. • HTML for markup. • JavaScript for interactivity. • CSS for presentation. 3
  • 4. Gadgets A gadget server: • Takes the gadget spec as input. • Performs optimizations on the gadget spec. • Outputs HTML, JavaScript, and CSS as one document. 4
  • 5. Gadgets A container: • Displays the social network’s user interface. • Opens an IFrame to the rendered gadget. 5
  • 6. Gadgets Example gadget XML spec: • Uses HTML to print “Hello World”. • Colors the text red with CSS. • Dynamically adjusts the height of the gadget with JavaScript. <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?> <Module> <ModulePrefs title=quot;Hello World!quot;> <Require feature=quot;dynamic-heightquot; /> </ModulePrefs> <Content type=quot;htmlquot;> <![CDATA[ <h1>Hello World</h1> <style type=quot;text/cssquot;> h1 { color: #dd0000; } </style> <script type=quot;text/javascriptquot;> gadgets.window.adjustHeight(); </script> ]]> </Content> </Module> 6
  • 7. Gadgets Content sections: • Define the current view: <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?> <Module> <ModulePrefs title=quot;Hello World!quot;> <Require feature=quot;dynamic-heightquot; /> </ModulePrefs> <Content type=quot;htmlquot; view=quot;canvasquot;> <![CDATA[ <h1>Hello World</h1> <style type=quot;text/cssquot;> h1 { color: #dd0000; } </style> <script type=quot;text/javascriptquot;> gadgets.window.adjustHeight(); </script> ]]> </Content> </Module> 7
  • 8. Gadgets What are views? • Gadgets can render in different locations on a container. • Rendering area changes from small to large. • Certain pages might be public, some are private. • Containers may have different policies depending on the page, especially when the gadget displays ads. • Views provide a way for gadgets to provide different functionality depending on where it is rendered. 8
  • 9. Gadgets iGoogle quot;homequot; view: • On iGoogle, the quot;homequot; view is a small, private page that does not allow ads. 9
  • 10. Gadgets iGoogle quot;canvasquot; view: • Large private view, allows ads. 10
  • 11. Gadgets Working with views in the gadget XML: • <Content> sections are repeated for each view. • Add a view=quot;view namequot; attribute to each section. • Content sections may support multiple views, for example view=quot;home,canvasquot; <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?> <Module> <ModulePrefs title=quot;Hello World!quot;> <Require feature=quot;dynamic-heightquot; /> </ModulePrefs> <Content type=quot;htmlquot; view=quot;homequot;> <![CDATA[ ... ]]> </Content> <Content type=quot;htmlquot; view=quot;canvasquot;> <![CDATA[ ... ]]> </Content> </Module> 11
  • 12. Gadgets Add extra features to your gadget: • dynamic-height - Change the size of your gadget in the container. • views - Navigate between different surfaces of the container. • skins - Make your gadget change its styles to match the container. • Containers may offer custom features... <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?> <Module> <ModulePrefs title=quot;Hello World!quot;> <Require feature=quot;dynamic-heightquot; /> </ModulePrefs> <Content type=quot;htmlquot;> <![CDATA[ ... ]]> </Content> </Module> 12
  • 13. Gadgets <?xml version=quot;1.0quot; encoding=quot;UTF-8quot; ?> <Module> <ModulePrefs title=quot;Hello Social!quot;> <Require feature=quot;opensocial-0.8quot; /> </ModulePrefs> <Content type=quot;htmlquot;> <![CDATA[ ... ]]> </Content> </Module> The OpenSocial JavaScript API is a gadget feature, too! 13
  • 14. Gadgets Requesting the gadget XML spec: 1. The client requests an app to be rendered. 14
  • 15. Gadgets Requesting the gadget XML spec: 1. The client requests an app to be rendered. 2. The container fetches the gadget XML spec from its host. 15
  • 16. Gadgets Requesting the gadget XML spec: 1. The client requests an app to be rendered. 2. The container fetches the gadget XML spec from its host. 3. The container renders the gadget into HTML, which is displayed to the client. 16
  • 17. Gadgets Scaling is hard: • Easy to start and get some users. 17
  • 18. Gadgets Scaling is hard: • Being popular on one social network can push your server to the limit... 18
  • 19. Gadgets Scaling is hard: • ...being popular on many networks can be disastrous. Caching can help! 19
  • 20. Gadgets Requesting a cached gadget XML spec: 1.The client requests an app to be rendered. The container already has a copy of the spec stored in its cache. 20
  • 21. Gadgets Requesting a cached gadget XML spec: 1.The client requests an app to be rendered. The container already has a copy of the spec stored in its cache. 2.The container renders the gadget into HTML, which is displayed to the client. 21
  • 22. Gadgets Requesting a cached gadget XML spec: 1.The client requests an app to be rendered. The container already has a copy of the spec stored in its cache. 2.The container renders the gadget into HTML, which is displayed to the client. Your server does not even get a request! 22
  • 23. Gadgets Optimizations? • Cache, cache, cache. • Rewrite links to use content proxies. • Rewrite relative links to full paths. • Concatenate JS and CSS. • Return only content for the current view. 23
  • 25. Gadgets JavaScript gadgets.* utility functions: • gadgets.io.makeRequest() Make cross-domain AJAX calls to remote servers. 25
  • 26. Gadgets JavaScript gadgets.* utility functions: • gadgets.io.makeRequest() Make cross-domain AJAX calls to remote servers. • gadgets.json.parse() and gadgets.json.stringify() Native JSON support. 26
  • 27. Gadgets JavaScript gadgets.* utility functions: • gadgets.io.makeRequest() Make cross-domain AJAX calls to remote servers. • gadgets.json.parse() and gadgets.json.stringify() Native JSON support. • gadgets.util.escapeString() Make text safe for display via innerHTML. 27
  • 28. Gadgets JavaScript gadgets.* utility functions: • gadgets.io.makeRequest() Make cross-domain AJAX calls to remote servers. • gadgets.json.parse() and gadgets.json.stringify() Native JSON support. • gadgets.util.escapeString() Make text safe for display via innerHTML. • gadgets.util.registerOnLoadHandler() Execute code when the page is finished loading. 28
  • 29. Gadgets JavaScript gadgets.io.makeRequest(): • Make cross-domain AJAX calls to remote servers. Remote content: • Work with different servers. • AJAX is not cross-domain! • JSONP is only one-way. • Data needs to be cached for millions of users. 29
  • 30. Gadgets JavaScript Requesting remote content: 1.The rendered app calls gadgets.io.makeRequest() to fetch remote content. 30
  • 31. Gadgets JavaScript Requesting remote content: 1.The rendered app calls gadgets.io.makeRequest() to fetch remote content. 2.The container requests content from the specified URL. 31
  • 32. Gadgets JavaScript Requesting remote content: 1.The rendered app calls gadgets.io.makeRequest() to fetch remote content. 2.The container requests content from the specified URL. 3.The container returns the response to the application, which renders the data. 32
  • 33. The OpenSocial JavaScript API Representing users: • Client-side, users must work with the VIEWER and the OWNER. 33
  • 34. The OpenSocial JavaScript API Multiple personalities: • When you visit your own profile, you are both the VIEWER and the OWNER. 34
  • 35. The OpenSocial JavaScript API Representing users: • Sometimes, containers allow anonymous browsing. ?? 35
  • 36. The OpenSocial JavaScript API OpenSocial requests: • An OpenSocial DataRequest is created. • Requests are added to the DataRequest. • The DataRequest is sent to the server asynchronously. • When the request finishes, the supplied callback will be called. function request() { var req = opensocial.newDataRequest(); req.add(...); ... req.send(response); }; function response(data) { ... }; gadgets.util.registerOnLoadHandler(request); 36
  • 37. The OpenSocial JavaScript API OpenSocial requests: • An OpenSocial DataRequest is created. • Requests are added to the DataRequest. • The DataRequest is sent to the server asynchronously. • When the request finishes, the supplied callback will be called. function request() { var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest(quot;OWNERquot;), quot;get_ownerquot;); req.add(req.newFetchPersonRequest(quot;VIEWERquot;), quot;get_viewerquot;); req.add(req.newFetchActivitiesRequest(quot;VIEWERquot;), quot;vactivitiesquot;); req.add(req.newFetchPersonAppDataRequest(quot;OWNERquot;, quot;*quot;), quot;odataquot;); ... req.send(response); }; function response(data) { ... }; gadgets.util.registerOnLoadHandler(request); 37
  • 38. The OpenSocial JavaScript API OpenSocial responses: • Responses are bundled according to the keys specified in the request. • Check for an error at the global response level. • Check for an error at the specific response level. • Use getData() to retrieve the actual information in a request. function response(data) { if (data.hadError()) { if (data.get(quot;get_ownerquot;).hadError()) { ... } if (data.get(quot;get_viewerquot;).hadError()) { ... } ... } var owner = data.get(quot;get_ownerquot;).getData(); var viewer = data.get(quot;get_viewerquot;).getData(); }; 38
  • 39. The OpenSocial JavaScript API Working with people: • opensocial.Person - JavaScript representation of a user. 39
  • 40. The OpenSocial JavaScript API Request one person: req.add(req.newFetchPersonRequest(idspec, opt_params), quot;keyquot;); • idspec can be either “VIEWER”, “OWNER” or an ID number. • opt_params contains extra request parameters, such as which profile fields to fetch. newFetchPersonRequest responses: var owner = data.get(quot;keyquot;).getData(); alert(owner.getDisplayName()); • Data contains a single opensocial.Person object. • Person objects can contain lots of information, such as addresses, companies, phone numbers, favorite movies, and thumbnail urls. 40
  • 41. The OpenSocial JavaScript API Methods available on an OpenSocial Person: • getDisplayName() Gets a text display name for this person; guaranteed to return a useful string. • getField(key, opt_params) Gets data for this person that is associated with the specified key. • getId() Gets an ID that can be permanently associated with this person. • isOwner() Returns true if this person object represents the owner of the current page. • isViewer() Returns true if this person object represents the currently logged in user. 41
  • 42. The OpenSocial JavaScript API An OpenSocial Person's fields: • ABOUT_ME • JOB_INTERESTS • SEXUAL_ORIENTATION • ACTIVITIES • JOBS • SMOKER • ADDRESSES • LANGUAGES_SPOKEN • SPORTS • AGE • LIVING_ARRANGEMENT • STATUS • BODY_TYPE • LOOKING_FOR • TAGS • BOOKS • MOVIES • THUMBNAIL_URL • CARS • MUSIC • TIME_ZONE • CHILDREN • NAME • TURN_OFFS • CURRENT_LOCATION • NETWORK_PRESENCE • TURN_ONS • DATE_OF_BIRTH • NICKNAME • TV_SHOWS • DRINKER • PETS • URLS • EMAILS • PHONE_NUMBERS • ETHNICITY • POLITICAL_VIEWS • FASHION • PROFILE_SONG • FOOD • PROFILE_URL • GENDER • PROFILE_VIDEO • HAPPIEST_WHEN • QUOTES • HAS_APP • RELATIONSHIP_STATUS • HEROES • RELIGION • HUMOR • ROMANCE • ID • SCARED_OF • INTERESTS • SCHOOLS 42
  • 43. The OpenSocial JavaScript API Working with people: • A Collection represents many opensocial.Person objects. 43
  • 44. The OpenSocial JavaScript API IdSpec: • idspec is an object that can represent groups of people. var idspec = opensocial.newIdSpec({ quot;userIdquot; : quot;OWNERquot;, quot;groupIdquot; : quot;FRIENDSquot; }); IdSpec can represent only one person: var idspec = opensocial.newIdSpec({ quot;userIdquot; : quot;OWNERquot;, quot;groupIdquot; : quot;SELFquot; }); Or specific data: var idspec = opensocial.newIdSpec({ quot;userIdquot; : quot;1234567890quot;, quot;groupIdquot; : quot;familyquot; }); 44
  • 45. The OpenSocial JavaScript API Request many people: var idspec = opensocial.newIdSpec({ quot;userIdquot; : quot;OWNERquot;, quot;groupIdquot; : quot;FRIENDSquot; }); req.add(req.newFetchPeopleRequest(idspec, opt_params), quot;keyquot;); • Pass an idspec object to the newFetchPeopleRequest function. • opt_params contains extra request parameters, such as which profile fields to fetch, and how to order or filter the returned people. newFetchPersonRequest responses: var owner_friends = data.get(quot;keyquot;).getData(); owner_friends.each(function (person) { alert(person.getDisplayName()); }); • Data contains a Collection of opensocial.Person objects. Iterate over these by using the each() method. 45
  • 46. The OpenSocial JavaScript API Working with data: • Persistent data gives apps key, value storage directly on the container. • String only, but conversion to JSON allows for storage of complex objects. • Storage per app per user - scales well with growth. • Ideal for settings, customizations. 46
  • 47. The OpenSocial JavaScript API Set persistent data: req.add(req.newUpdatePersonAppDataRequest(idspec, key, value)); • idspec can only be “VIEWER”. • key is the name under which this data will be stored. • value is a string representing the data to store. 47
  • 48. The OpenSocial JavaScript API Fetch persistent data: var idspec = opensocial.newIdSpec({ quot;userIdquot; : quot;OWNERquot;, quot;groupIdquot; : quot;SELFquot; }); req.add(req.newFetchPersonAppDataRequest(idspec, keys), quot;keyquot;); req.add(req.newFetchPersonRequest(quot;OWNERquot;), quot;ownerkeyquot;); • idspec is an object that can represent groups of people, the same as newFetchPeopleRequest. • keys is a list of persistent data keys to retrieve the data for. • The owner is requested because the data returned is indexed by user ID and we want the owner’s data. newFetchPersonAppDataRequest responses: var app_data = data.get(quot;keyquot;).getData(); var value = app_data[owner.getId()][key]; 48
  • 49. The OpenSocial JavaScript API Fetch persistent data: • Data is returned as an object indexed by ID number, then as an object indexed by key name, even if there is only data returned for one user! { quot;1234567890quot; : { quot;key1quot; : quot;value1quot; } } • One person, multiple keys: { quot;1234567890quot; : { quot;key1quot; : quot;value1quot;, quot;key2quot; : quot;value2quot; } } • Multiple people: { quot;1234567890quot; : { quot;key1quot; : quot;value1quot; }, quot;2345678901quot; : { quot;key1quot; : quot;value2quot; } } 49
  • 50. The OpenSocial JavaScript API Working with activities: • API to post information about what users are doing with your app. • Many containers have support for images and some HTML. • Channel to grow your application. orkut MySpace hi5 50
  • 51. The OpenSocial JavaScript API Post an activity: function postActivity(text) { var params = {}; params[opensocial.Activity.Field.TITLE] = text; var activity = opensocial.newActivity(params); opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.HIGH, callback); }; • Assign the activity text to the TITLE field. • Call opensocial.newActivity() to create a new Activity instance. • Call opensocial.requestCreateActivity() to post the activity to the container. 51
  • 52. Building apps across containers 52
  • 53. Challenges Cross container development is still tricky: • Containers may not follow the standard. • Containers may follow the standard but have different policies. • Follow best practices: http://tinyurl.com/4nuzll 53
  • 54. Robustness - Be Explicit • Spot the bug in this code! Let's request the owner: function request() { var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest( quot;VIEWERquot;), quot;reqquot;); req.send(response); }; function response(data) { var url = data.get(quot;reqquot;).getData().getField( opensocial.Person.Field.PROFILE_URL)); • And access their profile URL: ... } 54
  • 55. Robustness - Be Explicit • On hi5, url is: http://www.hi5.com/friend/profile/ displayProfile.do?userid=XXXXXXXXXX • On orkut, url is: null • The OpenSocial specification only states the following about fields available on Person objects: quot;The server will always include ID, NAME, and THUMBNAIL_URL.quot;* *http://rurl.org/qoo 55
  • 56. Robustness - Be Explicit • Introducing opensocial.DataRequest .PeopleRequestFields.PROFILE_DETAILS • Assign an array of properties you want to access to this optional parameter var params = {}; params[opensocial.DataRequest .PeopleRequestFields.PROFILE_DETAILS] = [ opensocial.Person.Field.ABOUT_ME, opensocial.Person.Field.ADDRESSES, opensocial.Person.Field.AGE ]; 56
  • 57. Robustness - Be Explicit • Fixing the request: From this... function request() { var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest( quot;VIEWERquot;), quot;reqquot;); req.send(response); }; 57
  • 58. Robustness - Be Explicit • ...to this: function request() { var req = opensocial.newDataRequest(); var params = {}; params[opensocial.DataRequest.PeopleRequestFields .PROFILE_DETAILS] = [ opensocial.Person.Field.PROFILE_URL ]; req.add(req.newFetchPersonRequest( quot;VIEWERquot;, params), quot;reqquot;); req.send(response); }; 58
  • 59. Robustness - Be Explicit • On hi5, url is: http://www.hi5.com/friend/profile/ displayProfile.do?userid=XXXXXXXXXX • On orkut, url is: http://www.orkut.com/ Profile.aspx?uid=YYYYYYYYY 59
  • 60. Robustness - Check For Errors 60
  • 61. Robustness - Check For Errors • Why is the following code brittle? Request a user by ID: function request() { var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest( quot;14088281537290874435quot;), quot;reqquot;); req.send(response); }; • And get the display name: function response(data) { var name = data.get(quot;reqquot;).getData() .getDisplayName(); ... }; 61
  • 62. Robustness - Check For Errors • If the passed ID is invalid for any reason, the previous code throws a JavaScript error: data.get(quot;reqquot;).getData() has no properties • Check for problems! DataRequest.send callbacks get DataResponse arguments with hadError methods: function response(data) { if (!data.hadError()) { var name = data.get(quot;reqquot;).getData() .getDisplayName(); ... } }; 62
  • 63. Robustness - Check For Errors • Inside of these DataResponse objects are nested ResponseItem objects, which also have hadError methods: function response(data) { if (!data.hadError()) { ... } else { if (data.get(quot;reqquot;).hadError()) { ... } } }; • You can check each response individually to see where the point of failure is. 63
  • 64. Robustness - Check For Errors • Handling errors gracefully: function response(data) { if (!data.hadError()) { ... } else if (data.get(quot;reqquot;).hadError()) { alert(data.get(quot;reqquot;).getErrorMessage()); } else { alert(quot;An unknown error occurredquot;); } }; • getErrorMessage() provides a human-readable error message, but varies by container. • This may not be ideal for display to an end user. 64
  • 65. Robustness - Check For Errors • getErrorCode() provides an enum indicating the type of error data.get(quot;reqquot;).getErrorCode() • Check for the type of error and fall back where possible. 65
  • 66. Robustness - Check For Errors • opensocial.ResponseItem.Error.BAD_REQUEST • The request was invalid • opensocial.ResponseItem.Error.FORBIDDEN • The gadget can never have access to this data • opensocial.ResponseItem.Error.INTERNAL_ERROR • Server problem • opensocial.ResponseItem.Error.LIMIT_EXCEEDED • Over quota • opensocial.ResponseItem.Error.NOT_IMPLEMENTED • No container support 66
  • 67. Robustness - Check For Errors • Check for error types at runtime: function response(data) { if (!data.hadError()) { ... } else if (data.get(quot;reqquot;).hadError()) { switch (data.get(quot;reqquot;).getErrorCode()) { case opensocial.ResponseItem.Error.BAD_REQUEST: ... break; case opensocial.ResponseItem.Error.INTERNAL_ERROR: ... break; } } else { ... 67
  • 68. Robustness - Check For Errors • Not all errors need to be fatal! • An appropriate response to UNAUTHORIZED would be to call opensocial.requestPermission() switch (data.get(quot;reqquot;).getErrorCode()) { case opensocial.ResponseItem.Error.UNAUTHORIZED: opensocial.requestPermission( [ quot;VIEWERquot; ], quot;Share a gift with your friendquot;, callback); break; } 68
  • 69. Robustness - Off Track For A Second • While you can react to an UNAUTHORIZED error, there’s also the opensocial.hasPermission()method, which you can check before making the request: var has_permission = opensocial.hasPermission( opensocial.Permission.VIEWER); • has_permission will be boolean true or false 69
  • 70. Robustness - Check For Errors • Let’s go back to that requestPermission call: opensocial.requestPermission( [ opensocial.Permission.VIEWER ], “Share a gift with your friend”, callback); • callback will be called when this request completes and get a ResponseItem as a parameter. • What happens if the container doesn’t support requestPermission? 70
  • 71. Robustness - Check For Errors • Unimplemented methods will get an NOT_IMPLEMENTED error code: function callback(data) { if (!data.hadError()) { ... } else { switch(data.getErrorCode()) { case opensocial.ResponseItem.Error.NOT_IMPLEMENTED: ... break; } } }; 71
  • 72. Robustness - Check For Errors • A container may not implement any method and still remain spec compliant as long as they return the NOT_IMPLEMENTED error code. • This applies to any method where the callback receives a DataResponse or ResponseItem, including: • requestCreateActivity • requestPermission • requestSendMessage • requestShareApp • all new*Request calls • So be sure to check for such cases! 72
  • 73. Robustness - Check For Support 73
  • 74. Robustness - Check For Support • Containers have different purposes. Not every field may be available. opensocial.Person.Field.LOOKING_FOR • hi5: not supported • MySpace: not supported • orkut: supported MyOpenSpace.Person.Field.DESIRE_TO_MEET • hi5: not supported • MySpace: supported • orkut: not supported hi5.PersonField.PRESENCE • hi5: supported • MySpace: not supported • orkut: not supported 74
  • 75. Robustness - Check For Support • Your impulse may be to write code like this: if (MySpace) { ... } else if (hi5) { ... } else if (orkut) { ... } else { ... } • This is brittle! How do you scale to new containers automatically? 75
  • 76. Robustness - Check For Support • Sounds like a job for capabilities querying: var supports_lookingfor = opensocial.getEnvironment().supportsField( opensocial.Environment.ObjectType.PERSON, opensocial.Person.Field.LOOKING_FOR); • Now supports_lookingfor has the following value: • on hi5: false • on MySpace: false • on orkut: true • Goal: Build apps that programatically utilize extra functionality based on such booleans • Why is this approach brittle? 76
  • 77. Robustness - Check For Support • Try a container-specific profile field: var supports_desiretomeet = opensocial.getEnvironment().supportsField( opensocial.Environment.ObjectType.PERSON, MyOpenSpace.Person.Field.DESIRE_TO_MEET); • Now supports_desiretomeet has the following value: • on hi5: JavaScript error • on MySpace: true • on orkut: JavaScript error • Oops! 77
  • 78. Robustness - Check For Support • What about: var supports_desiretomeet = false; if (MyOpenSpace) { var supports_desiretomeet = opensocial.getEnvironment().supportsField( opensocial.Environment.ObjectType.PERSON, MyOpenSpace.Person.Field.DESIRE_TO_MEET); } • Now supports_desiretomeet has the following value: • on hi5: false • on MySpace: true • on orkut: false • This approach defeats the purpose of querying! 78
  • 79. Robustness - Check For Support • You should be able to see that: var supports_desiretomeet = false; if (MyOpenSpace) { var supports_desiretomeet = opensocial.getEnvironment().supportsField( opensocial.Environment.ObjectType.PERSON, MyOpenSpace.Person.Field.DESIRE_TO_MEET); } • Is really the same as: var supports_desiretomeet = (MyOpenSpace) ? true : false; 79
  • 80. Robustness - Check For Support • Remember, we don't want to write code like this: if (MyOpenSpace) { ... } else if (hi5) { ... } else { ... } • Apps should query by capability, not container name 80
  • 81. Robustness - Check For Support • Don't do this: var env = opensocial.getEnvironment(); var supports_presence = env.supportsField( opensocial.Environment.ObjectType.PERSON, hi5.PersonField.PRESENCE); var supports_desiretomeet = env.supportsField( opensocial.Environment.ObjectType.PERSON, MyOpenSpace.Person.Field.DESIRE_TO_MEET); var supports_lookingfor = env.supportsField( opensocial.Environment.ObjectType.PERSON, opensocial.Person.Field.LOOKING_FOR); 81
  • 82. Robustness - Check For Support • A workaround is to ignore the enums and go for string representations: var env = opensocial.getEnvironment(); var supports_presence = env.supportsField( opensocial.Environment.ObjectType.PERSON, quot;presencequot;); var supports_desiretomeet = env.supportsField( opensocial.Environment.ObjectType.PERSON, quot;DESIRE_TO_MEETquot;); var supports_lookingfor = env.supportsField( opensocial.Environment.ObjectType.PERSON, quot;lookingForquot;); 82
  • 83. Robustness - Check For Support Wait a sec, isn’t this a worst practice? 83
  • 84. Robustness - Check For Support • Thankfully, the specification addresses this issue: “Extra person, activity or other object fields should be defined in an enum under the container's namespace, and the environment should allow applications to discover these fields.” 84
  • 85. Robustness - Check For Support • Thankfully, the specification addresses this issue: “For example, if the field orkut.PersonField.SPECIAL_FIELD is defined as 'orkut.specialPersonField', then opensocial.getEnvironment().supportsField( quot;personquot;, quot;orkut.specialPersonFieldquot;) and opensocial.getEnvironment().supportsField( opensocial.Environment.ObjectType.PERSON, orkut.PersonField.SPECIAL_FIELD) should both return true.”* *http://rurl.org/qr4 85
  • 86. Robustness - Check For Support • We now have runtime access to capabilities across all containers: hi5 MySpace orkut supports_presence TRUE FALSE FALSE supports_desiretomeet FALSE TRUE FALSE supports_lookingfor FALSE FALSE TRUE • Drawback: Now we have to be sensitive to the underlying string value for Profile field enums 86
  • 87. Robustness - Check For Support • Now, instead of: • Use: if (MyOpenSpace) { if (supports_presence) { ... ... } else if (hi5) { } ... if (supports_desiretomeet) { } else { ... ... } } if (supports_lookingfor) { ... } 87
  • 89. Resources • OpenSocial Tutorial: http://rurl.org/ss3 • OpenSocial Spec, Foundation, Reference: http://opensocial.org • Caja: http://code.google.com/p/google-caja/ • Shindig: http://incubator.apache.org/shindig/ • OpenSocial Across Containers video: http://tinyurl.com/4nuzll • OpenSocial Templates: http://ostemplates-demo.appspot.com/ • OpenSocial Dev App: http://osda.appspot.com • Partuza: http://partuza.nl • OpenSocial Specification Proposals: http://groups.google.com/group/opensocial-and-gadgets-spec/topics 89
  • 90. Hacking! Beginner (http://is.gd/7W05): • Write a gadget to display quot;Hello Worldquot; in your favorite container. • Display a list of your friends. • Display the OWNER's favorite movies. • Post an activity update. • Write an app that uses AppData to store preferences (http://is.gd/7W0g) Intermediate: • Make an app that works on two containers using the same XML. • Use makeRequest to list the OWNER's favorite movies and information from a web API such as amazon.com or imdb.com • Write a gift giving app using AppData: (http://is.gd/7W0v) Advanced: • Write a server-side app that uses the Java (http://is.gd/7W0E) or PHP (http://is.gd/7W0K) client libraries. 90