本格派エンジニアの工具箱

第15回「Play Framework」モデル/コントロールをカスタマイズする

コントロールのカスタマイズ

前回に引き続き、Play Framework⁠日本語サイトはこちらの使い方を解説します。Play Frameworkで作成したアプリケーションはモデル/ビュー/コントロールの各パーツから構成され、それぞれプロジェクトのmodels/views/controllersフォルダ内に格納されています。前回はビューの修正を行ったので、今回はまずコントロールをカスタマイズしてみましょう。

デフォルトのコントロールはcontrollersフォルダにApplication.javaとして作成されています。このindex()メソッドがビューのindex.htmlに関連付けられていることは前回説明しました。index()メソッドでは、次のようにrender()メソッドの呼び出しを行っています。これがPlay Frameworkのテンプレートエンジンを利用してWebページのレンダリングを行う処理です。

public static void index() {
    render();
}

render()メソッドにはObject型の引数を渡すことができます。渡した引数は、ビューのテンプレート内で変数として参照することができます。例えば、次のようにrender()にStringの値を渡したとします。

public static void index() {
    String message = "ようこそ、Play Frameworkへ!";
    render(message);
}

この場合、index.html側ではmessageという変数が利用できるようになり、その値はrender()の呼び出し時に設定されていた「ようこそ、Play Frameworkへ!」という文字列となっています。テンプレート内で、変数の値は「${変数名}」で参照できます。message変数の場合には以下のような具合です。

#{extends 'main.html' /}
#{set title:'Play Frameworkの使用例' /}

<h2>Playで作成したアプリケーションです</h2>

<div>${message}</div>

Webブラウザでページをリロードすると、図1のようにコントロールから渡されたmessageの値が表示に反映されていることが確認できます。

図1 messageの値が反映されている
図1 messageの値が反映されている

なお、render()の引数は可変長なので、同時に複数のオブジェクトを渡すことも可能です。

入力フォームとモデルの利用

続いて、モデルとの連携を行ってみましょう。ここでは、フォームから入力された名前とメールアドレスをデータベースに記録していくというアプリケーションを作ってみます。モデルの定義はJavaクラスで行います。次に示すAddressクラスは、名前とメールアドレスをプロパティに持つモデルを定義した例です。

package models;
 
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
 
@Entity
public class Address extends Model {
    public String name;
    public String email;
    
    public Address(String name, String email) {
	this.name = name;
	this.email = email;
    }
}

Play Frameworkでは、モデルの永続化にJPA(Java Persistence API)を利用しています。JPAでは、@Entityアノテーションを使ってデータベースに永続化するエンティティを定義します。Addressクラスが継承しているplay.db.jpa.Modelは、JPAを利用して永続化するクラスの基底クラスになります。作成したAddressクラスはモデルを表すクラスなので、modelsフォルダに配置します。

データベースへの永続化を利用する場合には、confフォルダにある「applocation.conf」ファイルの設定を変更する必要があります。データベースとして付属のH2を利用する場合には、この設定ファイルから「db=mem」と書かれた部分を探して次のようにコメントインしましょう。

# Database configuration
# ~~~~~ 
# Enable a database engine if needed.
#
# To quickly set up a development database, use either:
#   - mem : for a transient in memory database (H2 in memory)
#   - fs  : for a simple file written database (H2 file stored)
db=mem
#
# To connect to a local MySQL5 database, use:
# db=mysql:user:pwd@database_name
#
# If you need a full JDBC configuration use the following :
# db.url=jdbc:postgresql:database_name
# db.driver=org.postgresql.Driver
# db.user=root
# db.pass=secret

この設定だとH2がインメモリーで実行されます。⁠db=fs」とすると、ファイルに記録する形で実行されます。その他、MySQLやPostgreSQLを使う場合には、それぞれデータベースの設定をコメントインして、URLやドライバの設定を行ってください。

さて、フォームからの入力を受け取れるようにビューとコントロールの方も作っていきましょう。まずビューの方は、入力フォームを持ったページのテンプレートを作成する必要があります。以下に例を示します。これを「add.html」として、view/Applicationフォルダに配置しましょう。

#{extends 'main.html' /}
#{set title:'Play Frameworkの使用例' /}

<h1>アドレスの追加</h1>

<form method="post" action="@{Application.add}">
  名前: <input type="text" name="name" /><br/>
  アドレス: <input type="text" name="email" /><br>
  <input type="submit" value="追加" />
</form>

<table border="1">
  <tr><th>名前</th><th>アドレス</th></tr>
  #{list items:addresses, as:'address'}
  <tr><td>${address.name}</td><td>${address.email}</td></tr>
  #{/list}
</table>

上のformタグの部分が入力フォームを表示するためのもので、下のtableタブは記録されたアドレスの一覧を表示するためのものです。まずformタグの方から見ていきます。action属性の値には、⁠@{クラス名.メソッド名}」というフォーマットで、リクエストを処理するコントロールのメソッドを指定します。この例の場合はApplicationクラスのadd()メソッドということになります。名前とメールアドレスを入力するための入力フィールドには、それぞれname属性の値として"name"、"email"を指定しています。これがコントロール側で値を受け取る際の変数名に対応します。

そのApplicationクラスのadd()メソッドは、次のようなコードになります。

public static void add(String name, String email) {
    if ((name!=null && !name.equals("")) || 
	(email!=null && !email.equals(""))) {
	Address address = new Address(name, email);
	address.save();
    }
    
    List<Address> addresses = Address.findAll();
    render(addresses);
}

フォームから送信された値はメソッドの仮引数として渡されます。この仮引数名が、inputタグのname属性の対応付けられているわけです。この例ではnameとemailの値を使ってAddressオブジェクトを生成するようになっています。そしてAddressのsave()メソッド(play.db.jpa.Modelの親クラスであるplay.db.jpa.GenericModelに用意されたメソッドです)を呼び出すことで、作成したオブジェクトをデータベースに記録しています。

findAll()メソッドは、データベースに記録されたAdressの全エンティティを取得し、Listに格納して返すメソッドです。ここでは取得したListをrender()メソッドに渡してテンプレートで利用できるようにしています。

add.htmlのtableタグの部分に戻りましょう。ここで利用している「#{list ●●●}というのは、Listオブジェクトに対応してfor-each(あるいはJavaの拡張for文)のように使うことができる構文です。上の例ではrender()メソッドにadressesという変数名でListオブジェクトが渡されています。この要素それぞれが順番にaddress変数に格納されて処理されるということです。つまり、データベースに記録されている全Addressオブジェクトの名前とメールアドレスを、trタグで順番に出力するということになります。

最後に、add.htmlとApplication.add()メソッドとの関連付けの設定を、confフォルダのroutesファイルに追加します。今回はPOSTメソッドでリクエストを処理しているので、次のようにPOSTの設定を追加する必要があります。

POST     /add                                       Application.add

以上で完成です。Webブラウザで「http://localhost:9000/add」にアクセスすると、最初はデータが登録されていないので図2のように表示されます。フォームから名前とアドレスを追加していくと、図3のようにテーブルに一覧が表示されるようになります。

図2 入力フォームが表示される
図2 入力フォームが表示される
図3 追加されたアドレスはテーブルに一覧表示される
図3 追加されたアドレスはテーブルに一覧表示される

NerBeans/Eclipseでの利用方法

最後に、Play Frameworkで作成したプロジェクトをNetBeansで編集する方法を紹介します。コマンドプロンプトから次のコマンドを実行してください。

> play netbeansify myapp

コマンドが成功すると、myapp/nbprojectフォルダにNetBeans用の設定ファイルが生成されます。これで、myappプロジェクトがNetBeansで開けるようになります。同様に次のコマンドでEclipse用の設定ファイルを作ることもできます。

> play eclipsify myapp

Play Frameworkは、Webアプリケーションを実に軽快に開発できるようにしてくれるフレームワークです。モデル/ビュー/コントロールの分離が明解であることや、それぞれの関連付けがほぼ自動で行われること、プログラム修正後の再配備が不要なこと、オブジェクトの永続化が容易なことなど、多くのメリットがあります。ストレスフリーな開発のために一度試してみる価値のあるツールと言えるでしょう。

おすすめ記事

記事・ニュース一覧