Play Java 歴 1 年くらいの私が、最近、プロジェクトで、Play Scala、Slickのバージョンアップを行いました。マイグレーションを行う方が、事前に知っておいた方が良いことについて記しておきます。なお、ここに記載されていることが全てではありませんので、マイグレーションガイドを参照ください。
Play 2.4.x への以降
移行の詳細については、マイグレーションガイドを参照。
ビルド方法の変更
project/plugins.sbt にあるPlayを以下に更新します。
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.0")
Play 2.4 の対応 sbt バージョンは 0.13.8 です。project/build.properties を更新しましょう。
sbt.version=0.13.8
Javaは8のみサポート
6と7はサポート対象外になり、6または7でビルドしようとするとエラーになるようです。
Dependency Injectionのサポート
3.0 でグローバルな状態管理を完全に廃止することを目標にDIの導入を行っているようです。2.4から Guiceというライブラリを使ったDIをデフォルトでサポートし始めたようです。DIの詳細はドキュメントを参照。
対応する場合、まずbuild.sbtにルートジェネレータとして、DIに対応版を使うことを明記。
routesGenerator := InjectedRoutesGenerator
DI 対応の目印で conf/routes の Controller のメソッド名に @ をつけます。
GET /some/path @controllers.Application.index
- DIのを使うことは @Inject で明記します。@inject は JSR330 で決められた DI 用のアノテーション。
- 共通に DI を使う用途は、後述のメッセージ国際化対応(messagesApi: MessagesApi)、DB の設定(dbConfigProvider: DatabaseConfigProvider)です。
class Application @Inject() (dbConfigProvider: DatabaseConfigProvider, messagesApi: MessagesApi) extends Controller with I18nSupport {
なお、コントローラを object(シングルトンオブジェクト)としていた場合、今後はclassにし、かつ @Singleton をつけることで、引き続きシングルトンとして扱うことが可能です。
@Singleton
class YoutSingletonClass @Inject(yourParameter: YourClass) {
国際化APIへの対応
Internationalization API が導入されました。ビューに表示するメッセージは言語ごとに設定ファイルとして用意し、 play.api.i18n.Messages としてコントローラやビューに渡すようになりました。詳細はドキュメント参照。
DIの仕組みでviewに注入するため、viewの先頭にmessageの宣言が必要です。
(implicit messages: Messages)
Controllerも messagesApi: play.api.i18n.Messages を渡すように修正が必要。
class Application @Inject() (dbConfigProvider: DatabaseConfigProvider, messagesApi: MessagesApi) extends Controller with I18nSupport {
また、conf/application.confのアプリケーション言語設定もi18nの方を使うように修正。
play.i18n.langs = [ "en" ]
Slick 3.0 への移行
詳細は Slick のマイグレーションガイドを参照。
buid.sbtの変更
- play-slick のバージョンを変更します。
- evolutions は別モジュールに切りだされたそうです。利用する場合は "evolutions"(ORM 共通)と "play-slick-evolutions"(Slickのevolutions)が必要です。
libraryDependencies ++= Seq(
...
evolutions,
"com.typesafe.play" % "play-slick_2.11" % "1.1.1",
"com.typesafe.play" %% "play-slick-evolutions" % "1.1.1",
...
)
evolutiuonを止めたい場合は、conf/application.confに以下を設定。プロパティ名が変更されている点に注意。
play.evolutions.enabled=false
DBの設定
slick を使う場合、application.conf の設定名が変更。プロパティ名が変更されている点に注意。
slick.dbs.default.driver="slick.driver.H2Driver$"
slick.dbs.default.db.driver=org.h2.Driver
slick.dbs.default.db.url="jdbc:h2:mem:play"
slick.dbs.default.db.user=sa
slick.dbs.default.db.password=""
Slick ドライバの自動検出
これまでは以下の import で特定のドライバ用のAPIをインポートしていましたが、この方法は廃止されました。
import play.api.db.slick.Config.driver.simple._.
これからは application.conf で設定したものをフレームワークが自動検出し、DI で注入するようになりました。import driver.api._ の箇所で設定したドライバの API が利用できるようになります。
class Application @Inject() (dbConfigProvider: DatabaseConfigProvider, messagesApi: MessagesApi) extends Controller with I18nSupport {
val dbConfig = dbConfigProvider.get[JdbcProfile]
import dbConfig._
import driver.api._
非同期クエリ実行のサポート
2.x系で使われていたDBAction、DBSessionRequest、DB.withSessionなどのAPIが廃止されました。
このドキュメントにあるように今後は、db.runというAPIを使います。これは Future を返すメソッドです。DB のクエリが非同期化され、コントローラのレスポンス部分も非同期化(Futureを返す)ようになっている点に注目。
例えば、あるまとまった処理を小分けてし、非同期処理し、結果がまとまったら返すみたいなことができ、スケールアウトさせることが容易になったといえます。
def index(name: String) = Action.async { implicit request =>
val resultingUsers: Future[Seq[User]] = dbConfig.db.run(Users.filter(_.name === name).result)
resultingUsers.map(users => Ok(views.html.index(users)))
}
以上です。本記事が、これからマイグレーションを行う方にとって参考になりましたら、幸いです。もし記事の内容で、気になる点、間違いなどありましたら、コメントいただけると嬉しいです。