ラベル Play Framework の投稿を表示しています。 すべての投稿を表示
ラベル Play Framework の投稿を表示しています。 すべての投稿を表示

2015年3月4日水曜日

[play framework] 間違って controllers 内のクラスを削除したらコンパイルエラー

下記コマンドでリビルドしたら解消した。
$ play clean compile stage


2015年3月1日日曜日

[Play Framework] 多対多で自己再帰の関連を持つテーブルのEntity

多対多(Many To Many)で自己再帰的(self recursive)な関係をEbean の Model で表現するのに苦戦した。
あまり良い例ではないけど、
person には似てる人(similarPerson)が複数いる、という設定で書いてみた。
person と person の多対多を解消する中間テーブルは similar_person として定義してみる。
@Entity
public class Person {
    @Id
    public Long id;

    @ManyToMany
    @JoinTable(name = "similar_person",
            joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "similar_person_id", referencedColumnName = "id"))
    public List similarPersons;
}
ポイントは @JoinTable の引数の joinColumns と inverseJoinColumns 。
最初これらを書かずにいたら、similar_person テーブルで列名 person_id が重複しています と怒られた。

考えてみたらどちらも外部参照先 (person.id) は同じなんだから、列名指定せずに自動生成したらそうなるよな…。

上記のクラスを定義した上で Evolution を実行すると、下記SQL が自動生成される。
# --- Created by Ebean DDL
# To stop Ebean DDL generation, remove this comment and start using Evolutions

# --- !Ups

create table similar_person (
  person_id                     bigint not null,
  similar_person_id             bigint not null,
  constraint pk_similar_person primary key (person_id, similar_person_id))
;

alter table similar_person add constraint fk_similar_person_person_01 foreign key (person_id) references person (id) on delete restrict on update restrict;

alter table similar_person add constraint fk_similar_person_person_02 foreign key (similar_person_id) references person (id) on delete restrict on update restrict;

# --- !Downs

SET REFERENTIAL_INTEGRITY FALSE;

drop table if exists similar_person;

JPA をちゃんと理解してなかったのでけっこうハマった。

【参考】

JPA – Recursive ManyToMany-Relationship | stuetzpunkt -


[Play Framework] Play2.2.x で Java8 の記法で書いたらコンパイルエラーになった

Play2.2.x で play new したプロジェクトを素のまま使っていて Java8 の記法で書いたらコンパイルエラーになった。
2.2系は Java8 対応してないとのこと。

SBT のバージョン上げたら動くようにはなったけど、問題がありそうなので正式対応した 2.3系を使おう。

【参考】

[play-framework] Error Unknown constant: 18 - Grokbase - 


2015年1月5日月曜日

[Heroku][Play Framework] New Relic APMを使って、一定時間アクセスが無くても Dyno をスリープさせないようにする

先日公開した Haiku Matcher で使っている Heroku の Dyno(プロセス) は一定時間(1時間?)アクセスが無いとスリープしてしまう。(IDLE状態になってしまう)

New Relic APM を使って叩き起こし続けることにした。

Heroku のスリープについて

会社の元同期に「Dyno寝てるっぽいよ」と教えてもらって、「あ、眠るんだ…」と知りました。

知っておきたい!Herokuを使う上では当たり前?の16の常識 | mah365 - 

確かに、暫く放置した後のアクセスにはレスポンスが急激に遅くなっていた。
また、Heroku の Personal Apps ページで対象のアプリケーションの六角形アイコンを見てみると、六角形の中に"zzz" が表示されていた。

Dynoとは
Dynoはアプリケーションサーバの1プロセスで、アプリケーションサーバThin(http://code.macournoyer.com/thin/)をベースにしているもののようです。Dynoは追加購入すれば、ユーザは柔軟に増やすことができ、2秒で起動するとのことです。
フレクトのクラウドBlog: Herokuについて調べたことのまとめ - 
スリープさせないためには。
  1. Dyno を増設する
  2. シェルなどで定期的に ping 打つ
  3. Heroku Addon の New Relic APM を使う
1.は課金することになってしまうので今回はパス。
2.は実行用の環境を用意するのが面倒なので今回はパス。

今回は無料プランがあり、Addon ということで簡単に導入できそうな3.を採用。

New Relic APM の導入

検索するといろんな言語での導入方法が出てくるが、今回は Java, かつ Play Framework を利用していたので下記を参考に実践した。
adding new relic addon to heroku play framework 2.2.1 java app - Stack Overflow - 

Amit Sharma 氏の answered Jan 28 '14 at 6:07 の投稿通りに実行した結果、1時間後でもスリープしていないことが確認できた。

上記内容で導入できたと思っていたら、できていなかった。
New Relic のページ見たらアプリケーション情報が表示されず、newrelic agent がそもそも起動してなかったと判明した…。

Java - Play2.2をherokuで動かした時にはまったポイント - Qiita - を参考にやり直したらうまくいったので、方法をきちんとまとめておく。

1) 決済情報を登録する。Heroku ダッシュボードから [Manage Account] → [Billing] で登録しておく。完了していればスキップする。登録していないと 2) で下記エラーが出る。
Adding newrelic:stark on your-app-name... failed
 !    Please verify your account to install this add-on plan (please enter a credit card)
 !    For more information, see https://devcenter.heroku.com/categories/billing

2) アドオンを入れる。
$ heroku addons:add newrelic:stark

3) 依存ライブラリを追加する。build.sbt に下記を追記する。
"com.newrelic.agent.java" % "newrelic-agent" % "3.12.1"
※newrelic-api は不要だった。
※最初にてきとうに 3.1.0 を選んだらエラー出て、Java8に対応してなかった。今回はJava8を使っているので、対応しているバージョンを選択した。

4) New Relic 関連のファイルを配置する。
ファイル群は New Relic の管理ページ → Application タブのページから取得できるはず。(自分のアプリが正常に連携されてからそのページが開けなくなった…)
・newrelic.yml のみルートディレクトリに配置する。
・それ以外(jarなど)は lib/ に配置する。

5) Procfile にVM引数を追加する。
-J-javaagent:lib/newrelic.jar
※Play2.2から JAVA_OPTS に設定してもダメとのこと。

6) ここまでの変更をコミット、Heroku へデプロイする。
$ git add .
$ git commit -m "optional message"
$ git push heroku master
数分後、New Relic の管理ページ →アプリケーションタブのページに自分のアプリ名が表示される。

7) New Relic の Monitoring 対象に自分のサイトを加える。
New Relic の管理ページ → Applications タブ → [自分のアプリ名] → Availability Monitoring → URL Monitor に自分のサイトのURLを入力する。
(参考)1DynoなHerokuをNew Relicでアイドルを回避 - PILOG - 




感想

簡単だと思ったら色々とハマった。Heroku Scheduler の方が簡単だったかも。

(参考)Heroku Scheduler

【環境 】

・Java8
・Play Framework 2.2.6


2014年12月31日水曜日

俳句調のツイートを検索して表示するWebアプリ作ってみた

俳句調のツイートを Twitter から検索して表示するWebアプリ作ってみた。

http://haiku-matcher.herokuapp.com/
https://github.com/ohbarye

テキストボックスに入力された値でツイートを取得して、その中から575調になっているものだけを表示する。
入力値がユーザ名なら、そのユーザのタイムラインから。ユーザ名でなければキーワード検索した結果からツイートを取得する。


言語/フレームワーク

  • Java8
  • Play Framework 2.2.6

□よかったこと
・やっぱりJava8で書くとコードが変わると思った。まだ知らない機能が多いので引き続き学びたい
・Play、噂通りで開発効率がかなり上がる
・特に立ち上げの速さ
・sbtによる依存性管理がストレスフリー
・Java EEから解放された感
 http://d.hatena.ne.jp/wyukawa/20140416/1397662264
・フルスタック感
・Hot Deploy
・scala templateの型安全性
…+まだやってないこといっぱいある

■困ったこと
・Play2.2系はJava8対応してなくて、sbtのバージョンあげたり結局諦めたエラーとかあった(2.3以降は対応済。よく調べずに2.2を選んだのは失敗)
・Playの更新頻度が高いので調べた情報が違うバージョンの情報…というのはよくあった

形態素解析

  • kuromoji

文章ぶち込むだけで解析結果を返してくれるライブラリ。全文検索エンジンの Solr とかでも使っているらしい。
Tweet から拾う単語は未知語(内蔵辞書に載ってない語)が多かった。今回は雑に処理したけど、そこらへん真面目にやろうとしたら自分で辞書用意する必要があるっぽくて震えた。

Twitter連携

  • twitter4j

直接 Twitter API を叩く必要ない。
ライブラリの問題じゃないけど、検索後によって401が返ってくるというよくわからないエラーでかなり悩んだ。時間を置いたりリトライしたら通るようになった。
いろいろググってたら Twitter から401エラーが返ってきて困った的な質問がめちゃ多くて世界中の悩み感があった。

プラットフォーム

  • heroku

初めて使ってみた。確かに爆速でデプロイできて便利っぽい。
環境・サーバ構築とかをほとんど考えなくてよくなったのでアプリ作る〜公開のハードルがまた下がった感がある。

けどまだ全然使いこなせてない。

git push heroku master した後の待ち時間が長いので休憩にしたりしてた。

フロントサイド

  • webjars
  • Bootstrap
  • LESS

フロントサイドの知識全然無いけど、この辺組み合わせるのがややモダンらしいので試してみた。
jqueryとか、クライアントサイドライブラリ揃えるのも確かに面倒なので webjars のこと知れてよかったという気持ちがある。

あまりよく知らないのでデザイン領域触れたくなかったけど、Bootstrap とか LESS とか試してみたら思ったより軽く書けたのでちょっと興味湧いた。けど深入りしたくない感じ。

その他感想

仕事で試す日が来ることは暫く無さそうで辛い(からい)。

2014年12月24日水曜日

[Play Framework] 設定ファイル(application.conf)から値を取得する

設定ファイル:application.conf に定義した値を取得する方法。意外と簡単で良かった。

とりあえず取得

key="value"
まず conf ファイルに定義する。
文字列にダブルクォーテーション付ける必要があるので注意。
Play.application()
       .configuration()
       .getString("key");    // "value" が取得できる

Configulationクラス

Configulation クラスには getString 以外にも getBoolean, getDouble など様々な型での値の取得が可能で便利だが、上記の書き方だとやたら長いのでラップしたメソッドを用意して使ってる。
 public static String getString(String key) {  
     return Play.application()
       .configuration()
       .getString(key);
 }

 public static boolean getBoolean(String key) {  
     return Play.application()
       .configuration()
       .getBoolean(key);
 }

2014年12月23日火曜日

[Play Framework] controllers 内でサブパッケージを作成する場合の注意点

Play Framework 始めた。

controllers 内にサブパッケージを作成して、その中のクラスおよびメソッドへのルーティングで一度失敗したのでメモ。

controller 直下のクラスにアクセスする

まず基本のおさらい。
パッケージ名:controllers
クラス名:MyClass
メソッド名:index
↑ココにアクセスしたい場合は以下のように routes とテンプレートファイルを編集する。
POST /index  controllers.MyClass.index()
@form(action = routes.MyClass.index) {
    <!-- 省略 -->
} 

controller 下のサブパッケージのクラスにアクセスする

本題はこのクラスのサブパッケージ内に作成する場合。
パッケージ名:controllers.sub
クラス名:MyClass
メソッド名:index
まず routes を修正する。
POST /index  controllers.sub.MyClass.index()
その後に scala.html 内のPOST先 action を修正。
サブパッケージ名をクラス名に付けてみる。
@form(action = routes.sub.MyClass.index) {
    <!-- 省略 -->
}
これでアクセスしてみると…
value sub is not a member of object controllers.routes
「"sub"なんてオブジェクトないよ」とのエラーメッセージ。
調べてみたところ完全修飾名で書けばOKとのこと。
There is a routes subpackage for each controller package. So the rightfully qualified name of your route is:@controllers.foo.routes.Home.index()
It's done this way to "see" the routes subpackage relatively from any
controllet package as "routes" 
[2.0] [Scala] routes for controller sub-packages - Google Groups -  
下記の通り修正したら無事通るようになった。
@form(action = controllers.sub.routes.MyClass.index) {
    <!-- 省略 -->
}