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等で記述できるようにしたら、さらにラピッドな開発ができるようになるかも。あとで考えてみる。