2011年2月10日木曜日

slim3 + JSONICメモ3



前回slim3+JSONICメモ2のエントリーでRESTfulでAjaxなCRUDアプリの実装内容をメモ。
タイトルと説明を入力して登録、一覧リストに表示された行を選択して
編集→更新/削除と動作します。
もちろんデータはBigTableへ反映されています。
こちらからアプリを試せます。

前回と同様にJSONICのRESTサーブレットを使用してコントローラを実装します。
JSONICのRESTサーブレットを使用すると、リクエストからの値をJSON形式で受取る事ができます。
RESTサーブレットが変換してくれます。
そして下記のようなHTTPメソッドに対応したメソッドをコントローラに用意すれば、
javascript側でHTTPメソッドを変えて投げてやれば対応したメソッドを実行してくれます。

GETfind()
POSTcreate()
PUTupdate()
DELETEdelete()
※DELETEのみPOSTでクエリ変数に"?_method=DELETEとします。

使用できるようにするにはweb.xmlに設定が必要です。
前前回のエントリー参照
今回はユニットテストは無視です。

それでは下記の順に作っていきます。

1.IndexController ← (slim3のbuld.xmlで生成。初回アクセス時に呼ばれる)
2.MyReferenceModel ← (永続化するデータモデル)
3.MyReferenceService ← (CRUD処理するサービス)
4.index.jsp ← (アプリケーション画面)
5.MyRefRESTfulController ← (新規に作成するコントローラクラス)
6.common.js ← (クライアント側を制御するjavascript)

1.IndexController


slim3のbuild.xml・gen-controllerを実行し、IndexControllerを生成します。

内容は初回にアクセスされた時、サービスからリストを取得しJSON形式に変換し、
"jsonList"という名前でJSON文字列をリクエストにセットし、"index.jsp"へforwardするだけ。

  1. public class IndexController extends Controller {  
  2.   
  3.     private MyReferenceService service = new MyReferenceService();  
  4.   
  5.     @Override  
  6.     public Navigation run() throws Exception {  
  7.   
  8.         List<myreferencemodel> list = service.getMyReferenceList();  
  9.   
  10.         String jsonData = JSON.encode(list);  
  11.         requestScope("jsonList", jsonData);  
  12.   
  13.         return forward("index.jsp");  
  14.     }  
  15. }  
  16. </myreferencemodel>  

この時点でサービス・モデルはまだないので順次作っていきます。

2.MyReferenceModel


slim3のbuild.xml・gen-modelを実行し、MyReferenceModelを生成します。
生成するとserialVersionUIDとkeyとversionのフィールドのみ出来ています。
今回は下記のようにフィールドを追加しgetter/setterを追加します。

  1. @Model(schemaVersion = 1)  
  2. public class MyReferenceModel implements Serializable {  
  3.   
  4.     private static final long serialVersionUID = 1L;  
  5.   
  6.     @Attribute(primaryKey = true)  
  7.     private Key key;  
  8.   
  9.     @Attribute(version = true)  
  10.     private Long version;  
  11.   
  12.     @Attribute(persistent=false)  
  13.     private String strKey;  
  14.   
  15.     private String title;  
  16.   
  17.     private String description;  
  18.   
  19.     private Date createDate = new Date();  
  20.   
  21. ・・・  
  22.   
  23.     public void setStrKey(String strKey) {  
  24.         this.strKey = strKey;  
  25.         // key文字列を設定  
  26.         if (this.key != null) {  
  27.             this.strKey = KeyFactory.keyToString(this.key);  
  28.         }  
  29.     }  
  30.   
  31. ・・・  
  32.   
  33.     public void setKey(Key key) {  
  34.         this.key = key;  
  35.         // key文字列を設定  
  36.         if (key != null) {  
  37.             this.strKey = KeyFactory.keyToString(key);  
  38.         }  
  39.     }  
  40.   
  41. ・・・  

strKeyフィールドに"@Attribute(persistent=false)"というアノテーションを追加しています。
これはこのフィールドのみ永続化対象としない設定です。
keyとstrKeyのsetterメソッドを少し追加します。

com.google.appengine.api.datastore.Key型を文字列にエンコードして扱う必要があり、
通常のWebアプリケーションであれば、jspではslim3・JSTLファンクション"${f:h(xxx)}"で
KeyをBase64エンコードしたり、コントローラでは"asKey()"メソッドなど使えば簡単に扱えます。
今回はJSONとして送受信したいので、ちょっと現状は簡単に使えなさそうです。
(近いうちにslim3もJSON対応してくるでしょうね。)

なので、JSON内にBase64エンコードされたKey文字列を保持してやる必要があり、
strKeyフィールドを用意しています。(無理矢理な方法ですが)
で、Keyをsetする時にstrKeyも同時に設定する処理を追加しています。


今回はここまでで、次回サービスの実装を行いたいと思います。



参考サイト:
blazedsを使用の内容ですが、modelでKey文字列保持して永続化対象させないところを参考にさせて頂きました。↓↓↓
[blazeds][slim3] アップデート(更新処理)が、できま10(テン)!

2011年2月8日火曜日

slim3 + JSONICメモ2

slim3 + JSONIC でCRUD実装してましたのでメモ。
以前にslim3 + JSONICで試しに作ったものをベースに作りました。

とりあえず動くものはこちら
javascriptでCRUD処理を非同期に行っていて画面遷移が発生しません。

はまったのは、GAE環境ではJSONIC・RESTサーブレットのHTTP/DELETEメソッド送信時、削除処理してくれませんでした。
(ローカルでは普通にDELETEできるのに。)
そこで、JSONIC・RESTサーブレットで用意されている

"PUT/DELETEが使えない場合があります。そのような場合の代替手段として、クエリ変数に「_method=HTTP Method名」を指定することもできます。"


というのを参考に、DELETEの場合のみPOST+クエリ変数追加にして試したところうまくいきました。
これが正解かどうかはわかりませんが。
あとはControllerにfind(),create(Xxxx model),update(Xxxx mode),delete(Xxxx model)を用意。
RESTサーブレットが自動でJSON → JavaBean (model) へ変換して、HTTPメソッドを判断し各メソッドへ振分けてくれます。

下記が非同期REST送受信javascriptです。
(jqueryとjquery.jsonというライブラリを使用する前提です)
  1. ...  
  2.   
  3. /** 非同期処理 */  
  4. function sendJSON(method, jsonval, actionURI, displayId, delURI) {  
  5.  // 一覧取得URI設定  
  6.  var getURI = actionURI;  
  7.  // delURIが存在する場合「削除処理」と判断  
  8.  if (delURI != undefined) actionURI = delURI;  
  9.  $.ajax({  
  10.   type:method,  
  11.   url:actionURI,  
  12.   contentType:"application/json",  
  13.   data:jsonval,  
  14.   cache:false,  
  15.   success:function(data){displayMessage(getURI,displayId);}  
  16.   });  
  17. }  
  18. /** 登録を行います */  
  19. function createSend(form, actionURI, displayId) {  
  20.  sendJSON("POST", createJSON(form), actionURI, displayId);  
  21. }  
  22. /** 更新を行います */  
  23. function updateSend(form, actionURI, displayId) {  
  24.  sendJSON("PUT", createJSON(form), actionURI, displayId);  
  25. }  
  26. /** 削除処理を行います */  
  27. function deleteSend(form, actionURI, displayId) {  
  28.  var delURI = actionURI+"?_method=DELETE";  
  29.  // HTTP/DELETEメソッドが使用できなさそうなのでクエリ変数へDELETE設定  
  30.  sendJSON("POST", createJSON(form), actionURI, displayId, delURI);  
  31. }  
  32. /** formの内容をJSON形式に変換 */  
  33. function createJSON(form) {  
  34.  var form = $("#" + form);  
  35.  var param = {};  
  36.  $(form.serializeArray()).each(function(i,v){param[v.name] = v.value;});  
  37.  var jsonval = $.toJSON(param);  
  38.  return jsonval;  
  39. }  
  40. ...  

実装の中身は次のエントリーで書いていこうと思います。

あと、RESTサーブレットを使用するとslim3コントローラを使用しない為、
ユニットテストが出来ないということになります。
せっかく標準で用意されていて、簡単にテストが行えるのでなんとかしてテストできないか考えないと...。
ていうかRESTfulに実装しなければいいのか。

2011年2月7日月曜日

Eclipse プラグイン開発セミナー受講してきました

ので後々の為にメモ。

講師の方が資料をアップして下さっていました。
この資料がとても分かりやすく、セミナーを受講していない人でも
ある程度簡単に単純なEclipseプラグインができてしまうと思います。

普段仕事でEclipseとEclipseプラグインを使用してjavaを書いていましたが、
自分の慣れた使い方しかしていない事に気づきました。

プラグイン・スパイとか勉強になりました。

ありがとうございました。m(_ _)m

何かプラグイン作ったらブログにのせていこうと思います。