yojikのlog

yojikのブログです

Click勉強のつづき。3ファイルでつくるTODOアプリ

昨日の続きで、簡単なTODOアプリをつくってみた。ちょい長めのエントリになる*1
まずはEntity。これは普通のEJB3用のPOJO。

package yojik.sample.domain;
import javax.ejb.*;
import java.io.*;
import javax.persistence.*;
@Entity
public class TodoItem {
    @Id @GeneratedValue
    Long id;
    String contents;
    Boolean done = false;
    public TodoItem(){}
    public String getContents() {
        return contents;
    }
    public void setContents(String contents) {
        this.contents = contents;
    }    
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Boolean getDone() {
        return done;
    }
    public void setDone(Boolean done) {
        this.done = done;
    }
}

アクセサがかったるいけどしょーがない。OGNLとかVelocityで必要だし。
つぎがPageクラス。画面用のウィジェット(Control)とイベントハンドラで構成されてて分かりやすい。一部でEntityとFormの相互変換をしているところがあるけど、ここがシンプルで面白い(onEditLinkとonEditSubmitのあたり)。

package yojik.sample.web;
import yojik.sample.domain.*;
import net.sf.click.Page;
import net.sf.click.control.*;
import java.util.*;
import javax.persistence.*;

public class TodoList extends Page {
    
    @PersistenceContext
    public EntityManager em;
    
    Form form = new Form("form");
    Form editForm = new Form("editForm");
    ActionLink editLink = new ActionLink("editLink", this, "onEditLink");
    ActionLink deleteLink = new ActionLink("deleteLink", this, "onDeleteLink");
   
    public void onInit() {
        addControl(form);
        form.add(new TextField("addField", ""));
        form.add(new Submit("addButton", "add", this, "onAdd"));
        addControl(editForm);
        editForm.add( new HiddenField("id", Long.class));
        editForm.add( new Checkbox("done"));
        editForm.add( new TextField("contents"));
        editForm.add( new Submit("editSubmit", "submit", this, "onEditSubmit"));
        addControl(editLink);
        addControl(deleteLink);
    }
    public void onGet() {
        Query q  =  em.createQuery("from TodoItem i where i.done = :done");
        addModel("items",     q.setParameter("done",false).getResultList());
        addModel("doneItems", q.setParameter("done",true).getResultList());
    }
    public boolean onAdd() {
        setRedirect("/todoList.htm");
        String todo = form.getField("addField").getValue();
        if(todo==null || todo.trim().equals(""))  return false;
        TodoItem item = new TodoItem();
        item.setContents(todo);
        em.persist(item);
        return false;
    }
    public boolean onEditLink() {
        addModel("currentEditID" , editLink.getValueLong());
        TodoItem item = em.find(TodoItem.class, editLink.getValueLong());
        if(item!=null) editForm.copyFrom(item);
        return true;
    }
    public boolean onDeleteLink() {        
        TodoItem item = em.find(TodoItem.class, deleteLink.getValueLong());
        if(item!=null) em.remove(item);
        setRedirect("/todoList.htm");
        return false; 
    }    
    public boolean onEditSubmit() {
        TodoItem item = new TodoItem();
        editForm.copyTo(item, true);
        if(item.getId() != null) em.merge(item);
        setRedirect("/todoList.htm");
        return false; 
    }    
}

最後がViewとなるテンプレート。これがちと苦手なんだよなぁ。

#macro(display_items $entries) 
  #if ($entries)
  <div>
   #foreach( $i in $entries) 
    <div>
      <span>[<a href="$editLink.getHref($i.id)">edit</a>/<a href="$deleteLink.getHref($i.id)">delete</a>]</span>
      <span>$i.contents</span>
      <div>
	#if( $currentEditID == $i.id )
	<div style="background-color:lightgray">$editForm</div>
	#end
      </div>
    </div>
   #end
  </div>
  #end
#end

<html>
  <head>
    <title>My todo list</title>
    $imports
  </head>
  <body>
    <h2>TodoList:</h2>
    $form
    <hr />
    <h3>NotDone:</h3>
    <p>
      #if($items)
      #display_items($items)
      #end
    </p>
    <hr />
    <h3>  Done:  </h3>
    <p>
      #if($items)
      #display_items($doneItems)
      #end
    </p>
    <hr />
  </body>
</html>

これだけ。
残りはclickの設定ファイルにautoマッピングの設定しとくだけ*2。ちなみに画面はこんな感じになる。

インフラさえ整ってしまえば、Struts*3による開発よりも何十倍も早く作れる。テケトーなプロトタイピングもばっちり。かなり惚れてきた。流行らせたいなぁClick。
どの程度の規模の開発で使えるか見極めたい。ちなみに性能面では素のJSPより早いらしいです。このフレームワークではHTTPSessionを殆ど使ってないのもポイント高い。
あとPageをRhino等で記述できるようにしたら、さらにラピッドな開発ができるようになるかも。あとで考えてみる。

*1:ブログとしてはの話で、ソースはめっちゃ短い

*2:あとPersistence関連も必要か

*3:毎回引き合いに出して申し訳ないけど