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

2009年7月22日水曜日

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

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

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

をやってみる。

まずはガジェットXML。
gooディベロッパーキッチンを見ながら作った。
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <Module>  
  3.   <ModulePrefs title="AppData">  
  4.     <Require feature="opensocial-0.8" />  
  5.   </ModulePrefs>  
  6.   <Content type="html" view="home,profile,canvas">  
  7.     <![CDATA[ 
  8.     <script type="text/javascript"> 
  9.     function updateAppData() { 
  10.       /*====================================================================*/ 
  11.       /* これから保存したいオブジェクト                                     */ 
  12.       /*====================================================================*/ 
  13.       var obj = {'param1':'データだよーん', 'param2':'だよーんデータ'}; 
  14.       /*====================================================================*/ 
  15.       /* オブジェクトを文字列に変換(OpenSocial推奨らしい)                   */ 
  16.       /*====================================================================*/ 
  17.       var strObj = gadgets.json.stringify(obj); 
  18.  
  19.       /*====================================================================*/ 
  20.       /* DataRequest生成、セットアップ                                      */ 
  21.       /*====================================================================*/ 
  22.       var req = opensocial.newDataRequest(); 
  23.       req.add(req.newUpdatePersonAppDataRequest( 
  24.         opensocial.IdSpec.PersonId.VIEWER, 
  25.         'key', 
  26.         strObj), 
  27.         'get_response'); 
  28.       /*====================================================================*/ 
  29.       /* 送信!                                                             */ 
  30.       /*====================================================================*/ 
  31.       req.send(function(response){ 
  32.         var result = response.get('get_response'); 
  33.         if (result.hadError()) { 
  34.           document.getElementById('result').innerHTML = '失敗したよー:' 
  35.             + result.getErrorMessage(); 
  36.         } else { 
  37.           document.getElementById('result').innerHTML 
  38.             = 'newUpdatePersonAppDataRequest成功'; 
  39.         } 
  40.       }); 
  41.     } 
  42.     function getAppData() { 
  43.       var idspec = new opensocial.IdSpec(); 
  44.       idspec.setField(opensocial.IdSpec.Field.USER_ID,  opensocial.IdSpec.PersonId.VIEWER); 
  45.       idspec.setField(opensocial.IdSpec.Field.GROUP_ID, opensocial.IdSpec.GroupId.SELF); 
  46.  
  47.       var req = opensocial.newDataRequest(); 
  48.       /*====================================================================*/ 
  49.       /* まずVIEWERを取得                                                   */ 
  50.       /*====================================================================*/ 
  51.       req.add( 
  52.         req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), 
  53.         'get_viewer'); 
  54.       /*====================================================================*/ 
  55.       /* APPDATA取得のリクエストを生成                                      */ 
  56.       /*====================================================================*/ 
  57.       req.add( 
  58.         req.newFetchPersonAppDataRequest(idspec, 'key'), 
  59.         'get_appdata'); 
  60.       /*====================================================================*/ 
  61.       /* 送信                                                               */ 
  62.       /*====================================================================*/ 
  63.       req.send(function(response){ 
  64.         var viewer = response.get('get_viewer'); 
  65.         if (viewer.hadError()) { 
  66.           document.getElementById('result').innerHTML = 'Viewerの取得に失敗したよー:' 
  67.             + viewer.getErrorMessage(); 
  68.         } else { 
  69.           var appdata = response.get('get_appdata'); 
  70.           if (appdata.hadError()) { 
  71.             document.getElementById('result').innerHTML = 'AppDataの取得に失敗したよー:' 
  72.               + appdata.getErrorMessage(); 
  73.           } else { 
  74.             if (appdata.getData()[viewer.getData().getId()]) { 
  75.               /*============================================================*/ 
  76.               /* VIEWER固有のAppData取得                                    */ 
  77.               /*============================================================*/ 
  78.               var srcObj = appdata.getData()[viewer.getData().getId()]; 
  79.               /*============================================================*/ 
  80.               /* unescape                                                   */ 
  81.               /*============================================================*/ 
  82.               var jsonStr = gadgets.util.unescapeString(srcObj); 
  83.               var jsonObj = gadgets.json.parse(jsonStr); 
  84.               document.getElementById('result').innerHTML = jsonObj['param1'] + ' 
  85. ' + jsonObj['param2']; 
  86.             } else { 
  87.               document.getElementById('result').innerHTML = 'がちょーん'; 
  88.             } 
  89.           } 
  90.         } 
  91.       }); 
  92.     } 
  93.     function removeAppData() { 
  94.       var req = opensocial.newDataRequest(); 
  95.       req.add( 
  96.         req.newRemovePersonAppDataRequest(opensocial.IdSpec.PersonId.VIEWER, 'key'), 
  97.         'get_response'); 
  98.       /*====================================================================*/ 
  99.       /* 送信                                                                */ 
  100.       /*====================================================================*/ 
  101.       req.send(function(response){ 
  102.         var result = response.get('get_response'); 
  103.         if (result.hadError()) { 
  104.           document.getElementById('result').innerHTML = 'appDataの削除に失敗したよー:' 
  105.             + result.getErrorMessage(); 
  106.           } else { 
  107.           document.getElementById('result').innerHTML = '削除したよー'; 
  108.         } 
  109.       }); 
  110.     } 
  111.     </script> 
  112.     <div id="result"></div> 
  113.     <input type="button" value="更新" onclick="updateAppData()" /> 
  114.  
  115.     <input type="button" value="取得" onclick="getAppData()" /> 
  116.  
  117.     <input type="button" value="削除" onclick="removeAppData()" /> 
  118.  
  119.     ]]>  
  120.   </Content>  
  121. </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は以下な感じ。
  1. package jp.qsdn.gms.social.service;  
  2.   
  3. import org.apache.shindig.auth.SecurityToken;  
  4. import org.apache.shindig.protocol.DataCollection;  
  5. import org.apache.shindig.protocol.ProtocolException;  
  6.   
  7. import java.util.Map;  
  8. import java.util.Set;  
  9. import java.util.concurrent.Future;  
  10.   
  11. import org.apache.shindig.social.opensocial.spi.AppDataService;  
  12. import org.apache.shindig.social.opensocial.spi.UserId;  
  13. import org.apache.shindig.social.opensocial.spi.GroupId;  
  14. import org.apache.shindig.auth.SecurityToken;  
  15.   
  16. import org.apache.commons.logging.Log;  
  17. import org.apache.commons.logging.LogFactory;  
  18.   
  19. /** 
  20.  * AppDataServiceの実装 
  21.  */  
  22. public class AppDataServiceImpl implements AppDataService {  
  23.   protected final Log logger = LogFactory.getLog(AppDataServiceImpl.class);  
  24.   
  25.   public Future<DataCollection> getPersonData(Set<UserId> userIds, GroupId groupId,  
  26.       String appId, Set<String> fields, SecurityToken token) throws ProtocolException {  
  27.     throw new UnsupportedOperationException();  
  28.   }  
  29.   
  30.   public Future<Void> deletePersonData(UserId userId, GroupId groupId,  
  31.       String appId, Set<String> fields, SecurityToken token) throws ProtocolException {  
  32.     throw new UnsupportedOperationException();  
  33.   }  
  34.   /** 
  35.    * Updates app data for the specified user and group with the new values. 
  36.    * 
  37.    * @param userId  The user 
  38.    * @param groupId The group 
  39.    * @param appId   The app 
  40.    * @param fields  The fields to filter the data by. Empty set implies all 
  41.    * @param values  The values to set 
  42.    * @param token   The security token 
  43.    * @return an error if one occurs 
  44.    */  
  45.   public Future<Void> updatePersonData(UserId userId, GroupId groupId,  
  46.       String appId, Set<String> fields, Map<String, String> values, SecurityToken token)  
  47.       throws ProtocolException {  
  48.     if (logger.isDebugEnabled()) {  
  49.       logger.debug("userId:[" + userId + "]");  
  50.       logger.debug("userId2:[" + userId.getUserId(token) + "]");  
  51.       logger.debug("groupId:[" + groupId + "]");  
  52.       logger.debug("appId:[" + appId + "]");  
  53.       for (String field: fields) {  
  54.         logger.debug("field:[" + field + "]");  
  55.       }  
  56.       for (String key: values.keySet()) {  
  57.         logger.debug("key:[" + key + "] value:[" + values.get(key) + "]");  
  58.       }  
  59.     }  
  60.     throw new UnsupportedOperationException();  
  61.   }  
  62. }  


で、ログはこんな感じ。

[リクエスト:[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 コメント: