§Play 2.1 移行ガイド
これは、Play 2.0 から Play 2.1 への移行ガイドです。
**Play 2.0.x** アプリケーションを **Play 2.1.0** に移行するには、まず project/plugins.sbt
ファイルで Play の sbt-plugin
を更新します。
addSbtPlugin("play" % "sbt-plugin" % "2.1.0")
次に、PlayProject
クラスではなく新しい play.Project
クラスを使用するように project/Build.scala
ファイルを更新します。
まずインポートします。
import play.Project._
次に、main
プロジェクトの作成です。
val main = play.Project(appName, appVersion, appDependencies).settings(
最後に、project/build.properties
ファイルを更新します。
sbt.version=0.12.2
その後、**Play 2.1.0** ディストリビューションで play
コマンドを使用してプロジェクトをクリーンアップして再コンパイルします。
play clean
play ~run
コンパイルエラーが発生した場合は、このドキュメントを参照して、非推奨になった変更や互換性のない変更によってエラーが発生した原因を特定できます。
§ビルドファイルの変更
Play 2.1 ではモジュール化がさらに進められたため、アプリケーションに必要な依存関係を明示的に指定する必要があります。デフォルトでは、すべての play.Project
には Play コアライブラリへの依存関係のみが含まれています。アプリケーションに必要なオプションの依存関係の正確なセットを選択する必要があります。**Play 2.1** の新しいモジュール化された依存関係を以下に示します。
jdbc
:**JDBC** 接続プールとplay.api.db
API。anorm
:**Anorm** コンポーネント。javaCore
:コア **Java** API。javaJdbc
:Java データベース API。javaEbean
:Java 用の Ebean プラグイン。javaJpa
:Java 用の JPA プラグイン。filters
:Play の組み込みフィルターのセット(CSRF フィルターなど)。
**Play 2.1** の一般的な Build.scala
ファイルを以下に示します。
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "app-name"
val appVersion = "1.0"
val appDependencies = Seq(
javaCore, javaJdbc, javaEbean
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
)
}
プロジェクトの mainLang
パラメータは不要になりました。メイン言語は、プロジェクトに追加された依存関係に基づいて決定されます。依存関係に javaCore
が含まれている場合、言語は JAVA
に設定され、それ以外の場合は SCALA
に設定されます。appDependencies
セクションのモジュール化された依存関係に注意してください。
§play.mvc.Controller.form() が play.data.Form.form() に名前変更
モジュール化にも関連して、play.data
パッケージとその依存関係は Play コアから javaCore
アーティファクトに移動されました。その結果、play.mvc.Controller#form
は play.data.Form#form
に移動されました。
§play.db.ebean.Model.Finder.join() が fetch() に名前変更
クリーンアップの一環として、Finder API の join メソッドは fetch メソッドに置き換えられました。動作はまったく同じです。
§Play の Promise が Scala の Future になる
Scala 2.10 で scala.concurrent.Future
が導入されたことで、Scala エコシステムはさまざまな Future と Promise ライブラリを統合するための大きな飛躍を遂げました。
Play が scala.concurrent.Future
を直接使用するようになったということは、ユーザーは内部 API や外部ライブラリから取得した future/promise を簡単に組み合わせることができることを意味します。
Java ユーザーは、現時点では scala.concurrent.Future をラップした Play のラッパーを引き続き使用します。
次のスニペットを検討してください。
import play.api.libs.iteratee._
import play.api.libs.concurrent._
import akka.util.duration._
def stream = Action {
AsyncResult {
implicit val timeout = Timeout(5.seconds)
val akkaFuture = (ChatRoomActor.ref ? (Join()) ).mapTo[Enumerator[String]]
//convert to play promise before sending the response
akkaFuture.asPromise.map { chunks =>
Ok.stream(chunks &> Comet( callback = "parent.message"))
}
}
}
新しい scala.concurrent.Future
を使用すると、これは次のようになります。
import play.api.libs.iteratee._
import play.api.libs.concurrent._
import play.api.libs.concurrent.Execution.Implicits._
import scala.concurrent.duration._
def stream = Action {
AsyncResult {
implicit val timeout = Timeout(5.seconds)
val scalaFuture = (ChatRoomActor.ref ? (Join()) ).mapTo[Enumerator[String]]
scalaFuture.map { chunks =>
Ok.stream(chunks &> Comet( callback = "parent.message"))
}
}
}
次の追加インポートに注意してください。
- 実行コンテキスト
play.api.libs.concurrent.Execution.Implicits
の新しいインポート - 期間
scala.concurrent.duration
の変更(Akka API の使用の代わりに) asPromise
メソッドは削除されました。
一般的に、「error: could not find implicit value for parameter executor」というエラーメッセージが表示された場合は、おそらく次のものを追加する必要があります。
import play.api.libs.concurrent.Execution.Implicits._
(詳細については、実行コンテキストに関する Scala ドキュメントを参照してください。)
そして、次のことを覚えておいてください。
- Play の
Promise
は、現在は Scala のFuture
です。 - Play の
Redeemable
は、現在は Scala のPromise
です。
§Scala JSON API の変更
**Play 2.1** には、新しく改良された Scala JSON 検証ツールとパスナビゲーターが付属しています。ただし、この新しい API は既存の JSON パーサーとの互換性を損ないます。
play.api.libs.json.Reads
タイプシグネチャが変更されました。次を検討してください。
trait play.api.libs.json.Reads[A] {
self =>
def reads(jsValue: JsValue): A
}
2.1 では、これは次のようになります。
trait play.api.libs.json.Reads[A] {
self =>
def reads(jsValue: JsValue): JsResult[A]
}
そのため、**Play 2.0** では、User
タイプの JSON シリアライザーの実装は次のとおりでした。
implicit object UserFormat extends Format[User] {
def writes(o: User): JsValue = JsObject(
List("id" -> JsNumber(o.id),
"name" -> JsString(o.name),
"favThings" -> JsArray(o.favThings.map(JsString(_)))
)
)
def reads(json: JsValue): User = User(
(json \ "id").as[Long],
(json \ "name").as[String],
(json \ "favThings").as[List[String]]
)
}
**Play 2.1** では、次のようにリファクタリングする必要があります。
implicit object UserFormat extends Format[User] {
def writes(o: User): JsValue = JsObject(
List("id" -> JsNumber(o.id),
"name" -> JsString(o.name),
"favThings" -> JsArray(o.favThings.map(JsString(_)))
)
)
def reads(json: JsValue): JsResult[User] = JsSuccess(User(
(json \ "id").as[Long],
(json \ "name").as[String],
(json \ "favThings").as[List[String]]
))
}
JSON を生成するための API も進化しました。次を検討してください。
val jsonObject = Json.toJson(
Map(
"users" -> Seq(
toJson(
Map(
"name" -> toJson("Bob"),
"age" -> toJson(31),
"email" -> toJson("[email protected]")
)
),
toJson(
Map(
"name" -> toJson("Kiki"),
"age" -> toJson(25),
"email" -> JsNull
)
)
)
)
)
**Play 2.1** では、これは次のようになります。
val jsonObject = Json.obj(
"users" -> Json.arr(
Json.obj(
"name" -> "Bob",
"age" -> 31,
"email" -> "[email protected]"
),
Json.obj(
"name" -> "Kiki",
"age" -> 25,
"email" -> JsNull
)
)
)
これらの機能の詳細については、Json ドキュメントを参照してください。
§Cookie 処理の変更
JBoss Netty の変更により、maxAge
を -1 に設定する代わりに null
または None
(API に依存)に設定することで、Cookie が一時的なものになります。maxAge
の値が 0 以下の場合、Cookie はすぐに期限切れになります。
SimpleResult
の discardingCookies(String\*)
(Scala)と discardCookies(String...)
(Java)メソッドは非推奨になりました。これらのメソッドは、特定のパス、ドメインに設定された Cookie や、セキュリティ設定された Cookie を処理できません。代わりに、discardingCookies(DiscardingCookie\*)
(Scala)と discardCookie
(Java)メソッドを使用してください。
§RequireJS
**Play 2.0** では、Javascript のデフォルトの動作は Google の Closure CommonJS モジュールサポートを使用することでした。**Play 2.1** では、代わりに RequireJS を使用するように変更されました。
実際には、デフォルトでは Play はステージ、dist、スタートモードでのみファイルの縮小と結合を行います。開発モードでは、Play はクライアント側で依存関係を解決します。
この機能を使用する場合は、モジュールを project/Build.scala
ファイルの設定ブロックに追加する必要があります。
requireJs := "main.js"
この機能の詳細については、RequireJS ドキュメントページを参照してください。
このドキュメントにエラーを見つけた場合、このページのソースコードは こちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを送信して自由に貢献してください。質問やアドバイスを共有したいですか? コミュニティフォーラムにアクセスして、コミュニティとの会話を始めましょう。