WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

OpenSocial 0.9 の OSAPI 仕様を和訳してみました

4 月に公開された OpenSocial 0.9 では JavaScript API が大幅に強化され、「OSAPI」という軽量 API が新たに追加されました。 OpenSocial 0.8.1 までの JavaScript API はちょっと形式ばっていて使いづらかったのですが、この OSAPI はより JavaScript らしい形式で簡単に呼び出せるのが特徴です。例えば従来の API でビュアーの名前を表示するには、以下のようにする必要がありました。

var req = opensocial.newDataRequest();
req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
req.send(function(response) {
  alert(response.get('viewer').getData().getDisplayName());
});

これが OSAPI では以下のように単純化されます。

osapi.people.getViewer().execute(function(response) {
  alert(response.displayName);
});

とても簡単になっているのがおわかりいただけるでしょう。もちろんユーザー情報だけでなく Activity や AppData なども同様に取得・設定できます。 OpenSocial ガジェットの作成が格段に楽しくなりそうですね。

OpenSocial 0.9 については私も最近キャッチアップし始めたばかりなので、今回は勉強も兼ねて OSAPI Specification を(かなり適当に ^^;)翻訳してみました。 OSAPI の概要を知るには最適の文書だと思いますので、ぜひ参考にしていただければと思います。各メソッドの詳細な使い方は JavaScript API Reference に掲載されているので、そちらも併せてご利用ください。

また、まだ OpenSocial 0.9 に対応したコンテナは数少ないので、私の知る限り唯一正式対応している Friend Connect を利用して実験ページを作ってみました。

Google Friend Connect Console

私の JavaScript Console ガジェット に OSAPI feature を読み込ませて Friend Connect に埋め込んだだけの手抜き環境ですが、簡単に OSAPI の各機能が試せるようになっています。以下で出てくるサンプルソースを、ぜひ実際に動かしてみてください。

概要

OS Lite もしくは OS API は、 OpenSocial ガジェットを作成するための、 Javascript 開発者にとってより自然で簡潔な軽量 Javascript API です。この API は既存の JsonRpc プロトコルハンドラを利用し、シンプルな JSON オブジェクトを入出力に使用することを特徴としています。注:この実装は JsonRpc 仕様に1対1で従っていますが、 REST 上に実装することも可能です。

互換性のため従来の JS API もまだ利用可能ですが、もし開発者が新しい API に移行すれば、 1.0 のタイムフレームでそれらを廃止することを検討するかもしれません。

ハイライト

  • データリクエストに署名する標準的な方法を導入する - JSON 入力、 JSON 出力
  • 入出力パラメータがJsonRpc 呼び出しと1対1対応し、そのドキュメントが共用できる。
  • データリクエストが "サービス" オブジェクトの関数のように見える。例えば opensocial.DataRequest.newXXXRequest() ではなく osapi.people.get() のようになる。
  • データリクエストを個別に、またはバッチの一部として呼び出すことができる。
  • osapi 名前空間内に配置されている。

実例

以降の詳細説明をより有意義なものとするために、まず最初に簡単な 3 つの例を示します。

Person リクエスト、最も基本的な例:

osapi.people.getViewer().execute(function(result) {
  alert('Your name is ' + result.name + '!');
});

取得するフィールドを指定する JSON リクエストパラメータオブジェクトを伴う Person リクエスト:

osapi.people.getViewer({fields: ['name', 'birthday']}).execute(function(result) {
  alert('Your name is ' + result.name + '!');
  alert('Your birthday is ' + result.birthday + '!');
});

Person と Activity を取得するバッチリクエスト:

var batch = osapi.newBatch().
    add("viewer", osapi.people.getViewer()).
    add('activities', osapi.activities.get({ userId : '@viewer', groupId : '@self'}));
 
batch.execute(function(result) {
  alert('Hi, ' + result.viewer.name + '!');
  alert('You have ' + result.activities.length + ' activities.');
});

注 : バッチ呼び出しはカスケードできます。 newBatch() 呼び出しがバッチを返し、それによりリクエストの追加と実行が簡単に行えます。

OSAPI の特徴

すべての機能を osapi.* 名前空間に配置しています。これは短い名前空間なのでタイプしやすく、そして既存のAPIとは異なっているので、古いAPIと共存できます。ガジェットにすべての feature を require するには、以下のようにします:

<Require feature="osapi"/>

これは osapi.base, osapi.people, osapi.activities, osapi.appdata, osapi.ui のラッパー feature です。

  • osapi - すべての OSAPI feature を簡単に取り込める包括的な feature です。
  • osapi.base - 基本的な feature で、他の feature から利用されます。これには io やバッチ処理機能が含まれています。通常、開発者が直接 include することはありません。
  • osapi.people - People feature は、ユーザー情報へのアクセスを提供します。
  • osapi.activities - Activity feature は、アクティビティーの取得と作成機能を提供します。
  • osapi.appdata - AppData featureは、 appdata の取得、設定、削除を提供します。
  • osapi.ui - ui ダイアログ、 requestShareApp 、 requestSendMessage など、コンテナの助けを必要とする feature のコレクションです。これらの呼び出しはバッチ化できないことに注意してください。

API が構造化される方法に注目すると、このような呼び出しもできます。

  • osapi['SERVICE'] - もし 'SERVICE' という名前の任意のサービスがサーバーで利用可能であり、そしてクライアントで定義されていれば、それを返します。もしあなたが望むなら osapi['people'] で people にアクセスできますが、 osapi.people のほうがより適切です。独自サービスの追加については以降の osapi.newJsonRequest を参照してください。

クライアントで利用可能な feature は javascript を配信するサーバーで決定されます。ガジェットサーバーが osapi ライブラリをレンダリングするときに、 SystemHandler の listMethods エンドポイントが呼び出され、利用可能なサービスが追加されます。js クライアントは、これを使って、 people.get のようなサービスメソッドを生成します(TODO まだ未実装)。安全なガジェットを書きたい開発者は、サービスとメソッドの存在をそれらを呼び出す前にテストできます。

例:

if (osapi.people.getViewer) {
  osapi.people.getViewer().execute(function(result) {
    alert('Your name is ' + result.name + '!');
  });
}

機能別 OSAPI 関数

osapi.people

people エンドポイントにマップされる関数群を持つオブジェクト。ガジェットで使用するには、以下のように require します:

<Require feature="osapi.people"/>

または

<Require feature="osapi"/>
  • osapi.people.get(params) - people JsonRpc サービスから情報を取得するリクエストを構築します。サーバーの JsonRpc People サービスに渡すリクエストパラメータで構成される JSON オブジェクトを取ります。パラメータを指定されていないときは、サーバのデフォルトである { user : @me, group : @self} が使用されます。これは osapi.newJsonRequest() の上に構築されています。
  • osapi.people.getViewer(params) - より便利な osapi.people.get() で、セキュリティートークンで指定されたビュアーの情報を people JsonRpc サービスから検索するリクエストを構築します。デフォルトリクエストを変更するための省略可能なパラメータセットを引数にとります。注: このメソッドは people.get のショートカットです。
  • osapi.people.getViewerFriends(params) - セキュリティートークンで指定されたビュアーの友達情報を people JsonRpc サービスから検索するリクエストを構築します。デフォルトリクエストを変更する省略可能なパラメータセットを引数にとります。注: このメソッドは people.get のショートカットです。
  • osapi.people.getOwner(params) - セキュリティートークンで指定されたオーナーの情報を people JsonRpc サービスから検索するリクエストを構築します。デフォルトリクエストを変更する省略可能なパラメータセットを引数にとります。注: このメソッドは people.get のショートカットです。
  • osapi.people.getOwnerFriends(params) - セキュリティートークンで指定されたオーナーの友達情報を people JsonRpc サービスから検索するリクエストを構築します。デフォルトリクエストを変更する省略可能なパラメータセットを引数にとります。注: このメソッドは people.get のショートカットです。
  • osapi.people.get.execute(callback) - 上記のすべての関数が返すオブジェクトにエクスポートされる、サーバーにサービスリクエストを実行させる関数です。レスポンスを処理するためのコールバックを引数にとります。

例:

osapi.people.get({userId: '@owner', groupId: '@friends'}).execute(function(ownerFriends) {
  alert('You have ' + ownerFriends.length + ' friends');
});

osapi.activities

activities エンドポイントにマップされる関数群を持つオブジェクトです。

<Require feature="osapi.activities"/>

または

<Require feature="osapi"/>

関数:

  • osapi.activities.get(params) - activities get エンドポイントにマップされます。activity JSON オブジェクトの配列を返します。
  • osapi.activities.create(params) - activities create エンドポイントにマップされます。これは osapi.ui.requestCreateActivity 呼び出しの UI 無しバージョンです。
  • osapi.activities.get.execute(callback) - 上記のすべての関数が返すオブジェクトにエクスポートされる、サーバーにサービスリクエストを実行させる関数です。レスポンスを処理するためのコールバックを引数にとります。

osapi.appdata

app data エンドポイントにマップされる関数群を持つオブジェクトです。

<Require feature="osapi.appdata"/>

または

<Require feature="osapi"/>

関数:

  • osapi.appdata.get(params) - app data get エンドポイントにマップされます。
  • osapi.appdata.update(params) - app data update エンドポイントにマップされます(すべての app data セットが更新されます)。
  • osapi.appdata.deleteData(params) - app data delete エンドポイントにマップされます。
  • osapi.appdata.get.execute(callback) - 上記のすべての関数が返すオブジェクトにエクスポートされる、サーバーにサービスリクエストを実行させる関数です。レスポンスを処理するためのコールバックを引数にとります。

例 :

osapi.appdata.get({userId: '@viewer', groupId: '@friends', keys: ['gifts']}).execute(myCallback);
osapi.appdata.update({userId: '@viewer', data: {gifts: 'a crazed monkey'}}).execute(myCallback);

osapi.messages

TODO

Batch Functions

シンプルなサービスリクエストや makerequest 呼び出しをバッチ化する関数群です。

<Require feature="osapi.base"/>

または

<Require feature="osapi"/>
  • osapi.newBatch() - 新しい osapi.base.batch リクエストを返します。
  • osapi.base.batch.add(key, request) - 指定されたキーに関連付けられたサービスリクエストをバッチに追加します。 request は osapi.people.get() などの jsonrpc 呼び出し、またはサードパーティーへの osapi.makeRequest 呼び出しのいずれかです。
  • osapi.base.batch.execute(callback) - バッチ内のすべてのリクエストを実行します。コールバックにはそれぞれのリクエストキーを JSON レスポンスオブジェクトにマップした JSON オブジェクトが渡されます。

例:

var batch = osapi.newBatch().
    add("viewer", osapi.people.getViewer()).
    add('activities', osapi.activities.get({ userId : '@viewer', groupId : '@self'})).
 
batch.execute(function(result) {
  alert('Hi, ' + result.viewer.name + '!');
  alert('You have ' + result.activities.length + ' activities.');
});

osapi.makeRequest

  • osapi.makeRequest(url, params) - (現在の) gadgets.io.makeRequest を使った任意の URL へのリクエストを作成します。これは JsonRpc エンドポイントではなく、単なるサードパーティーの web サービスです。
<Require feature="osapi.base"/>

または

<Require feature="osapi"/>

例:

osapi.makeRequest('http://www.somephotosite.com', {userId: '123'}).execute(function(result) {
  alert('You have ' + result.photos.length + ' photos');
});

osapi.ui

コンテナによってインターセプトされ、ユーザーと対話する関数を持つオブジェクトです。これらの呼び出しは UI の表示のためにコンテナにインターセプトされ得るので、バッチ化できないことに注意してください。

<Require feature="osapi.ui"/>

または

<Require feature="osapi"/>

関数:

  • osapi.ui.requestCreateActivity(reason, callback) - もしコンテナがリクエストの処理を許可するなら、 activity.create エンドポイントにマップされます。
  • osapi.ui.requestSendMessage(recipientIds, message, callback) - もしコンテナがリクエストの処理を許可するなら、パラメータに従ってメッセージを送信します。
  • osapi.ui.requestShareApp(recipientIds, reason, callback) - もしコンテナがリクエストの処理を許可するなら、 "recipientIDs" フィールドで指定されたユーザーやグループに、もしくはそれが与えられていなければ受信者をビュアーに選択させて、アプリケーション共有のためのメッセージを送信します。
    • 以下の 2 つの引数(と callback)をとります。
      • recipientIDs: 省略可能なコンマ区切りのエンティティのIDのリストで、そのエンティティーはユーザーもしくはグループにできます。フォーマットの詳細については recipient discussion を参照してください。
      • reason: アプリケーションを共有する理由を説明した文字列で、必須です。
    • もし受信者への共有リクエストがコンテナに承認された場合は success を返します。
      • これは受信者がリクエストを実施したことを保証しないことに注意してください。
    • リクエストが失敗した場合は standard error を返します。
  • osapi.ui.requestPermission(permission, reason, callback) - 追加の許諾をユーザーに促すようにコンテナに要求するメソッドです。
    • 以下の 2 つの引数(と callback)をとります。
      • permissions: 要求する許諾を表すコンマ区切りの文字列リストです。
      • reason: アプリケーションが許諾を求める理由としてコンテナがユーザーに提示する文字列です。

osapi.base

これらの関数群は新しいサービスインターフェースを構築するためのもので、通常はガジェット開発者が利用するものではありません。すべての既存のサービスリクエストは以下の osapi.newJsonRequest() で構築されています。もし写真やアルバムのような新しいサービス実装したいときは、 osapi.people.get の例に従ってください。

<Require feature="osapi.base"/>

もしくは

<Require feature="osapi"/>
  • osapi.newJsonRequest(jsonRpcServiceMethod, options) - これは通常はガジェット開発者が利用するものではありません。これは関数を構築する base json リクエストです。実行可能な JsonRpc リクエストを返します。全ての opensocial サービス (people, activities, appdata) はこの関数で構築されています。"people.get" のようにサーバー上でサービスとメソッドを識別する jsonRpcServiceMethod と、 JsonRpc 仕様で指定されている省略可能な jsonrequest パラメータを引数にとります。サーバーに新しいサービスを追加したときに使うことになるでしょう。
  • osapi.newBatchJsonRequest(jsongenerator, options) - これは通常はガジェット開発者が利用するものではありません。これは osapi.newBatch で使われている、バッチ化のための関数を構築する base json リクエストです。バッチとそれが含むすべてのリクエストのための json を作成する jsonGenerator を取ります。それはまた、サーバーからのレスポンスの後処理を行う requestDataProcessor もとります。これは通常、 json-keyed object property を再構築することと、エラー処理のために必要です。
  • osapi.base.batch.execute(callback) - サーバーへの呼び出しを実行するためにすべての jsonRequest オブジェクトにエクスポートされる関数です。レスポンスを処理するためのコールバックを引数にとります。これは実際のサービスリクエストやバッチリクエストを実行するためにガジェット開発者が利用します。

TODO: supportedFields の動作について説明する。

エラー処理

この api は JSONRPC プロトコルを基盤としているため、エラーハンドリングは厳密にそのインターフェースに沿った動作をします。返される JSON オブジェクトはリクエストで発生した任意のエラーを反映しています。これは 3 つのタイプのエラーに分類されます。

  • ネットワークエラー、これはトップレベルエラーを返します。例えば、コールバックに渡されるオブジェクトが error オブジェクトを保持しています。

例:

osapi.people.get({userId: '@owner', groupId: '@friends'}).execute(function(ownerFriends) {
  if (ownerFriends.error) {
    alert('Error occurred: ' + error.message);
  } else {
    alert('You have ' + ownerFriends.length + ' friends');
  }
});
  • 単一リクエストのアプリケーションエラー

この場合、トップレベルエラーオブジェクトが設定されます。注: 上記のエラーと同様です。

例:

osapi.people.get({userId: '@owner', groupId: '@friends'}).execute(function(ownerFriends) {
  if (ownerFriends.error) {
    alert('Error occurred: ' + error.message);
  } else {
    alert('You have ' + ownerFriends.length + ' friends');
  }
});
  • バッチリクエストのアプリケーションエラー

この場合、トップレベルエラーが設定されますが、もしあれば、成功したすべてのリクエストの結果も返されます。失敗したリクエストにはエラーが設定されます。

例: バッチ内でなんらかのエラーが発生したら処理しない。

var batch = osapi.newBatch().
    add("viewer", osapi.people.getViewer()).
    add('activities', osapi.activities.get({ userId : '@viewer', groupId : '@self'})).
 
batch.execute(function(result) {
  if (result.error) {
    alert("This batch had an error: " + error.message);
  } else {
    alert('Hi, ' + result.viewer.name + '!');
    alert('You have ' + result.activities.length + ' activities.');
  }
});

例: バッチ内で成功したすべてのサブリクエストを処理する。

var batch = osapi.newBatch().
    add('activities', osapi.activities.get({ userId : '@viewer', groupId : '@self'})).
 
batch.execute(function(result) {  
  for (var i =0; i < results.activities.length) {
    if (result.activities[i].error) {
      alert("This activity had an error: " + result.activities[i].error.message);
    } else {
      alert('Activity: ' + result.activities[i].title);
    }
  }
});

Resources

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles