By Takayuki Kobayashi 2011年12月12日 Leave a Comment

Play! framework 1.2.3 CRUD モジュールを拡張したJQCRUD

さて、Play! framework Advent Calendar 2011 jp #play_ja の13日目。さすがに Play 2.0 の話題が多い中、まだ1.xでがんばっています。
Play との出会いは、知人(@d_noguchi)に java で Rails みたいなことができるものってないの?
と聞いたところ、「Play framework があるよ、ただ自分は Scala のほうに興味がありますが・・・」、といわれて触り始めました。
もともと生産性の高い(?)Java 言語だけに、堅牢性や冗長性、などが考慮されいるフレームワークはほかにないのではないでしょうか。

今回は標準でサポートされている CRUD モジュールを拡張し、jQuery 対応をした JQCRUD を作ってみました。
Play framework JQCRUD デモサイト(更新OK!)

JQCRUD モジュールを作成

Play! framwork の利点の一つとして豊富なモジュール(本家)があげられると思います。
また、このモジュールが結構簡単に作成できてしまいます。

クラスメソッド開発ブログ
Play frameworkのいろいろなモジュール番外編 –Play Moduleを作成してみるその1

これだけでモジュールのプロジェクトのテンプレートを作成できます。

play new-module jqcrud

その後、build.xml が作成されるので、それをもとに eclipse でプロジェクトをインポートします。

当初は Play アプリケーションで実装を進めていたのですが、リファクタリングとしてモジュール化を行いました。

CRUD.java を継承し、追加(含オーバーライド)したメソッドは4つ。
index(), list(), listTable(), showJson(), createJson() です。
主に JSON 系の処理を追加しています。

処理は CRUD とほぼ一緒で html を返却するのではなく、JSON を返却するようにしています。
この辺りも Play のメリットで、renderJSON() メソッドを使うことで簡単に JSON 対応できてしまいます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package controllers;
 
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import play.data.binding.Binder;
import play.db.Model;
import play.exceptions.TemplateNotFoundException;
import play.i18n.Messages;
 
public class JQCRUD extends CRUD {
 
    // テンプレートをJQCRUD用に変更。(他は変更なし)
    public static void index() {
        if (getControllerClass() == CRUD.class) {
            forbidden();
        }
        try {
            render();
        } catch (TemplateNotFoundException e) {
            render("JQCRUD/index.html");
        }
    }
 
    // テンプレートをJQCRUD用に変更。(他は変更なし)
    public static void list(int page, String search, String searchFields, String orderBy, String order) {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        if (page < 1) {
            page = 1;
        }
        List<Model> objects = type.findPage(page, search, searchFields, orderBy, order, (String) request.args.get("where"));
        Long count = type.count(search, searchFields, (String) request.args.get("where"));
        Long totalCount = type.count(null, null, (String) request.args.get("where"));
        try {
            render(type, objects, count, totalCount, page, orderBy, order);
        } catch (TemplateNotFoundException e) {
            render("JQCRUD/list.html", type, objects, count, totalCount, page, orderBy, order);
        }
    }
 
    // テンプレートをJQCRUD用に変更。(他は変更なし)
   public static void listTable(int page, String search, int size, String searchFields, String orderBy, String order) {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        if (page < 1) {
            page = 1;
        }
        List<Model> objects = type.findPage(page, search, searchFields, orderBy, order, (String) request.args.get("where"));
        Long count = type.count(search, searchFields, (String) request.args.get("where"));
        Long totalCount = type.count(null, null, (String) request.args.get("where"));
        try {
            render(type, objects, count, totalCount, page, orderBy, order);
        } catch (TemplateNotFoundException e) {
            render("JQCRUD/listTable.html",type, objects, count, totalCount, page, orderBy, order);
        }
    }
 
    // ここは新規に作成。
    public static void showJson(String id) {
        ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
        Model object = type.findById(id);
        notFoundIfNull(object);
        renderJSON(object);
    }
 
    // ここは新規に作成。
    public static void createJson(String id) throws Exception {
    	ObjectType type = ObjectType.get(getControllerClass());
        notFoundIfNull(type);
 
        Model object = null;
        if("new".equals(id)) {
            Constructor<?> constructor = type.entityClass.getDeclaredConstructor();
            constructor.setAccessible(true);
            object = (Model) constructor.newInstance();
        } else {
            object = type.findById(id);
            notFoundIfNull(object);
        }
        Binder.bind(object, "object", params.all());
        validation.valid(object);
        if (validation.hasErrors()) {
            renderArgs.put("error", Messages.get("crud.hasErrors"));
            Map<String,String>	result = new HashMap<String,String>();
            result.put("result", "validation error");
            result.put("message", Messages.get("crud.hasErrors"));
            renderJSON(result);
        }
        object._save();
        Map<String,Object>	result = new HashMap<String,Object>();
        result.put("result", "OK");
        result.put("message", Messages.get("crud.created", type.modelName));
        result.put("id ", object._key());
        renderJSON(result);
    }
}

JQCRUD を使用する Play! アプリケーションの作成

使い方も CRUD とほぼ一緒です。

CRUD: Administration generator

  1. アプリケーションにモジュールを追加
    module.jqcrud=${play.path}/modules/jquery_crud
    module.crud=${play.path}/modules/crud
  2. routes 設定を追加
    *		/admin									module:jqcrud
  3. モデルクラスを作成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    package models;
     
    import javax.persistence.Entity;
    import play.db.jpa.Model;
     
    @Entity
    public class Customer extends Model {
    	public	String	name;
    	public	String	kana;
    	public	String	address;
    	public	String	sex;
    	public	String	age;
    	public	String	birth;
    	public	String	married;
    	public	String	bloodtype;
    	public	String	pref;
    	public	String	tel;
    	public	String	mobile;
    	public	String	carrer;
    }
  4. コントローラクラスを作成
    1
    2
    3
    4
    5
    
    package controllers;
     
    import models.Customer;
     
    public class Customers extends JQCRUD {}
  5. テンプレートを作って細工
    CRUD モジュールと同様です。list.html に対して、表示するフィールドを指定します。message ファイルも設定しているため、日本語表示されています。

    #{jqcrud.table fields:['name', 'kana', 'address', 'sex', 'age', 'pref'] /}

  6. 実行確認

    検索での絞り込み、ソート、表示、編集、をすることができます。
    Play JQCRUD デモサイト(更新OK!)

デモサイトには Customer というモデルを作成しています。

検索一覧までは見た目はかわりません。(実際に検索自体は JSON でやり取りしてます。)

データは「なんちゃって個人情報」を使って csv で5,000件作成。
データのローディングは OpenCSV を使って取り込み。(詳細は OpenCSVを使ってみた を参照 )
(ここも Play module を使いたかったのですが、今回は見送り)

まとめ

今回すべてのソースを公開しなかった理由としては、まだ完全に対応しきれていないことがあげられます。ある程度まとまったところで github にでも入れようと思います。残ってしまったのが、以下3つ。

  1. 細かい jQuery 側の設定。
    例えばダイアログのサイズの自動設定や、ブラウザ内のダイアログ表示の位置など。
  2. Ajax Validation
    ここまで Ajax の対応をしたので、ValidationもAjaxで、と考えていました。「Ajax validation for the Play! framework」を取り込もうと思ったのですが、時間切れ。また次の機会に。
  3. Google Appengine 対応
    本当は Appengine で動かしたかったのですが、時間が足りず断念。
    ただ、crudsiena モジュールの対応となるので、それほど大変ではないかと思います。時間があればやりたいと思います。
  4. JQCURD モジュールのコマンド対応
    テンプレート作成時に使います。現状は CRUD のコマンドが動作してしまいます。詳しく調べられていませんが、おそらく Python のプログラムを修正することになるのではないかと思います。

Play framerok は、もともと groovy も触っていたので入りやすかったです。使い込むことで非常に魅力的で、よく考えられていることが想像できました。もう一度 java を見直そうと本気で思いました。またいろいろと情報を載っけていきたいと思いますので、ぜひこのブログのフィードを購読してくださいね!

次は 12/14、@daiksy さんです。




Sorry, the comment form is closed at this time.

Sorry, the comment form is closed at this time.