Play Framework でフォームを扱う(オウム返しアプリを作ろう)

前回の記事(↓)を踏まえて、今度は投稿フォームを利用したアプリ(オウム返しアプリ)をPlay Framework で作ってみる。

Play Framework で「Hello World!!」 - hirahiro56のブログ

作るアプリの機能としては、ユーザがフォームに入力した文字列をそのまま表示するだけのオウム返しアプリで実用性は無いものであるが、今後作るチャットアプリの基礎となるものである。

それでは、このオウム返しアプリを実現するのには、どの様なものを実装すれば良いのかを考えよう。
必要なものは下記の通りである。
つまり、入出力画面2つと、それぞれのリクエスト(URL)を処理するためのコントローラ2つの合計4つのモジュールを作成する必要がある。

・ユーザの入力を受け付けるView
・文字列を出力するView
・入力を受け付ける画面へアクセスする際のリクエスト(URL)を処理するコントローラ
・入力画面で入力内容を投稿した後に出力用のView へ画面遷移する際のリクエストを処理するコントローラ

早速順番に実装して行こう。実装の順番は私自身が実装する手順をそのまま記載することとする。

1. ルーティングの設定(routesファイルの設定)
ユーザの入力を受け付ける画面にアクセスするURLを"/inputchat" とし、routes ファイルに下記の通り記載しよう。

GET     /inputchat                  controllers.Application.inputchat()

この設定により、ユーザがブラウザでhttp://localhost:9000/inputchatのURLでアクセスすると、
"controllers.Application.inputchat()"が呼び出されるようになる。
次に、この"controllers.Application.inputchat()"を実装していく。

2. Controller の実装
controllers => Application.java を開いて下記の通りinputchat メソッドを実装する。

package controllers;

import play.mvc.Controller;
import play.mvc.Result;
import views.html.*; //要注意!!

public class Application extends Controller {
  //中略
    public static Result inputchat() {
        return ok(inputchat.render("InputChatForm"));
    }

}

Eclipse でエラーが出てしまうが、取りあえずは無視で良い。import 文を修正していることに注意。
因みにEclipse の機能でimport 文が勝手に修正されてしまう場合は、Eclipse のウィンドウ => 設定 => Java => 保管アクションの設定で、
インポートの編成のチェックを外しておけば良い。

続いて、"inputchat.render()" で呼び出されるView の実装に入る。

3. ユーザの入力を受け付けるViewの実装
HTML(Scala)ファイルが無ければ始まらないので、viewsパッケージ以下に「inputchat.scala.html」を作成し、
以下の通り編集する。取りあえずガワだけ用意する。

■inputchat.scala.html

@(message: String)

This resource is @message.

ここまでできたら、
http://localhost:9000/inputchat
にアクセスして、"This resource is InputChatForm."とブラウザ上に表示されればOKである。

次に、この画面(inputchat.scala.html)に入力フォームを配置してみよう。
そのためにはちょっとしたお作法があるので最初は慣れないと思うが、Play Framework 以外のフレームワークでも共通する作法となるので、
徐々に慣れていって欲しい。

4. フォームクラスを定義
Play Framework でフォームを利用する際(他のJava フレームワークでも同様だが)、フォームクラスというものを定義する。
なぜ、このようなクラスを定義するかというと、ブラウザ上のフォームの内容をJavaオブジェクトとして扱えるという利点があるのだが、
ピンとこない場合は「お作法なのね。」「便利なのね。」と軽い気持ちで理解しておけば、後々分かってくるであろう。

それでは早速フォームクラスを定義するのだが、app以下にformsというパッケージを作成し、
下記の通りユーザがインプットする内容をフィールド値として持つようなクラスを定義する。

■PostChatForm.java

package form;

import javax.persistence.*;
import java.util.*;
import play.data.validation.Constraints.*;
import play.data.validation.Constraints;

public class PostChatForm {
	public String postMessage;
	
	public void setPostMessage(String postMessage){
		this.postMessage = postMessage;		
	}
	
	public String getPostMessage(){
		return this.postMessage;		
	}

}

次にコントローラの中で下記の通り実装し、View へForm の型を通知する。

■Application.java

package controllers;

import play.*;
import play.mvc.*;
import play.mvc.Http.Context;
import models.*;

import views.html.*;
import play.mvc.Http.MultipartFormData;
import play.data.*;
import static play.data.Form.*;
import java.util.*;
import forms.*;

public class Application extends Controller {

    public static Result index() {
        return ok(index.render("Your new application is ready."));
    }

    public static Result inputchat() {

    	//フォームを定義
		Form<PostChatForm> postChatForm = new Form(PostChatForm.class);

        return ok(inputchat.render("InputChatForm",postChatForm));
    }

}


続いて、View 側で上記Controller から渡されたForm の型を受け取り、Play Framework のフォームヘルパーを用いて下記の通り実装する。

■inputchat.scala.html

@(message: String, postchatform: Form[forms.PostChatForm])

@import helper._

This resource is @message.

@form(routes.Application.index()) {
	@inputText(postchatform("postMessage"))
}

ここまでできたら、
http://localhost:9000/inputchat
へアクセスしてフォームが配置されていることを確認してみよう。
生成されたフォームのコードはブラウザのソースを表示から確認できるが、
下記コードによりフォーム用のHTMLを自動生成してくれていることが分かると思う。

@form(routes.Application.index()) {
	@inputText(postchatform("postMessage"))
}

5. フォーム内容表示画面の開発
まずは、上記作成したView を下記の通り書き換える。

@(message: String, postchatform: Form[forms.PostChatForm])

@import helper._

This resource is @message.

@form(routes.Application.postchat()) {
	@inputText(postchatform("postMessage"))
}

これにより、フォームを入力し投稿するとhttp://localhost:9000/postchatというURLでリクエストが飛ぶようになる。
それでは、このリクエスト"/postchat"に対する処理を実装していこう。
まずは、routesファイルを下記の通り記載する。
■routes

GET     /postchat                   controllers.Application.postchat()

次に、Application.java に、上記ルーティングに呼び出されるpoctchat()メソッドを追加する。
ここでのポイントは、FormクラスのbindFromRequest() でフォームの内容をインスタンス化するところである。フォームのname属性とFormクラスのフィールド名が同一であれば、フォームの値でフィールドを初期化されたFormクラスがインスタンス化される点である。
これは、今後多用するので覚えておきたい。

    public static Result postchat(){
    	//フォームの内容を取得して、PostChatFormクラスのインスタンスに格納する。
    	Form<PostChatForm> postChatForm = new Form(PostChatForm.class).bindFromRequest();
    	
    	//フォームの内容をpostMessageに代入する。
    	String postMessage = postChatForm.get().getPostMessage();

        return ok(postchat.render(postMessage));
    }

最後に、views以下に下記の投稿メッセージ出力用Viewを用意する。


■postchat.scala.html

@(postmessage:String)

@postmessage

ここまでできたら、下記URLにアクセスし、動作を確認してみよう。
フォームに入力した内容がそのままオウム返しされるはずだ。

http://localhost:9000/inputchat