データストアを使ったカウンターサーブレットのサンプル
ドキュメントを見ながら、データストアを使ったカウンターのサンプルを作ってみました。
カウンタの値を格納するクラス
データストアでは、Java Data Objects(JDO)の標準インターフェイスを介して、任意のエンティティ(アノテーションが付与されたPOJO)を永続化できます。カウンターをつくるので、まずはカウンタの値を格納するエンティティを作成します。
package test; import javax.jdo.annotations.IdentityType; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; /* * カウンタの値 */ @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Count { // インスタンスは1つなのでプライマリーキーは固定 @PrimaryKey private String id = "count"; @Persistent private Integer value = 0; public String getId() { return id; } public void setId(String id) { this.id = id; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } }
カウンターサーブレット
あとは、カウンタ値を読み込んで更新するサーブレットを作ればOK。
- PersistenceManagerを生成して、
-
- カウンタの値を取得。
- 値があれば、インクリメントして更新します。
- 値がなければ新規に生成して保存します。
-
- これらを1トランザクションで行います。トランザクションはこのあたりを参考にして書いてみました。
package test; import java.io.IOException; import javax.jdo.JDOHelper; import javax.jdo.JDOObjectNotFoundException; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; import javax.jdo.Transaction; import javax.servlet.http.*; @SuppressWarnings("serial") public class CounterServlet extends HttpServlet { /** * GETメソッドを処理する。 */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/plain"); PersistenceManager pm = null; try { // PersistenceManager を取得 pm = getPersistenceManager(); // トランザクション Transaction tx = pm.currentTransaction(); try { tx.begin(); // トランザクション開始 Count c = null; try { // 値クラスのインスタンスを取り出す。 c = pm.getObjectById(Count.class, "count"); c.setValue(c.getValue()+1); // 値があればインクリメント } catch ( JDOObjectNotFoundException e ) { // 初回のアクセスで値がない場合、ここに来る。 c = new Count(); } // 更新 pm.makePersistent(c); // 値を表示する。 resp.getWriter().println("count :" + String.valueOf( c.getValue() )); tx.commit(); // コミット } finally { if (tx.isActive()) tx.rollback(); } } finally { // PersistenceManager はクローズ必須。 if ( pm != null ) pm.close(); } } /** * {@link PersistenceManager}を取得する。 * @return {@link PersistenceManager} */ public static PersistenceManager getPersistenceManager() { return pmfInstance.getPersistenceManager(); } /** * {@link PersistenceManagerFactory}は作成コストが高いらしいのでアプリケーションごとに一意にすること。 * 本来は専用のホルダクラスを用意するのがよいみたいだが、とりあえずサーブレット自身に持たせる。 */ private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); }