プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

【Java】 Play!Framework 試してみた(その3)

実際に、いろいろと使い始めて気づいたことを雑多になりますが、まとめておきます。

過去にやった記事はこちらです。

 

【Java】 Play!Framework 試してみた

【Java】 Play!Framework 試してみた(続き)

 

なお、元記事とは違い、ここでは、Play! Framework 2.1.1 を使いました。

 

EBeanのユニーク制約について

Play Frameworkを使ってみた vol.6 にあるように、エンティティの先頭で指定するようです。

 

@Entity
@Table(uniqueCOnstraints = @UniqueConstraint(name="code"))
public class Vehicle extends Model {
 ・・・
} 

 

 

外部キー制約について

Play frameworkのDB操作を楽にするEBeanの基礎知識 の記事は非常に重宝しています。特に、テーブル間に親子関係がある場合の例がうれしかったです。

ですが、単にテーブル間に外部キー制約を設けたいだけなら、下記の参考資料のようにすれば良いことがわかりました。

 

(参考)

Play!Framework をインストールしたディレクトリにある、samples/java/computer-databaseのmodels/Company.javaおよびComputer.java を参照

Annotation Type OneToMany (Java EE 6 API References)のunidirectional の例を参照

 

要は、Javaのオブジェクトが双方向(bidirectional)でオブジェクトの情報にアクセスしたいか、一方向(unidirectinal)でアクセスしたいかに応じて、アノテーションの設定方法を変えれば良いようです。

 

DB更新について

EBean を使うと、モデルディレクトリのエンティティを更新したタイミングで、自動的に conf/evolutions/default/1.sqlが更新されます。

そこで、DBの更新が自動的に行われるだろうと思って、ブラウザでアクセスするとエラーが表示されることがあります(もちろんうまく更新される場合もあります)。

うまくいかない場合は、どうやって新しいDBスキーマを適用するかというと、データベースそのものを破棄して作り直すのが確実で手っ取り早いようです。たとえば、シェルから

dropdb mydb
createdb mydb

とすればよいかと思います。

 

データベースそのものを破棄したくない場合は次のような方法もあるようです。

StackOverflow の質問(Play 2.1 framework not detecting evolution changes)にあるように、DB内のplay_evolutionsテーブルが適用したエボリューションスクリプトのSQLを管理しているので、このレコードを破棄することでエボリューションスクリプトを再適用するようにできるようです。ただ、試してみたところ、ID列用にシーケンスが作られているとこれまたエラーになる場合があります。

なので、やはり開発環境なら、データベースを破棄して作り直すのが一番かと思われます。

 

あと、Play!Framework にはデータベース・エボリューションの仕組みがあるのですが、この世代管理は、自分で行うことになるようです。

(参考)

データベース・エボリューション

 

XMLを返す場合

REST のように、Play!Frameworkでviewテンプレートを使って、XMLを返す場合があるとします。この場合、main.scala.xml を下記のようにして、

@(content: Xml)
<?xml version="1.0" encoding="UTF-8" ?>
<sample>
    @content
</sample>

ブラウザでアクセスすると、

XML パースエラー: 実体の初めに XML またはテキスト宣言がありません。
URL: http://localhost:9000
行番号: 2, 列番号: 1:<?xml version="1.0" encoding="UTF-8" ?>
^

のようにエラーが出てしまいます。

これは、main.scala.xml の引数宣言の部分に対応して改行が入ってしまうのが原因のようです。

 

これを避けるには、たとえば下記のように

@(content: Xml)<?xml version="1.0" encoding="UTF-8" ?>
<sample>
    @content
</sample>

 

テンプレートの引数の後ろで改行せずに書けば大丈夫です。

なお、テンプレートが複数のファイルに分かれている場合も、各ファイルから生成される際に不要な改行文字が入らないように注意する必要があります。

 

(参考)

How to serve XML and JSON with Play! 2.0

 

メッセージの国際化

Play!Framework にはメッセージ国際化の仕組みもあります。

詳しくは、ドキュメント メッセージの外部ファイル化と多言語対応 を読めばいいのですが、簡単に手順をまとめておきます。

 

まず、conf/application.confに対応している言語を記述します。

次に、conf/messages に全言語向けのメッセージ, messages.xxx に各言語向けのメッセージを記載します。各言語向けのメッセージは、ISO言語コード(ISO 639 (Wikipedia)かな?)とISO国コードを組み合わせて指定します。たとえば、日本語(日 本)なら、ja-JP, フランス語(カナダ)なら、fr-CA といった具合です。

 

たとえば、messagesとして、

title=title sample for test

と記述しておき、messages.ja には

title=タイトル

としておきます。

 

定義した文字列にアクセスする場合は、Messages.get("title") のようにすると、言語に応じてメッセージを取得します。

 

(参考) 実際のフォーマットについては下記に載っています

国際化(Play!Framework 1.1 のドキュメント)

Playframework 2.0(Scala)でサンプルアプリケーション作成-3.メッセージの国際化(i18n)対応