メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2009年7月22日水曜日

[Apache Shindig][お勉強][OpenSocial] メモ66 DataRequest.newUpdatePersonAppDataRequestのサーバ側実装をしてみる(1)

AppDataを扱うメソッドのうち、


Object newUpdatePersonAppDataRequest(id, key, value)
# 指定した個人のアプリケーション フィールドを更新するように要求するアイテムを作成します。

をやってみる。

まずはガジェットXML。
gooディベロッパーキッチンを見ながら作った。

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="AppData">
<Require feature="opensocial-0.8" />
</ModulePrefs>
<Content type="html" view="home,profile,canvas">
<![CDATA[
<script type="text/javascript">
function updateAppData() {
/*====================================================================*/
/* これから保存したいオブジェクト */
/*====================================================================*/
var obj = {'param1':'データだよーん', 'param2':'だよーんデータ'};
/*====================================================================*/
/* オブジェクトを文字列に変換(OpenSocial推奨らしい) */
/*====================================================================*/
var strObj = gadgets.json.stringify(obj);

/*====================================================================*/
/* DataRequest生成、セットアップ */
/*====================================================================*/
var req = opensocial.newDataRequest();
req.add(req.newUpdatePersonAppDataRequest(
opensocial.IdSpec.PersonId.VIEWER,
'key',
strObj),
'get_response');
/*====================================================================*/
/* 送信! */
/*====================================================================*/
req.send(function(response){
var result = response.get('get_response');
if (result.hadError()) {
document.getElementById('result').innerHTML = '失敗したよー:'
+ result.getErrorMessage();
} else {
document.getElementById('result').innerHTML
= 'newUpdatePersonAppDataRequest成功';
}
});
}
function getAppData() {
var idspec = new opensocial.IdSpec();
idspec.setField(opensocial.IdSpec.Field.USER_ID, opensocial.IdSpec.PersonId.VIEWER);
idspec.setField(opensocial.IdSpec.Field.GROUP_ID, opensocial.IdSpec.GroupId.SELF);

var req = opensocial.newDataRequest();
/*====================================================================*/
/* まずVIEWERを取得 */
/*====================================================================*/
req.add(
req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER),
'get_viewer');
/*====================================================================*/
/* APPDATA取得のリクエストを生成 */
/*====================================================================*/
req.add(
req.newFetchPersonAppDataRequest(idspec, 'key'),
'get_appdata');
/*====================================================================*/
/* 送信 */
/*====================================================================*/
req.send(function(response){
var viewer = response.get('get_viewer');
if (viewer.hadError()) {
document.getElementById('result').innerHTML = 'Viewerの取得に失敗したよー:'
+ viewer.getErrorMessage();
} else {
var appdata = response.get('get_appdata');
if (appdata.hadError()) {
document.getElementById('result').innerHTML = 'AppDataの取得に失敗したよー:'
+ appdata.getErrorMessage();
} else {
if (appdata.getData()[viewer.getData().getId()]) {
/*============================================================*/
/* VIEWER固有のAppData取得 */
/*============================================================*/
var srcObj = appdata.getData()[viewer.getData().getId()];
/*============================================================*/
/* unescape */
/*============================================================*/
var jsonStr = gadgets.util.unescapeString(srcObj);
var jsonObj = gadgets.json.parse(jsonStr);
document.getElementById('result').innerHTML = jsonObj['param1'] + '<br />' + jsonObj['param2'];
} else {
document.getElementById('result').innerHTML = 'がちょーん';
}
}
}
});
}
function removeAppData() {
var req = opensocial.newDataRequest();
req.add(
req.newRemovePersonAppDataRequest(opensocial.IdSpec.PersonId.VIEWER, 'key'),
'get_response');
/*====================================================================*/
/* 送信 */
/*====================================================================*/
req.send(function(response){
var result = response.get('get_response');
if (result.hadError()) {
document.getElementById('result').innerHTML = 'appDataの削除に失敗したよー:'
+ result.getErrorMessage();
} else {
document.getElementById('result').innerHTML = '削除したよー';
}
});
}
</script>
<div id="result"></div>
<input type="button" value="更新" onclick="updateAppData()" /><br />
<input type="button" value="取得" onclick="getAppData()" /><br />
<input type="button" value="削除" onclick="removeAppData()" /><br />
]]>
</Content>
</Module>


というか、サンプルのまんま。

で、Gadgetを表示させてみて、表示されたボタンのうち「更新」ボタンを押下してみる。
今のところ、サーバ側では、java.lang.UnsupportedOperationException
を投げるようにしてあるんで、やっぱりjava.lang.UnsupportedOperationExceptionがスローされる。

スタックトレースは、

java.lang.UnsupportedOperationException
at jp.qsdn.gms.social.service.AppDataServiceImpl.updatePersonData(AppDataServiceImpl.java:62)
at org.apache.shindig.social.opensocial.service.AppDataHandler.create(AppDataHandler.java:106)
at org.apache.shindig.social.opensocial.service.AppDataHandler.update(AppDataHandler.java:78)

な感じ。
AppDataHandlerからAppDataServiceをimplementsしたAppDataServiceImplの
updatePersonDataがコールされる模様。

今のところのAppDataServiceImplは以下な感じ。

package jp.qsdn.gms.social.service;

import org.apache.shindig.auth.SecurityToken;
import org.apache.shindig.protocol.DataCollection;
import org.apache.shindig.protocol.ProtocolException;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

import org.apache.shindig.social.opensocial.spi.AppDataService;
import org.apache.shindig.social.opensocial.spi.UserId;
import org.apache.shindig.social.opensocial.spi.GroupId;
import org.apache.shindig.auth.SecurityToken;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* AppDataServiceの実装
*/
public class AppDataServiceImpl implements AppDataService {
protected final Log logger = LogFactory.getLog(AppDataServiceImpl.class);

public Future<DataCollection> getPersonData(Set<UserId> userIds, GroupId groupId,
String appId, Set<String> fields, SecurityToken token) throws ProtocolException {
throw new UnsupportedOperationException();
}

public Future<Void> deletePersonData(UserId userId, GroupId groupId,
String appId, Set<String> fields, SecurityToken token) throws ProtocolException {
throw new UnsupportedOperationException();
}
/**
* Updates app data for the specified user and group with the new values.
*
* @param userId The user
* @param groupId The group
* @param appId The app
* @param fields The fields to filter the data by. Empty set implies all
* @param values The values to set
* @param token The security token
* @return an error if one occurs
*/
public Future<Void> updatePersonData(UserId userId, GroupId groupId,
String appId, Set<String> fields, Map<String, String> values, SecurityToken token)
throws ProtocolException {
if (logger.isDebugEnabled()) {
logger.debug("userId:[" + userId + "]");
logger.debug("userId2:[" + userId.getUserId(token) + "]");
logger.debug("groupId:[" + groupId + "]");
logger.debug("appId:[" + appId + "]");
for (String field: fields) {
logger.debug("field:[" + field + "]");
}
for (String key: values.keySet()) {
logger.debug("key:[" + key + "] value:[" + values.get(key) + "]");
}
}
throw new UnsupportedOperationException();
}
}



で、ログはこんな感じ。

[リクエスト:[22256969]] 2009-07-22 01:40:16,912 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - userId:[VIEWER]
[リクエスト:[22256969]] 2009-07-22 01:40:16,912 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - userId2:[Guest]
[リクエスト:[22256969]] 2009-07-22 01:40:16,914 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - groupId:[SELF]
[リクエスト:[22256969]] 2009-07-22 01:40:16,914 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - appId:[http://localhost/opensocial/hello.xml]
[リクエスト:[22256969]] 2009-07-22 01:40:16,915 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - field:[key]
[リクエスト:[22256969]] 2009-07-22 01:40:16,915 DEBUG jp.qsdn.gms.social.service.AppDataServiceImpl - key:[key] value:[{"param1":"データだよーん","param2":"だよーんデータ"}]



ログインしないで「更新」ボタンを押下したんで、userId2がGuest(Anonymous)になっている。
普通、GuestからのAppData保存はどうするんだろう。。

たぶん、認証してないよエラーを返すのが正解な気がする。

それは置いといて、
fieldとvaluesの関係がよくわからない。

values中のfieldsキーが示すデータを保存すればよいのかなぁ。。

ちなみに、POSTリクエスト時のデータは、

[{"method":"appdata.update","params":{"userId":["@viewer"],"groupId":"@self","appId":"@app","data":{"key"

:"{\"param1\":\"データだよーん\",\"param2\":\"だよーんデータ\"}"},"fields":"key"},"id":"get_response"}]

な感じ。

--
どうも、AppDataServiceDB.javaによると、
values中のfieldsで指定されたキーの値を、fieldsで指定されたキーで保存するみたい。


.

0 コメント: