PlayFramework
playframework2.6

Play 2.6の移行ガイド【翻訳】

More than 1 year has passed since last update.

https://www.playframework.com/documentation/2.6.x/Migration26 を google翻訳した


Play 2.6移行ガイド

これは、Play 2.5からPlay 2.6に移行するためのガイドです。以前のバージョンのPlayから移行する必要がある場合は、まず Play 2.5移行ガイド に従ってください。

移行する方法

sbtでPlayプロジェクトをロード/実行するには、次の手順を実行してsbtビルドを更新する必要があります。

Playアップグレード

play / playins.sbtのPlayバージョン番号を更新してPlayをアップグレードします。

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.x")

2.6.xの "x"は、使用したいPlayのマイナーバージョンです(例:2.6.0)。

0.13.15にsbtをアップグレード

Play 2.6では、最新のsbtバージョン0.13.15にアップグレードする必要があります。 0.13.15のsbtリリースには いくつかの改善とバグ修正 があります( sbt 0.13.13 の変更も参照)。

更新するには、 project/build.properties を次のように変更します。

sbt.version=0.13.15

Guice DIのサポートが別のモジュールに移動

Play 2.6では、コアPlayモジュールにGuiceが含まれなくなりました。 libraryDependenciesにguiceを追加してGuiceモジュールを設定する必要があります:

libraryDependencies += guice

OpenIDのサポートを別のモジュールに移動

Play 2.6では、コアPlayモジュールは、play.api.libs.openid(Scala)およびplay.libs.openid(Java)にOpenIDサポートを含まなくなりました。これらのパッケージを使用するには libraryDependenciesにopenIdを追加してください:

libraryDependencies += openId

Play JSON を別プロジェクトに移動

Play JSONが https://github.com/playframework/play-json でホストされ別のライブラリに移動しました。 Play JSONはPlayの残りの部分に依存しないので、PlayImportのjson値はSBTビルドではもう機能しません。代わりに、ライブラリを手動で指定する必要があります。

libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.0"

また、play-jsonにはコアPlayライブラリとは別のリリースサイクルがあり、バージョンはPlayのバージョンと同期していません。

Play Iteratees を別のプロジェクトに移動

Play Iterateesは、 https://github.com/playframework/play-iteratees でホストされている別のライブラリに移動されました。 Play Iteratees は Playの残りの部分に依存しないため、主な変更点は、ライブラリを手動で指定する必要があることです。

libraryDependencies += "com.typesafe.play" %% "play-iteratees" % "2.6.1"

このプロジェクトには、Iterateesと Reactive Streams を統合するサブプロジェクトもあります。次の依存関係も追加する必要があります。

libraryDependencies += "com.typesafe.play" %% "play-iteratees-reactive-streams" % "2.6.1"

注: ヘルパークラス play.api.libs.streams.Streamsplay-iteratees-reactive-streams に移動され、現在は play.api.libs.iteratee.streams.IterateStreams と呼ばれています。したがって、Iteratees依存関係を追加し、必要に応じて新しいクラスを使用する必要があります。

最後に、Play Iterateesは別のバージョン管理方式を採用しているため、バージョンはPlayバージョンと同期しなくなりました。

デフォルトのサーバーエンジンとしてのAkka HTTP

Playはデフォルトのバックエンドとして Akka-HTTP サーバーエンジンを使用します。何らかの理由(たとえば、Nettyの ネイティブトランスポート を使用している場合など)でNettyに戻す必要がある場合は、 Netty Server のマニュアルでその方法を参照してください。

Akka HTTP Server Backend で詳しく読むことができます。

Akka HTTPサーバーのタイムアウト

Play 2.5.xには、デフォルトのサーバーバックエンドである Netty Serverのリクエストタイムアウト設定はありません。しかし、Akka HTTPは、アイドル状態の接続とリクエストの両方にタイムアウトがあります(詳細については、 Akka HTTP Settings のドキュメントを参照してください)。 Akka HTTPドキュメント には、

Akka HTTPには、悪意のある攻撃やプログラミングミスからサーバーを保護するためのさまざまな組み込みのタイムアウトメカニズムが付属しています。

ここ で、 akka.http.server.idle-timeoutakka.http.server.request-timeout 、および akka.http.server.bind-timeout のデフォルト値を確認できます。 Playには タイムアウトを定義するための独自の設定 があります。したがって、503 Service Unavailableの数が表示されるようになったら、設定をアプリケーションにとってより合理的な値に変更することができます。

play.server.http.idleTimeout = 60s
play.server.akka.requestTimeout = 40s

Scalaモードの変更

Scala Mode は Enumeration から case オブジェクトにリファクタリングされました。このリファクタリングにより、ほとんどのScalaコードは変更されません。しかし、あなたのJavaコードでScala Modeの値にアクセスしている場合、それを以下から変更する必要があります:

//このJavaコードを検討する
play.api.Mode scalaMode = play.api.Mode.Test();

次のものに書き直さなければなりません:

//このJavaコードを検討する
play.api.Mode scalaMode = play.Mode.TEST.asScala();

JavaとScalaモード間の変換も簡単です。

// Javaコード内
play.api.Mode scalaMode = play.Mode.DEV.asScala();

またはあなたのScalaコードで:

play.Mode javaMode = play.api.Mode.Dev.asJava

また、 play.api.Mode.Mode は現在廃止予定です。代わりに play.api.Mode を使用してください。

Writeable[JsValue] の変更

以前は、デフォルトのScala Writeable[JsValue] では暗黙的なコーデックを定義することができました。異なるコーデックを使用して記述することができます。これは、 application/json がテキストベースのコンテンツタイプのように動作しないため、問題になる可能性があります。 Unicode文字セット(UTF-8、UTF-16およびUTF-32)のみが可能で、多くのテキストベースのコンテンツタイプのように charset パラメータは定義されていません。

現在、デフォルトの Writeable[JsValue] には暗黙のパラメータはなく、常に UTF-8 に書き込みます。ほとんどのユーザーはJSONのためにUTF-8を使用したいので、大部分のケースをカバーしています。また、JSONをバイト配列に書き込むためのより効率的な組み込みメソッドを簡単に使用することもできます。

古い動作が必要な場合は、希望のコーデックと Content-Typeの play.api.http.Writeable.writeableOf_JsValue(codec, contentType)を使用して任意のコーデックで書き込み可能を定義できます。

Scala コントローラの変更

慣用的なPlayコントローラは、これまで、必要なグローバル状態を有していた。必要な主要な場所は、グローバル Action オブジェクトと BodyParsers#parse メソッドでした。

その状態を注入する新しい方法をいくつかの新しいコントローラクラスに提供し、同じ構文を提供しました:

ControllerComponents は、コントローラで一般的に使用されるコンポーネントをバンドルするためのものです。 ControllerHelpers を拡張し、独自のコンポーネントバンドルを注入することで、独自のベースコントローラを作成することもできます。 Playでは、コントローラが特定の特性を実装する必要はありません。

BaseController は、 Actionparse が、グローバルオブジェクトではなく、注入されたインスタンスを参照するようにします。これは、通常は実行したいものです。

AbstractController を使用したコードの例を次に示します。

class FooController @Inject() (components: ControllerComponents)
    extends AbstractController(components) {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}

BaseController の場合:

class FooController @Inject() (val controllerComponents: ControllerComponents) extends BaseController {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}

InjectedController の場合:

class FooController @Inject() (val controllerComponents: ControllerComponents) extends BaseController {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}

InjectedController は、JSR-330準拠の依存関係注入によって自動的に呼び出される setControllerComponents メソッドを呼び出すことによって ControllerComponents を取得します。コンパイル時DIで InjectedController を使用することはお勧めしません。コントローラを手作業で広範囲にユニットテストする予定がある場合は、 InjectedController が依存関係を隠すので避けることをおすすめします。

個別の依存関係を手動で渡すことを希望する場合は、代わりにそれを行い、依存関係や状態のない ControllerHelpers を拡張することができます。ここに例があります:

class Controller @Inject() (
    action: DefaultActionBuilder,
    parse: PlayBodyParsers,
    messagesApi: MessagesApi
  ) extends ControllerHelpers {
  def index = action(parse.text) { request =>
    Ok(messagesApi.preferred(request)("hello.world"))
  }
}

Scala ActionBuilderとBodyParserの変更点

Scala ActionBuilder のトレイトは、ボディの型を型パラメータとして指定し、抽象パーサメンバをデフォルトボディパーサとして追加するように変更されました。あなたはあなたの ActionBuilder を修正し、ボディパーサを直接渡す必要があります。

Action グローバルオブジェクトと BodyParsers#parse は現在廃止予定です。それらはそれぞれ注入可能なトレイト、 DefaultActionBuilder および PlayBodyParsers に置き換えられます。コントローラの中にいる場合は、新しい BaseController トレイトによって自動的に提供されます(上記の [Scala コントローラの変更] を参照してください)。

クッキー

Javaユーザーの場合、 play.mvc.Http.Cookie.builder を使用して新しい Cookie を作成することをお勧めします。

Http.Cookie cookie = Cookie.builder("color", "blue")
  .withMaxAge(3600)
  .withSecure(true)
  .withHttpOnly(true)
  .withSameSite(SameSite.STRICT)
  .build();

これは普通のコンストラクタ呼び出しよりも読みやすく、今後クッキー属性を追加/削除するとソースと互換性があります。

SameSite属性(セッションとフラッシュ用に有効)

現在、Cookieには SameSite属性 が追加されており、CSRFを防止するために使用できます。次の3つの状態が考えられます。

  • SameSite がない。つまり、そのドメインへのすべてのリクエストに対してCookieが送信されます。
  • SameSite=Strict クロスサイトリクエストではなく、同じサイトリクエスト(サイトの別のページからのもの)に対してのみクッキーが送信されることを意味します。
  • SameSite=Lax つまり、トップレベルのナビゲーションとしてクロスサイトリクエストに対してクッキーが送信されますが、それ以外の場合は同じサイトリクエストに対してのみ送信されます。これにより、ほとんどのサイトで正しいことが実行されますが、ポップアップウィンドウを起動して実行される攻撃などの特定の種類の攻撃は防げません。

さらに、デフォルトで SameSite=Lax を使用するようにセッションCookieとFlash Cookieを移動しました。設定を使ってこれを微調整することができます。例えば:

play.http.session.sameSite = null // no same-site for session
play.http.flash.sameSite = "strict" // strict same-site for flash

注:この機能は現在、 多くのブラウザでサポートされていない ため、使用しないでください。 ChromeとOperaは現在SameSiteをサポートする唯一の主要なブラウザです。

__Host__Secure プレフィックス

また、 __Host__Secure のCookie名のプレフィックス もサポートしました。

これは、Cookie名にこれらのプレフィックスを使用している場合にのみ影響します。もしあなたがそうであれば、適切な属性が設定されていない場合、それらのクッキーをシリアライズおよびデシリアライズするときにPlayが警告し、自動的にそれらを設定します。警告を削除するには、Cookieにこれらの接頭辞を使用しないか、次のように属性を設定する必要があります。

  • __Host- で指定されたCookieは、 Path=/ および Secure 属性を設定する必要があります。
  • __Secure- で名前が付けられたCookieは、 Secure 属性を設定する必要があります。

Assets

コンパイル時DIを使用したアセットのバインド

コンパイル時DIを使用している場合は、 controllers.AssetsComponents をミックスインして、コントローラインスタンスで assets:Asset を取得する必要があります。

class MyComponents(context: Context) extends BuiltInComponentsFromContext(context) with AssetsComponents {
  lazy val router = new Routes(httpErrorHandler, assets)
}

lazy val assets: Assets を持つ場合は、削除することができます。

Assets の構成

既存のユーザー向けAPIは変更されていませんが、AssetsFinder APIに移り、アセットを探し、設定でアセットディレクトリを設定することをお勧めします。

play.assets {
  path = "/public"
  urlPrefix = "/assets"
}

ルートでは次のことができます:

# prefix must match `play.assets.urlPrefix`
GET /assets/*file           controllers.Assets.at(file)
GET /versionedAssets/*file  controllers.Assets.versioned(file)

引数リストの先頭にアセットのパスを指定する必要はなくなりました。これは設定から​​読み込まれるためです。

テンプレートでは、 AssetsFinder#path を使ってアセットの最終パスを見つけることができます:

@(assets: AssetsFinder)

<img alt="hamburger" src="@assets.path("images/hamburger.jpg")">

Assets.versioned を使用して引き続き逆ルートを使用することはできますが、複数のアプリケーションを一度に実行する場合は、問題の原因になる可能性がある最終的なアセット名に指定したアセット名を変換する必要があります。

フォームの変更

Play 2.6以降、POST、PUT、またはPATCHリクエストと組み合わせて bindFromRequest() を使用すると、クエリ文字列パラメータはフォームインスタンスにバインドされなくなります。

このリリースでは、2.5で既に廃止されていた静的メソッド( DynamicForm.form() など)は削除されました。移行方法について詳しくは、 Play 2.5移行ガイド を参照してください。

Javaフォームの変更

play.data.Form インスタンスの errors() メソッドは廃止予定です。 Map> の代わりに単純な List を返す allErrors() を代わりに使用する必要があります。 Play 2.6以前では .errors().get("key") を呼び出したところで、単に .errors("key") を呼び出すことができます。

これ以降、フォームクラス内で実装された validate メソッド(通常はクロスフィールド検証に使用される)は、クラスレベルの制約の一部です。このような制約の使用方法の詳細については、 高度な検証ドキュメント を参照してください。
影響を受けるフォームクラスに @Validate で注釈を付け、 validate メソッドの戻り値の型に応じて、適切なtype引数(すべてが play.data.validation.Constraints で定義されています)で Validatable インターフェイスを実装することで、既存の validate メソッドを簡単に移行できます:

戻り値の型 実装するインタフェース
String Validatable
ValidationError Validatable
List Validatable>
Map> (not supported anymore; use List instead) Validatable>

(これ以上サポートされていない; Listを代わりに使用する)Validatable >
たとえば、次のような既存のフォーム:

public class MyForm {
    //...
    public String validate() {
        //...
    }
}

変更する必要があります:

import play.data.validation.Constraints.Validate;
import play.data.validation.Constraints.Validatable;

@Validate
public class MyForm implements Validatable<String> {
    //...
    @Override
    public String validate() {
        //...
    }
}

注意:以前のすべての制約が以前に成功した後にのみ、「古い」検証メソッドが呼び出されました。しかし、デフォルトでは、クラスレベルの制約は、他の制約アノテーションと同時に呼び出されます(パスの合否に関係なく)。制約間に順序を定義するために、制約グループを使用できるようになりました。

JPA移行ノート

JPA移行ノート を参照してください。

I18n移行ノート

「I18N APIの移行」 を参照してください。

キャッシュAPI移行ノート

「キャッシュAPIの移行」 を参照してください。

Java Configuration API移行ノート

Java Configuration Migration を参照してください。

Scala 設定API

Scalaの play.api.Configuration APIには、 ConfigLoader を使用してあらゆるタイプの読み込みを可能にする新しいメソッドが追加されました。これらの新しい方法では、構成ファイルに構成キーが存在することが期待されます。たとえば、次の古いコードです。

val myConfig: String = configuration.getString("my.config.key").getOrElse("default")

変更する必要があります

val myConfig: String = configuration.get[String]("my.config.key")

my.config.key = default という設定で値 "default" を設定する必要があります。

また、デフォルト値を取得するためにコードでカスタムロジックが必要な場合は、設定ファイル( my.config.key = null )でデフォルトをnullに設定し、 Option[T] を読むことができます。

val myConfigOption: Option[String] = configuration.get[Option[String]]("my.config.key")
val myConfig: String = myConfigOption.getOrElse(computeDefaultValue())

また、 getBooleanList のようなJava型を返す古い play.api.Configuration にはいくつかのメソッドがあります。可能であれば、Scalaバージョンの get[Seq[Boolean]] を使用することをお勧めします。それが不可能な場合は、基礎となる underlingConfig オブジェクトにアクセスし、そこから getBooleanList を呼び出すことができます。

既存のメソッドの非推奨メッセージには、各メソッドの移行方法も説明されています。 play.api.Configuration の適切な使い方の詳細については、Scala Configurationドキュメント を参照してください。

Play JSON APIの変更

JSON配列インデックスの参照

Scala play-json APIを使用している場合は、JsLookup暗黙クラスの動作に少し変更があります。たとえば、次のようなコードがあるとします。

val bar = (jsarray(index) \ "bar").as[Bar]

indexは配列インデックスで、jsarrayはJsArrayです。これで、次のように記述する必要があります。

val bar = (jsarray \ index \ "bar").as[Bar]

これは、Scalaの他のコレクションのインデックスに沿った JsArrays のインデックス作成の動作を実現するために行われました。これで、 jsarray(index) メソッドはインデックスの値を返し、存在しなければ例外をスローします。

削除されたAPI

削除されたCrypto API

Crypto APIは、廃止予定のクラス play.api.libs.Crypto、play.libs.Crypto および AESCTRCrypter を削除しました。 Crypto へのCSRF参照は CSRFTokenSigner に置き換えられました。 Crypto へのセッションCookieの参照が CookieSigner に置き換えられました。詳細については、 CryptoMigration25 を参照してください。

Akka廃止されたメソッドが削除されました

廃止予定の静的メソッド play.libs.Akka.system および play.api.libs.concurrent.Akka.system が削除されました。依存関係注入を使用して ActorSystem のインスタンスを取得し、アクターシステムにアクセスします。

Scalaの場合:

class MyComponent @Inject() (system: ActorSystem) {

}

Javaの場合:

public class MyComponent {

    private final ActorSystem system;

    @Inject
    public MyComponent(ActorSystem system) {
        this.system = system;
    }
}

また、Play 2.6.xではAkka 2.5.xリリースシリーズが使用されるようになりました。必要に応じて、独自のコードを適用する方法については、 2.4.xから2.5.xへのAkka移行ガイド をお読みください。

削除されたYaml API

私たちは play.libs.Yaml を削除しました。Play の中にもうそれを使用していなかったからです。 Play YAMLの統合をサポートする必要がある場合は、 snakeyamlbuild.sbt に追加する必要があります。

libraryDependencies += "org.yaml" % "snakeyaml" % "1.17"

あなたのコードに以下のWrapperを作成します:

public class Yaml {

    private final play.Environment environment;

    @Inject
    public Yaml(play.Environment environment) {
        this.environment = environment;
    }

    /**
     * Load a Yaml file from the classpath.
     */
    public Object load(String resourceName) {
        return load(
            environment.resourceAsStream(resourceName),
            environment.classLoader()
        );
    }

    /**
     * Load the specified InputStream as Yaml.
     *
     * @param classloader The classloader to use to instantiate Java objects.
     */
    public Object load(InputStream is, ClassLoader classloader) {
        org.yaml.snakeyaml.Yaml yaml = new org.yaml.snakeyaml.Yaml(new CustomClassLoaderConstructor(classloader));
        return yaml.load(is);
    }

}

またはScalaで:

class Yaml @Inject()(environment: play.api.Environment) {
  def load(resourceName: String) = {
    load(environment.resourceAsStream(resourceName), environment.classLoader)
  }

  def load(inputStream: InputStream, classLoader: ClassLoader) = {
    new org.yaml.snakeyaml.Yaml(new CustomClassLoaderConstructor(classloader)).load(inputStream)
  }
}

Playの代替DIライブラリに明示的に依存している場合、または独自のカスタムアプリケーションローダーを定義している場合は、変更は必要ありません。

Play DIサポートを提供するライブラリは、 play.application.loader 設定キーを定義する必要があります。外部DIライブラリが提供されていない場合は、 ApplicationLoader をポイントしない限り、Playは起動を拒否します。

廃止予定の play.Routes を削除しました。

JavaScriptルータを作成するために使用された廃止予定のplay.Routesクラスが削除されました。新しいJavaまたはScalaヘルパーを使用する必要があります。

削除されたライブラリ

デフォルトのプレイ配布を少し小さくするために、いくつかのライブラリを削除しました。以下のライブラリは、もはやPlay 2.6の依存関係ではありませんので、使用する場合は手動でビルドに追加する必要があります。

joda-time の削除

java.time APIを使用することをお勧めします。そのため、Playのコアからjoda-timeサポートを削除します。

PlayのScalaフォームライブラリには、いくつかのJodaフォーマットがありました。移行しない場合は、jodaFormsモジュールをbuild.sbtに追加できます。

libraryDependencies += jodaForms

そして、対応するオブジェクトをインポートします:

import play.api.data.JodaForms._

play-jsonでJodaサポートが必要な場合は、次の依存関係を追加できます。

libraryDependencies += "com.typesafe.play" %% "play-json-joda" % playJsonVersion

ここで、playJsonVersionは使用したいplay-jsonバージョンです。 Play 2.6.xはplay-json 2.6.xと互換性があります。 play-jsonは別のプロジェクトになりました(後述)。

import play.api.libs.json.JodaWrites._
import play.api.libs.json.JodaReads._

Joda-Convertの削除

あなたがあなたのプロジェクトでそれをあなたのbuild.sbtに追加する必要があるならば、playはjoda-convertの内部使用をいくつか持っていました:

libraryDependencies += "org.joda" % "joda-convert" % "1.8.1"

XercesImplの削除

XML処理の場合PlayはXerces XML Libraryを使用しました。現代のJVMは参照実装としてXercesを使用しているので、それを削除しました。プロジェクトが外部パッケージに依存している場合は、単純にbuild.sbtに追加することができます。

libraryDependencies += "xerces" % "xercesImpl" % "2.11.0"

H2除去

以前のバージョンのPlayでは、H2データベースがプリインストールされていました。しかし、Playのコアを小さくするために、削除しました。 H2を使用する場合は、それをbuild.sbtに追加することができます:

libraryDependencies += "com.h2database" % "h2" % "1.4.193"

テストでのみ使用した場合は、Testスコープを使用することもできます。

libraryDependencies += "com.h2database" % "h2" % "1.4.193" % Test

依存関係を追加した後でもH2ブラウザは動作します。

snakeyaml 除去

play.libs.Yaml を削除しました。したがって、 snakeyaml への依存関係は削除されました。まだ使用している場合は、 build.sbt に追加してください:

libraryDependencies += "org.yaml" % "snakeyaml" % "1.17"

[Yaml APIの削除に関する注意] も参照してください。

Tomcat-servlet-apiの削除

tomcat-servlet-api は使用されていなかったので、Playで削除されました。まだ使用している場合は、 build.sbt に追加してください:

libraryDependencies += "org.apache.tomcat" % "tomcat-servlet-api" % "8.0.33"

リクエスト属性

すべての要求オブジェクトに属性が含まれるようになりました。リクエスト属性は、リクエストタグの代わりとなります。タグは廃止され、属性にアップグレードする必要があります。属性はタグより強力です。属性を使用してオブジェクトを要求に格納できますが、タグはストリングの格納のみをサポートしています。

リクエストタグの非推奨

タグは廃止されましたので、タグを使用してから属性を使用するように移行する必要があります。マイグレーションはかなり簡単です。

最も簡単な移行パスは、タグからString型の属性に移行することです。

以前のJava:

// Getting a tag from a Request or RequestHeader
String userName = req.tags().get("userName");
// Setting a tag on a Request or RequestHeader
req.tags().put("userName", newName);
// Setting a tag with a RequestBuilder
Request builtReq = requestBuilder.tag("userName", newName).build();

これからのJava:

class Attrs {
  public static final TypedKey<String> USER_NAME = TypedKey.<String>create("userName");
}

// Getting an attribute from a Request or RequestHeader
String userName = req.attrs().get(Attrs.USER_NAME);
String userName = req.attrs().getOptional(Attrs.USER_NAME);
// Setting an attribute on a Request or RequestHeader
Request newReq = req.withTags(req.tags().put(Attrs.USER_NAME, newName));
// Setting an attribute with a RequestBuilder
Request builtReq = requestBuilder.attr(Attrs.USER_NAME, newName).build();

以前のScala:

// Getting a tag from a Request or RequestHeader
val userName: String = req.tags("userName")
val optUserName: Option[String] = req.tags.get("userName")
// Setting a tag on a Request or RequestHeader
val newReq = req.copy(tags = req.tags.updated("userName", newName))

これからのScala:

object Attrs {
  val UserName: TypedKey[String] = TypedKey("userName")
}
// Getting an attribute from a Request or RequestHeader
val userName: String = req.attrs(Attrs.UserName)
val optUserName: [String] = req.attrs.get(Attrs.UserName)
// Setting an attribute on a Request or RequestHeader
val newReq = req.addAttr(Attrs.UserName, newName)

ただし、適切な場合は、StringタグをString以外の値を持つ属性に変換することをお勧めします。タグをString以外のオブジェクトに変換すると、いくつかの利点があります。まず、コードの型をより安全にします。これにより、コードの信頼性が向上し、理解しやすくなります。次に、属性に格納するオブジェクトには複数のプロパティを含めることができるため、複数のタグを単一の値に集約できます。第3に、タグを属性に変換すると、文字列の値をエンコードしてデコードする必要がなくなるため、パフォーマンスが向上する可能性があります。

class Attrs {
  public static final TypedKey<User> USER = TypedKey.<User>create("user");
}

後のスカラ:

object Attrs {
  val UserName: TypedKey[User] = TypedKey("user")
}

FakeRequest.withCookies を呼び出すと Cookies ヘッダーが更新されなくなりました

リクエストクッキーはリクエスト属性に格納されるようになりました。以前は、リクエストの Cookie ヘッダ文字列に格納されていました。これは、クッキーが変更されるたびにヘッダーにクッキーをエンコードしてデコードする必要がありました。

クッキーがリクエスト属性に格納されるようになったので、クッキーを更新すると新しいクッキー属性は変更されますが、Cookie HTTPヘッダーは変更されません。これは、 withCookies を呼び出してヘッダを更新する場合にのみ、テストに影響します。

それでもなお古い動作が必要な場合は、 Cookies.encodeCookieHeader を使用してCookieオブジェクトをHTTPヘッダーに変換し、 FakeRequest.withHeaders でヘッダーを保存することができます。

play.api.mvc.Security.username (Scala API)、session.username 変更

play.api.mvc.Security.username(Scala API)、 session.username 設定キーおよび依存アクションヘルパーは推奨されていません。 Security.username は、設定から session.username キーを取得するだけで、ユーザー名を取得するために使用されたセッションキーが定義されています。静的な動作が必要なため削除されました。同一または類似の動作を自分で実装するのはかなり簡単です。

configuration.get[String]( "session.username") を使用して、設定からユーザー名セッションキーを読み取ることができます。

Authenticated(String => EssentialAction) メソッドを使用している場合は、簡単に独自のアクションを作成して同様のことを行うことができます。

def AuthenticatedWithUsername(action: String => EssentialAction) =
  WithAuthentication[String](_.session.get(UsernameKey))(action)

UsernameKeyは、ユーザー名に使用するセッションキーを表します。

リクエストセキュリティ(Java API)ユーザ名プロパティが属性になりました

Java Requestオブジェクトには、Security.AuthenticatedアノテーションがJavaアクションに追加されたときに設定される username プロパティが含まれています。 Play 2.6では、 username プロパティは廃止されました。 usernameプロパティのメソッドが更新され、 Security.USERNAME 属性にユーザー名が格納されます。 Security.USERNAME 属性を直接使用するようにコードを更新する必要があります。 Playの将来のバージョンでは、 username プロパティを削除します。

この変更の理由は、usernameプロパティが Security.Authenticated アノテーションの特別なケースとして提供されたためです。これで特別なケースは必要なくなりました。

既存のJavaコード:

// Set the username
Request reqWithUsername = req.withUsername("admin");
// Get the username
String username = req1.username();
// Set the username with a builder
Request reqWithUsername = new RequestBuilder().username("admin").build();

アップデートされたJavaコード:

import play.mvc.Security.USERNAME;

// Set the username
Request reqWithUsername = req.withAttr(USERNAME, "admin");
// Get the username
String username = req1.attr(USERNAME);
// Set the username with a builder
Request reqWithUsername = new RequestBuilder().putAttr(USERNAME, "admin").build();

ルータタグは属性になりました

Router.Tags.* タグを使用した場合は、新しい Router.Attrs.HandlerDef (Scala) または Router.Attrs.HANDLER_DEF (Java)属性を使用するようにコードを変更する必要があります。 既存のタグは引き続き使用できますが、廃止され、今後のバージョンのPlayで削除されます。

この新しい属性には、現在タグ内にあるすべての情報を含む HandlerDef オブジェクトが含まれています。 現在のタグは、すべてHandlerDefオブジェクトのフィールドに対応します。

|Javaタグ名|Scalaタグ名|HandlerDefメソッド|
+-------+-----------+----------------+
|ROUTE_PATTERN | RoutePattern | path|
|ROUTE_VERB | RouteVerb |verb|
|ROUTE_CONTROLLER | RouteController |controller|
|ROUTE_ACTION_METHOD | RouteActionMethod |method|
|ROUTE_COMMENTS | RouteComments |comments|

注:この変更の一環として、 HandlerDef オブジェクトが play.core.routing 内部パッケージから play.api.routing パブリックAPIパッケージに移動されました。

play.api.libs.concurrent.Executionは推奨されていません

play.api.libs.concurrent.Execution クラスは、"現在の" アプリケーションのExecutionContextをプルするためにグローバルな可変状態を使用していたため、廃止されました。

以前に行った暗黙的な動作を指定する場合は、 依存関係注入 を使用してコンストラクタに暗黙的に実行コンテキストを渡す必要があります。

class MyController @Inject()(implicit ec: ExecutionContext) {

}

コンパイル時依存関係注入を使用している場合はBuiltInComponentsから取得します。

class MyComponentsFromContext(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context) {
  val myComponent: MyComponent = new MyComponent(executionContext)
}

ただし、一般的な場合でも実行コンテキストをインポートしたくない理由がいくつかあります。一般的なケースでは、アプリケーションの実行コンテキストは、アクションのレンダリングや、APIコールや I/O アクティビティのブロックに関係しないCPUバウンドアクティビティの実行に適しています。データベースを呼び出す場合やネットワーク呼び出しを行う場合は、独自のカスタム実行コンテキストを定義することができます。

カスタム実行コンテキストを作成するには、 Custom ExecutionContext を使用することをお勧めします。これは、Akkaディスパッチャシステム(java / scala )を使用して、エグゼキュータをコンフィグレーションで定義できるようにします。

独自の実行コンテキストを使用するには、 CustomExecutionContext 抽象クラスを application.conf ファイルのディスパッチャへのフルパスで拡張します。

import play.api.libs.concurrent.CustomExecutionContext

class MyExecutionContext @Inject()(actorSystem: ActorSystem)
 extends CustomExecutionContext(actorSystem, "my.dispatcher.name")
import play.libs.concurrent.CustomExecutionContext;
class MyExecutionContext extends CustomExecutionContext {
   @Inject
   public MyExecutionContext(ActorSystem actorSystem) {
     super(actorSystem, "my.dispatcher.name");
   }
}

必要に応じてカスタム実行コンテキストを注入します。

class MyBlockingRepository @Inject()(implicit myExecutionContext: MyExecutionContext) {
   // do things with custom execution context
}

カスタムスレッドプール設定の詳細については、 ThreadPools ページを、CustomExecutionContextを使用する場合は JavaAsync / ScalaAsync を参照してください。

play.api.testヘルパーへの変更

推奨されない次のテストヘルパーは、2.6.xで削除されました。

Java API

  • play.test.FakeRequestRequestBuilder に置き換えられました
  • play.test.FakeApplicationplay.inject.guice.GuiceApplicationBuilder に置き換えられました。 play.test.Helpers.fakeApplication から新しいアプリケーションを作成できます。
  • play.test.WithApplicationでは、廃止予定の provideFakeApplication メソッドが削除されました。provideApplication メソッドを使用する必要があります。

テンプレートヘルパーの変更

views/helper/requireJs.scala.html の requireJs テンプレートヘルパーは、 Play.maybeApplication を使用して設定にアクセスしました。

requireJs テンプレートヘルパーには、追加されたヘルパーのバージョンを使用する必要があるかどうかを示す追加パラメータ isProd が追加されています。

@requireJs(core = routes.Assets.at("javascripts/require.js").url, module = routes.Assets.at("javascripts/main").url, isProd = true)

MIMEタイプマッピングへのファイル拡張の変更

ファイル拡張子のMIMEタイプへのマッピングは、 reference.conf に移動されているので、 play.http.fileMimeTypes 設定の下で、設定を通して完全にカバーされています。以前は、リストは play.api.libs.MimeTypes の下にハードコードされていました。

play.http.fileMimeTypes の設定は、トリプルクォートを単一の文字列として定義していることに注意してください。これは、複数のファイル拡張子に c++ などの HOCON を壊す構文があるためです。

カスタムMIMEタイプを追加するには、 HOCON文字列値の連結 を使用します。

play.http.fileMimeTypes = ${play.http.fileMimeTypes} """
  foo=text/bar
"""

MIMEタイプを追加するために mimetype.foo=text/bar として定義された設定を可能にする構文があります。これは推奨されていません。上記の設定を使用することをお勧めします。

Java API

Http.Context.current().fileMimeTypes() メソッドは、 Results.sendFile のフードの下にあり、ファイル拡張子からコンテンツタイプを検索するその他のメソッドがあります。移行は必要ありません。

Scala API

play.api.libs.MimeTypes クラスが play.api.http.FileMimeTypes インターフェイスに変更され、実装が play.api.http.DefaultFileMimeTypes に変更されました。

ファイルまたはリソースを送信するすべての結果は、暗黙的に FileMimeTypes をとります。

implicit val fileMimeTypes: FileMimeTypes = ...
Ok(file) // <-- takes implicit FileMimeTypes

FileMimeTypes の暗黙のインスタンスは、便利なバインディングを提供するために、 BaseController(およびそのサブクラス AbstractController およびsubtrait InjectedController)によって ControllerComponents クラスによって提供されます。

class SendFileController @Inject() (cc: ControllerComponents) extends AbstractController(cc) {

  def index() = Action { implicit request =>
     val file = readFile()
     Ok(file)  // <-- takes implicit FileMimeTypes
  }
}

単体テストで完全に構成されたFileMimeTypesインスタンスを直接取得することもできます。

val httpConfiguration = new HttpConfigurationProvider(Configuration.load(Environment.simple)).get
val fileMimeTypes = new DefaultFileMimeTypesProvider(httpConfiguration.fileMimeTypes).get

またはカスタムのものを入手する:

val fileMimeTypes = new DefaultFileMimeTypesProvider(FileMimeTypesConfiguration(Map("foo" -> "text/bar"))).get

デフォルトのフィルタ

Play には、設定によって定義された有効なフィルタのデフォルトセットが付属しています。 play.http.filters プロパティがnullの場合、デフォルトは play.filters.enabled 設定プロパティの完全修飾クラス名で定義されたフィルタをロードする play.api.http.EnabledFilters になります。

Play 自体では、 play.filters.enabled は空のリストです。ただし、フィルタライブラリは自動的に PlayFilters という AutoPlugin として SBT にロードされ、次の値が play.filters.enabled プロパティに追加されます。

つまり、新しいプロジェクトでは、CSRF保護( ScalaCsrf / JavaCsrf )、 SecurityHeaders および AllowedHostsFilter はすべて自動的に定義されます。

デフォルトフィルタの効果

既定のフィルタは、プロジェクトに「デフォルトでセキュリティで保護された」構成を与えるように構成されています。

これらのフィルタは有効にしておく必要があります。アプリケーションをより安全にするためです。

既存のプロジェクトでこれらのフィルタを有効にしていない場合は、いくつかの設定が必要となり、関連するエラーや失敗に精通していない可能性があります。移行を支援するために、各フィルタ、そのフィルタ、必要な設定について説明します。

CSRFFilter

CSRFフィルタについては ScalaCsrfJavaCsrf で説明しています。これは、POSTリクエストでチェックされるフォームにCSRFトークンを追加することにより、 クロスサイト要求偽造攻撃 から保護します。

デフォルトで有効になっている理由

CSRFは非常に一般的な攻撃であり、実装に必要なスキルはほとんどありません。 Playを使用してCSRF攻撃の例を見ることができます(https://github.com/Manc/play-scala-csrf)。

どのような変更が必要ですか?

CSRF.formField などのCSRFフォームヘルパを使用しない既存のプロジェクトから移行する場合は、CSRFフィルタのPUTおよびPOSTリクエストに「403 Forbidden」が表示されることがあります。

CSRF.formField をフォームテンプレートに追加するとエラーが解決されます。AJAXでリクエストを作成する場合は、HTMLページにCSRFトークンを置き、 Csrf-Token ヘッダーを使用して要求に追加できます。

この動作を確認するには、 logback.xml<logger name = "play.filters.csrf" value = "TRACE" /> を追加してください。

また、 Play の SameSite Cookie を有効にして、CSRF攻撃に対する追加防御を提供することもできます。

SecurityHeadersFilter

SecurityHeadersFilter は、リクエストに余分なHTTPヘッダーを追加することで、 クロスサイトスクリプティングクリックジャック攻撃 を防ぎます。

デフォルトで有効になっている理由

ブラウザベースの攻撃は非常に共通しています。セキュリティヘッダーは、これらの攻撃を阻止するための深い防御を提供します。

どのような変更が必要ですか?

デフォルトの "Content-Security-Policy" の設定は非常に厳密です。最も有用な設定を見つけるには、それを試す必要があります。コンテンツセキュリティポリシーの設定では、Javascriptとリモートフレームがブラウザにどのように表示されるかが変更されます。 Content-Security-Policyヘッダーを変更するまで、埋め込まれたJavascriptまたはCSSはWebページに読み込まれません。

有効にしたくない場合は、次のようにContent-Security-Policyを無効にすることができます。

play.filters.headers.contentSecurityPolicy=null

CSP-Useful は、一般的な Content-Security-Policy の優れたリソースです。すべてのリクエストにカスタムCSPナンスを追加するなど、埋め込まれたJavascriptに対する他の潜在的な解決策があることに注意してください。

他のヘッダーは侵入性が低く、プレーンなWebサイトで問題を引き起こす可能性は低いですが、シングルページアプリケーションでCookieやレンダリングの問題が発生する可能性があります。 Mozillaには、URLのヘッダ名を使用して、各ヘッダを詳細に記述するドキュメントがあります。たとえば、X-Frame-Optionsの場合は https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options に行きます。

play.filters.headers {

    # The X-Frame-Options header. If null, the header is not set.
    frameOptions = "DENY"

    # The X-XSS-Protection header. If null, the header is not set.
    xssProtection = "1; mode=block"

    # The X-Content-Type-Options header. If null, the header is not set.
    contentTypeOptions = "nosniff"

    # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set.
    permittedCrossDomainPolicies = "master-only"

    # The Content-Security-Policy header. If null, the header is not set.
    contentSecurityPolicy = "default-src 'self'"

    # The Referrer-Policy header. If null, the header is not set.
    referrerPolicy = "origin-when-cross-origin, strict-origin-when-cross-origin"

    # If true, allow an action to use .withHeaders to replace one or more of the above headers
    allowActionSpecificHeaders = false
}

AllowedHostsFilter

AllowedHostsFilter は、許可されたホストのホワイトリストを追加し、ホワイトリストと一致しないホストを持つすべての要求に 400(Bad Request) 応答を送信します。

デフォルトで有効になっている理由

DNSリバインディング攻撃は、開発者のPlayのインスタンスに対して使用できるため、開発で使用する重要なフィルタです。短期間のDNS再バインドがlocalhost上で動作するサーバを攻撃する方法の例については、Rails Webconsole DNS Rebinding を参照してください。

どのような変更が必要ですか?

localhost 以外のアプリケーションでPlayアプリケーションを実行している場合は、 AllowedHostsFilter を設定して、接続先の ホスト名/IP を特に許可する必要があります。通常、開発環境ではlocalhostで実行されますが、ステージングや本番環境ではリモートで実行されるため、環境を変更するときに注意する必要があります。

play.filters.hosts {
  # Allow requests to example.com, its subdomains, and localhost:9000.
  allowed = [".example.com", "localhost:9000"]
}

フィルタに追加する

デフォルトリストに追加するには、 +=

play.filters.enabled+=MyFilter

play.api.http.DefaultHttpFilters を拡張して独自のフィルタを定義した場合、 EnabledFilters とコード内の独自のリストを組み合わせることもできます。これまでにプロジェクトを定義していたとしても、通常どおりに機能します。

class Filters @Inject()(enabledFilters: EnabledFilters, corsFilter: CORSFilter)
  extends DefaultHttpFilters(enabledFilters.filters :+ corsFilter: _*)

デフォルトフィルタのテスト

いくつかのフィルターが有効になっているため、すべてのテストが合格し、要求が有効であることを確認するために機能テストを少し変更する必要があります。たとえば、 Host HTTPヘッダーが localhost に設定されていない要求は AllowedHostsFilter を渡さず、代わりに 400 Forbidden 応答を返します。

AllowedHostsFilterを使用したテスト

AllowedHostsFilterフィルターが自動的に追加されるため、機能テストでは、Host HTTPヘッダーが追加されている必要があります。

FakeRequest または Helpers.fakeRequest を使用している場合は、Host HTTPヘッダーが自動的に追加されます。 play.mvc.Http.RequestBuilder を使用している場合は、ヘッダを手動で追加するために独自の行を追加する必要があります。

RequestBuilder request = new RequestBuilder()
        .method(GET)
        .header(HeaderNames.HOST, "localhost")
        .uri("/xx/Kiwi");

CSRFFilterによるテスト

CSRFFilterフィルタが自動的に追加されるので、 CSRF.formField を含むTwirlテンプレートをレンダリングするテスト。

@(userForm: Form[UserData])(implicit request: RequestHeader, m: Messages)

<h1>user form</h1>

@request.flash.get("success").getOrElse("")

@helper.form(action = routes.UserController.userPost()) {
  @helper.CSRF.formField
  @helper.inputText(userForm("name"))
  @helper.inputText(userForm("age"))
  <input type="submit" value="submit"/>
}

要求にCSRFトークンを含める必要があります。 Scala APIでは、これは play.api.test.CSRFTokenHelper._ をインポートすることによって実行されます。これは play.api.test.FakeRequestwithCSRFToken メソッドで埋められます:

import play.api.test.CSRFTokenHelper._

class UserControllerSpec extends PlaySpec with GuiceOneAppPerTest {
  "UserController GET" should {

    "render the index page from the application" in {
      val controller = app.injector.instanceOf[UserController]
      val request = FakeRequest().withCSRFToken
      val result = controller.userGet().apply(request)

      status(result) mustBe OK
      contentType(result) mustBe Some("text/html")
    }
  }
}

Java APIでは、これは play.mvc.Http.RequestBuilder インスタンスで CSRFTokenHelper.addCSRFToken を呼び出すことによって行われます。

requestBuilder = CSRFTokenHelper.addCSRFToken(requestBuilder);

デフォルトのフィルタを無効にする

デフォルトのフィルタを無効にする最も簡単な方法は、 application.conf に手動でフィルタのリストを設定することです。

play.filters.enabled = []

これは、デフォルトのフィルタを使用したくない機能テストがある場合に便利です。

すべてのフィルタクラスを削除する場合は、 disablePlugins メカニズムを使用してフィルタクラスを無効にすることができます。

lazy val root = project.in(file(".")).enablePlugins(PlayScala).disablePlugins(PlayFilters)

あるいは EnabledFilters で置換

play.http.filters = play.api.http.NoHttpFilters

GuiceApplicationBuilder を含む機能テストを作成していて、デフォルトのフィルタを無効にしたい場合は、 configure を使用してフィルタをすべて無効にすることができます。

GuiceApplicationBuilder().configure("play.http.filters" -> "play.api.http.NoHttpFilters")

コンパイル時のデフォルトフィルタ

コンパイル時依存関係注入を使用している場合、デフォルトのフィルタは実行時ではなくコンパイル時に解決されます。

これは、 BuiltInComponents トレイトに httpFilters メソッドが含まれていて、抽象化されたままであることを意味します。

trait BuiltInComponents {

  /** A user defined list of filters that is appended to the default filters */
  def httpFilters: Seq[EssentialFilter]
}

フィルタのデフォルトリストは play.filters.HttpFiltersComponents で定義されています:

trait HttpFiltersComponents
     extends CSRFComponents
     with SecurityHeadersComponents
     with AllowedHostsComponents {

   def httpFilters: Seq[EssentialFilter] = Seq(csrfFilter, securityHeadersFilter, allowedHostsFilter)
}

ほとんどの場合、 HttpFiltersComponents をミックスして独自のフィルタを追加する必要があります:

class MyComponents(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context)
  with play.filters.HttpFiltersComponents {

  lazy val loggingFilter = new LoggingFilter()
  override def httpFilters = {
    super.httpFilters :+ loggingFilter
  }
}

リストから要素をフィルタリングする場合は、次の操作を実行できます。

class MyComponents(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context)
  with play.filters.HttpFiltersComponents {
  override def httpFilters = {
    super.httpFilters.filterNot(_.getClass == classOf[CSRFFilter])
  }
}

コンパイル時デフォルトフィルタの無効化

デフォルトのフィルタを無効にするには、 play.api.NoHttpFiltersComponents をミックスインします:

class MyComponents(context: ApplicationLoader.Context)
   extends BuiltInComponentsFromContext(context)
   with NoHttpFiltersComponents
   with AssetsComponents {

  lazy val homeController = new HomeController(controllerComponents)
  lazy val router = new Routes(httpErrorHandler, homeController, assets)
}

JWTサポート

Play の Cookie エンコーディングが JSON Webトークン(JWT) を使用するように切り替わりました。 JWTには、HMAC-SHA-256による自動署名や、セッションクッキーが指定された時間枠外で再利用できないことを保証する自動「前回」および「期限切れ」日付チェックのサポートなど、多くの利点があります。

詳細は、「セッションCookieの設定」ページを参照してください。

フォールバッククッキーのサポート

PlayのCookieエンコーディングは、JWTでエンコードされたCookieを読み込み、JWTの解析が失敗した場合にURLでエンコードされたCookieを読み取ろうとする「フォールバック」Cookieエンコードメカニズムを使用しているため、既存のセッションCookieをJWTに安全に移行できます。この機能は FallbackCookieDataCodec トレイトにあり、 DefaultSessionCookieBakerDefaultFlashCookieBaker を利用しています。

レガシーサポート

JWTでエンコードされたクッキーを使用することはシームレスでなければなりませんが、必要に応じて application.conf ファイルの play.api.mvc.LegacyCookiesModule に切り替えることでURLエンコードされたクッキーエンコーディングに戻すことができます:

play.modules.disabled+="play.api.mvc.CookiesModule"
play.modules.enabled+="play.api.mvc.LegacyCookiesModule"

カスタムCookieBakers

カスタム Cookie が CookieBaker[T]トレイトを使用して Play で使用されている場合は、カスタム Cookie ベーカーに必要なエンコーディングの種類を指定する必要があります。

The encode and decode methods that Map[String, String] to and from the format found in the browser have been extracted into CookieDataCodecFallbackCookieDataCodecJWTCookieDataCodec 、または UrlEncodedCookieDataCodec の3つの実装があります。それぞれHMAC、JWT、または「JWTの書き込みコードまたはJWTの読み取り」コーデックでURLエンコードされています。

また、JWTConfigurationParser を使用して構成へのパスを使用して JWTConfiguration case class を提供するか、またはデフォルトの JWTConfiguration() を使用する必要があります。

@Singleton
class UserInfoCookieBaker @Inject()(service: UserInfoService,
                                    val secretConfiguration: SecretConfiguration)
  extends CookieBaker[UserInfo] with JWTCookieDataCodec {

  override val COOKIE_NAME: String = "userInfo"

  override val isSigned = true

  override def emptyCookie: UserInfo = new UserInfo()

  override protected def serialize(userInfo: UserInfo): Map[String, String] = service.encrypt(userInfo)

  override protected def deserialize(data: Map[String, String]): UserInfo = service.decrypt(data)

  override val path: String = "/"

  override val jwtConfiguration: JWTConfiguration = JWTConfigurationParser()
}

非推奨のFuturesメソッド

次の play.libs.concurrent.Futures 静的メソッドは廃止予定です:

  • timeout(A value, long amount, TimeUnit unit)
  • timeout(final long delay, final TimeUnit unit)
  • delayed(Supplier<A> supplier, long delay, TimeUnit unit, Executor executor)

依存関係が挿入された Futures のインスタンスを代わりに使用する必要があります。

class MyClass {
    @Inject
    public MyClass(play.libs.concurrent.Futures futures) {
        this.futures = futures;
    }

    CompletionStage<Double> callWithOneSecondTimeout() {
        return futures.timeout(computePIAsynchronously(), Duration.ofSeconds(1));
    }
}

更新されたライブラリ

Netty 4.1

Nettyは バージョン4.1 にアップグレードされました。これは主に、バージョン4.0が スタンドアローンモジュールへのplay-wsの移行 によって網羅されていたために可能でした。したがって、 Netty Server と Netty 4.0に依存するライブラリを使用している場合は、ライブラリの新しいバージョンにアップグレードするか、 Akka Server の使用を開始することをお勧めします。

何らかの理由でNettyクラスを直接使用している場合は、 コードをこの新しいバージョンに適合させる 必要があります。

FluentLeniumとSelenium

FluentLeniumライブラリはバージョン 3.2.0 にアップデートされ、Selenium はバージョン 3.3.1 にアップデートされました(ここで変更履歴をご覧ください)。以前に Selenium の WebDriver API を使用していた場合は、何もするべきではありません。詳細については、 この アナウンスを確認してください。
FluentLenium ライブラリを使用していた場合は、テストを再開するためにいくつかの構文を変更する必要があります。あなたのコードを変更する方法の詳細については、FluentLeniumの 移行ガイド を参照してください。

HikariCP

HikariCP が更新され、新しい設定が導入されました: initializationFailTimeout 。この新しい構成は、現在廃止されている initializationFailFast の代わりに使用する必要があります。この新しい設定の使い方を理解するには、 HikariCPの変更ログinitializationFailTimeoutのドキュメント を参照してください。

その他の構成の変更

いくつかの設定変更があります。通常、古い設定パスは動作しますが、使用すると、実行時に非推奨警告が出力されます。変更されたキーの概要を以下に示します。

古いキー 新しいキー
play.crypto.secret play.http.secret.key
play.crypto.provider play.http.secret.provider
play.websocket.buffer.limit play.server.websocket.frame.maxLength