Play Framework でMySQL を利用する(環境構築)
Play Framework でMySQL を利用するための環境を構築していく。
http://dev.mysql.com/downloads/mysql/
にアクセスし、
インストーラ「mysql-installer-community-5.6.22.0.msi」をダウンロードする。
(※)32-bit と書いてあるが、64-bit マシンであってもインストーラは同じ。
2. MySQL のインストール
(a) 上記msiファイルを実行する。
(b) License Agreement で同意して Next
(c) Setup Type ⇒ Full を選択
(d) Check Requirements でStatus にManual と記載されているもの以外を選択しExecute を押下
⇒ 必要なライブラリ一式をとってきてよしなにしてくれる。
(e) Installation でExecuteを押下
※いくつかセットアップに失敗すると思うが、特に気にせず進めてOK
(f) Configuration でNextを押下
(g) Type and Networking では、Development Machine を選択。後はデフォルトでOK。
(h) Accounts and Roles でroot(管理者) パスワードを設定する。
(i) Accounts and Roles でAdd User を押下してユーザ(一般ユーザ)を作成する。
ユーザ名: chatapp
Role: DB Admin ※開発環境なので管理者権限を与えることとする。
(j) Windows Service で Next を押下
(k) Apply Server Configuration でExecute を押下
(l) Product Configuration でNext を押下
(m) Connect To Server でCheck ⇒ Next の順で押下
(n) Execute を押下
後は取りあえずNext とFinish を押下していけばOK。
3. スキーマを作成する。
先ほどchatapp というユーザを作成したが、このユーザが保有するスキーマを作成する。
MySQL Workbench を起ち上げて、root ユーザのコネクション(パネル)をダブルクリックする。
左側のNavigator のSCHEMASフィールドを右クリックして「Create Schema」を押下し、
Schema Nameを「chatapp」として、スキーマを作成すr。
4. コネクションの追加(接続設定)
最後に先ほど作成したchatappユーザ(スキーマ)向けのコネクション(接続設定)を追加する。
MySQL Workbench を起ち上げて、MySQL Connections のプラス(+)ボタンを押下する。
立ち上がった接続設定画面で、下記の通り設定する。
Connection Name: chatapp
Username: chatapp
Default Schema: chatapp
以上でMySQLのソフトウェアのセットアップは完了で、Workbench からchatapp ユーザでアクセスできるようになったはずだ。非常にEasy だったと思うがこれでいいのだ。
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にアクセスし、動作を確認してみよう。
フォームに入力した内容がそのままオウム返しされるはずだ。
Play Framework で「Hello World!!」
Play Framework の環境構築については、
id: hidemium の下記記事を参照されたい。
Play Framework(Java)の開発環境を構築する - hidemium's blog
上記手順でEclipse 上にPlay Framework のプロジェクトが作成された状態からスタートする。
何はともあれ、お決まりの「Hello World !!」アプリを作っていこう。
作成したプロジェクトのappフォルダ以下のviews => index.scala.html を
以下の様に編集しよう。
■index.scala.html
@(message: String)
Hello World!!
上記コードを保存し下記URLでアクセスしてみよう。
http://localhost:9000/
これで、無事「Hello World!!」 が表示されたはずだ。
Play Framework の世界へようこそ。
ところで、何も説明せずに「Hello World!!」を作ってみたが、簡単に処理の流れを説明する。
まず、ユーザのhttp://localhost:9000/に対するリクエストがどの様に処理されるかを順を追って説明する。
(1) フレームワークの入口はroutesファイル
ユーザのhttp://localhost:9000/に対するリクエストにより、どのようなプログラムが呼び出されるかは、
routes ファイルを見れば分かる。
※Java EE 開発の経験があるならば、このroutes ファイルが web.xml に相当するものと理解して良い。
プロジェクトフォルダ => app => conf => routes ファイルを参照すると、
下記の記載があるはずだ。
■routes
GET / controllers.Application.index()
"/" つまり、http://localhost:9000/にアクセスした場合、「controllers.Application.index()」を呼び出すと
読むことができる。
次に「controllers.Application.index()」がどこで実装されているかを説明する。
(2) リクエストの受け手(Controller)
app => controllers => Application.java を見て欲しい。
package controllers; import play.*; import play.mvc.*; import views.html.*; public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); } }
当該クラスで index() というメソッドが定義されている。つまり、先ほどのroutes ファイルに従って呼び出されるメソッドは、このApplication.index()メソッドとなる。
つまり、
http://localhost:9000/
というURLでアクセスするとApplication.index()メソッドが呼び出される流れとなる。
(3) ブラウザへ表示するためのView
Application.index() の下記記載を見て欲しい。
return ok(index.render("Your new application is ready."));
上記行により、ブラウザで表示するHTMLを作成するプログラム(View)の「index.scala.html」が呼び出され、その結果ブラウザ上に「Hello World!!」が表示されるのである。
■index.scala.html
@(message: String)
Hello World!!
(4) Controller からView への値の受け渡しについて
下記コードのindex.render(***)の引数を見て欲しい。ここで、"Your new application is ready." という文字列をView に渡している。
return ok(index.render("Your new application is ready."));
それでは、この文字列をView 側で受け止めて表示してみよう。下記の通りView を編集する。
■index.scala.html
@(message: String)
@message <br>
Hello World!!
同様にhttp://localhost:9000/にアクセスしてみよう。
すると、ブラウザに"Your new application is ready."の文字列が表示されるはずだ。
View 側では、
@(message: String)
で、コントローラ側からString 型の文字列を受け取り、message という変数に代入する。
そして、@message により代入した(コントローラから渡された)文字列を出力する。
ここで、お気づきだろうが、Play Framework ではView はScala で記載される。
@で始まる文字列はPlay Framework により、Scala 文法に従って解釈される。
※Java EE 開発におけるJSP に相当するものである。
以上が、Play Framework における処理の流れである。
Java EE開発とは少々勝手が違うが、今後より複雑なアプリを作成することでPlay Framework の開発手法に慣れて欲しい。
Strutsを読む ~6日目: initInternal() の機能(結局のところ) ~
ActionServlet#init()#initInternal() では、結局のところ、
ActionResources*.properties の内容をkey - value 形式(HashMap)で
インスタンス化することが目的。
実際に読み込んでる箇所は、
PropertyMessageResources.loadLocale() の部分になることが分かった。
Debug 仕込んでこのメソッドが呼び出されているのは確実だが、
なぜこのメソッドが呼び出されるのかが未だ不明。。。
コンストラクタの中にも含まれていないのに。。。
まさか、internal.getMessage(*)で読み込んでるのか???
Strutsを読む ~5日目: ちょっとPending ファクトリを理解する。~
いきなり、ActionServlet#init()#initInternal()でつまずいた。
ただ、このメソッドの目的がKey=Value形式のPropertiesファイルをHashMap形式(MessageResources)のクラスにインスタンス化することがわかった。
「オブジェクト脳のつくり方」のp53までを読んでファクトリとやらを
噛みしめるべし。
Strutsを読む ~ 4日目: defaultFactory.createResources("org.apache.struts.action.ActionResources") ~
掲題のメソッドは抽象クラスで下記の通り定義されている。
public abstract MessageResources createResources(String config);
これを実装しているものが、PropertyMessageResourcesFactory クラスになり、
下記の通りコーディングされている。
#####################################################
public MessageResources createResources(String config) {
PropertyMessageResources messageResources =
new PropertyMessageResources(this, config, this.returnNull);
String mode = null;
if (getConfig() != null) {
mode = getConfig().getProperty("mode");
}
messageResources.setMode(mode);
return messageResources;
}
#####################################################
Strutsを読む ~3日目: ActionServlet#init()~
テーマ: initInternal() は何をするメソッド?
<深度:1>コードとしては、下記の通りで、ActionResources.propertiesの内容をインスタンス化する。
#########################################################
protected String internalName = "org.apache.struts.action.ActionResources";
protected MessageResources internal = null;
protected void initInternal(){
internal = MessageResources.getMessageResources(internalName);
}
#########################################################
<深度:2>MessageResourcesクラスを読み解く
MessageResources.getMessageResources("org.apache.struts.action.ActionResources");
実装 ↓ ※下記2行が何をしているかを読み解く。
MessageResourcesFactory defaultFactory = MessageResourcesFactory.createFactory();
return defaultFactory.createResources("org.apache.struts.action.ActionResources");
まずは、
<深度:3>MessageResourcesFactoryはどういうクラス?
所謂ファクトリパターンにおいてオブジェクトを生成するクラス。
ファクトリパターンの利用シチュエーションとしては、
たとえば、条件によってデータファイルの読み込みに使うオブジェクトが異なる場合、
CSV形式であればCSVDataReaderオブジェクトを、XML形式であれば
XMLDataReaderオブジェクトを生成するような場合に利用する。
ファクトリクラスでは、オブジェクトの生成のみを行います。
オブジェクト生成の専門家であるファクトリが、オブジェクトの使用者から生成するオブジェクトの種類や生成手順を隠してくれます。
オブジェクトの使用者はファクトリに生成を依頼するだけで、オブジェクトの生成手順や種類を意識する必要はなく、望むオブジェクトを使用できる状態で手に入れることができる。
結局下記メソッドが何をやっているかを読み解くのが鍵。
defaultFactory.createResources("org.apache.struts.action.ActionResources");