ドキュメント

§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** の新しいモジュール化された依存関係を以下に示します。

**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#formplay.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"))
      }
    }
  }

次の追加インポートに注意してください。

一般的に、「error: could not find implicit value for parameter executor」というエラーメッセージが表示された場合は、おそらく次のものを追加する必要があります。

import play.api.libs.concurrent.Execution.Implicits._

(詳細については、実行コンテキストに関する Scala ドキュメントを参照してください。)

そして、次のことを覚えておいてください。

§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 ドキュメントを参照してください。

JBoss Netty の変更により、maxAge を -1 に設定する代わりに null または None(API に依存)に設定することで、Cookie が一時的なものになります。maxAge の値が 0 以下の場合、Cookie はすぐに期限切れになります。

SimpleResultdiscardingCookies(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 ドキュメントページを参照してください。

次へ:Scala 3 移行ガイド


このドキュメントにエラーを見つけた場合、このページのソースコードは こちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを送信して自由に貢献してください。質問やアドバイスを共有したいですか? コミュニティフォーラムにアクセスして、コミュニティとの会話を始めましょう。