Documentation

You are viewing the documentation for the 2.1.x release series. The latest stable release series is 2.4.x.

§移行ガイド

Play 2.0.x アプリケーションを Play 2.1.0 に移行するためには、まず project/plugins.sbt 内でPlayの sbt-plugin のバージョンを上げましょう。

addSbtPlugin("play" % "sbt-plugin" % "2.1.0")

次に project/Build.scala 内で PlayProject の代わりに新しい play.Project を使うように修正しましょう。

import を記述します。

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 コマンドを起動して、プロジェクトを一旦 clean して、そして再コンパイルしましょう。

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 パラメータはもう必要なくなりました。 Play 2.1 からは、プロジェクトのメイン言語は追加されたモジュールによって自動的に決定されます。具体的には、 javaCore モジュールが追加されていればメイン言語は JAVA となり、それ以外のケースでは SCALA となります。上記の Build.scala ファイルの例でいうと、 appDependencies の部分にモジュール依存性が書かれています。

§play.mvc.Controller.form() が play.data.Form.form() へ名称変更

Play のモジュール化に関連して、 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 を利用するということは、つまり開発者が Play の内部 API および外部ライブラリ両方の Future/Promise をそのまま組み合わせられるようになったということです。

今のところ、Java ユーザは引き続き scala.concurrent.Future をラップした Play の Promise を利用することが想定されています

次のコードスニペットを見てみましょう。

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 が導入されました。この API は既存の JSON パーサとは互換性がありません。

play.api.libs.json.Reads型のシグネチャも変更されました。次のコードを見てください。

trait play.api.libs.json.Reads[A] {
  self =>

  def reads(jsValue: JsValue): A

}

このコードは、 Play 2.1 では次のように変わりました。

trait play.api.libs.json.Reads[A] {
  self =>

  def reads(jsValue: JsValue): JsResult[A]

}

例えば、 Play 2.0User 型の 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 を永続化するためにはこれまで maxAge に -1 を設定していました。しかし、 JBoss Netty 側の変更により、これからは -1 の代わりに null または None (利用する API に依ります)を設定するようになりました。 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 は stage 、 dist 、 start 時のみ JavaScript を minify するということです。開発モード時は、クライアント側で JavaScript モジュール間の依存性が解決されます。

この機能を利用する場合は、 project/Build.scala 内の設定に RequireJS で管理したいモジュールを追加する必要があります。

requireJs := "main.js"

この機能の詳細については RequireJS関連のドキュメント を参照してください。


このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。