§Play 2.7 移行ガイド
これは、Play 2.6からPlay 2.7に移行するためのガイドです。Playの以前のバージョンから移行する必要がある場合は、最初にPlay 2.6移行ガイドに従う必要があります。
§移行方法
sbtでPlayプロジェクトを読み込み/実行する前に、sbtビルドを更新するには、次の手順を実行する必要があります。
§Playのアップグレード
Playをアップグレードするには、`project/plugins.sbt`のPlayバージョン番号を更新します
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.x")
`2.7.x`の「x」は、使用するPlayのマイナーバージョンです。たとえば、`2.7.0`です。
§sbt 1.2.8へのアップグレード
Play 2.7はsbt 0.13シリーズをまだサポートしていますが、今後sbt 1.xを使用することをお勧めします。この新しいバージョンは積極的にメンテナンスおよびサポートされています。更新するには、`project/build.properties`を次のように変更します
sbt.version=1.2.8
これを書いている時点では、`1.2.8`はsbt 1.xファミリの最新バージョンです。より新しいバージョンも使用できる場合があります。Play 2.7.xのマイナーバージョンのリリースノートで詳細を確認してください。詳細については、sbtリリースのリストをご覧ください。
§APIの変更
既存のAPIを削除する前に廃止するというポリシーに従って、複数のAPIが変更されました。このセクションでは、これらの変更について詳しく説明します。
§廃止されたAPIが削除されました
以前のバージョンで廃止された多くのAPIは、Play 2.7で削除されました。まだ使用している場合は、Play 2.7にアップグレードする前に新しいAPIに移行することをお勧めします。JavadocとScaladocの両方には、通常、移行方法に関する適切なドキュメントがあります。詳細については、Play 2.6の移行ガイドを参照してください。
§StaticRoutesGeneratorが削除されました
2.6.0で廃止された`StaticRoutesGenerator`は削除されました。まだ使用している場合は、`build.sbt`ファイルから次のような行を削除する必要があるでしょう
routesGenerator := StaticRoutesGenerator
§Java `Http.Context`の変更
`play.mvc.Http.Context` APIで行われた変更を参照してください。これはJavaユーザーのみに関係します:Java `Http.Context`の変更。
§Play WSの変更
Play 2.6では、Play-WSのほとんどを、独立したリリースサイクルを持つスタンドアロンプロジェクトに抽出しました。Play-WSには、Play自体にいくつかの変更が必要な重要なリリースがあります。
§Cookieストアの処理
Play-WS 2.0は、グローバルな内部Cookieストアを持つAsync-Http-Clientの更新バージョンを提供します。サードパーティサービスへのリクエストでユーザーの機密Cookieを送信する場合、アプリケーションに影響を与える可能性があります。たとえば、Cookieストアはグローバルであるため、アプリケーションは同じホストにリクエストを行うときに、あるユーザーのCookieを別のユーザーのCookieと混同する可能性があります。キャッシュを有効または無効にするために使用できる新しい構成があります
# Enables global cache cookie store
play.ws.ahc.useCookieStore = true
デフォルトでは、キャッシュは無効になっています。これは、リダイレクトに自動的に従うなど、他の場所にも影響します。以前は、最初のリクエストのCookieが後続のリクエストで送信されていましたが、キャッシュが無効になっている場合はそうではありません。現在、リクエストごとにキャッシュを設定する方法はありません。
§Scala API
- `play.api.libs.ws.WSRequest.requestTimeout`は、`Option[Int]`ではなく`Option[Duration]`を返すようになりました。
§Java API
- `play.libs.ws.WSRequest.getUsername`は、`String`ではなく`Optional<String>`を返すようになりました。
- `play.libs.ws.WSRequest.getContentType` は、`String` ではなく `Optional<String>` を返すようになりました。
- `play.libs.ws.WSRequest.getPassword` は、`String` ではなく `Optional<String>` を返すようになりました。
- `play.libs.ws.WSRequest.getScheme` は、`WSScheme` ではなく `Optional<WSScheme>` を返すようになりました。
- `play.libs.ws.WSRequest.getCalculator` は、`WSSignatureCalculator` ではなく `Optional<WSSignatureCalculator>` を返すようになりました。
- `play.libs.ws.WSRequest.getRequestTimeout` は、`long` ではなく `Optional<Duration>` を返すようになりました。
- `play.libs.ws.WSRequest.getRequestTimeoutDuration` は、`play.libs.ws.WSRequest.getRequestTimeout` を使用するために削除されました。
- `play.libs.ws.WSRequest.getFollowRedirects` は、`boolean` ではなく `Optional<Boolean>` を返すようになりました。
Java APIを改善するために、いくつかの新しいメソッドも追加されました
新しいメソッド `play.libs.ws.WSResponse.getBodyAsSource` は、レスポンスボディを `Source<ByteString, ?>` に変換します。例えば
wsClient.url("https://play.dokyumento.jp")
.stream() // this returns a CompletionStage<StandaloneWSResponse>
.thenApply(StandaloneWSResponse::getBodyAsSource);
Java APIを改善するために追加されたその他のメソッド
- `play.libs.ws.WSRequest.getBody` は、そのリクエストに設定されたボディを返します。`play.libs.ws.WSRequestFilter` を実装する場合に役立ちます
- `play.libs.ws.WSRequest.getMethod` は、そのリクエストに設定されたメソッドを返します。
- `play.libs.ws.WSRequest.getAuth` は、`WSAuth` を返します。
- `play.libs.ws.WSRequest.setAuth` は、そのリクエストの `WSAuth` を設定します。
- `play.libs.ws.WSResponse.getUri` は、そのレスポンスの `URI` を取得します。
§BodyParsers APIの整合性
ボディパーサーのAPIは、バッファ長を定義するために`Integer`と`Long`を混在させて使用しており、値のオーバーフローにつながる可能性がありました。構成は、`Long`を使用するように統一されました。つまり、たとえば`play.api.mvc.PlayBodyParsers.DefaultMaxTextLength`に依存している場合は、`Long`を使用する必要があります。そのため、`play.api.http.ParserConfiguration.maxMemoryBuffer`も`Long`になりました。
§パーサーの`maxMemoryBuffer`制限
一部のペイロードは、解析時にメモリ内で展開されます。そのため、メモリ表現は、ワイヤから読み取られたプレーンテキスト表現よりも多くのスペースを占有します。JSONはこのような形式の1つです。サービス拒否を引き起こす可能性のあるメモリ不足エラーを防ぐために、ボディの解析とフォームのバインディングは`play.http.parser.maxMemoryBuffer`設定を尊重する必要があります。
特定のケースでは、`maxMemoryBuffer`を緩和することも可能です。JSON表現と展開された表現のサイズが異なり、異なる制限を使用する必要がある場合があります。次のように、カスタマイズされた制限を使用してフォームバインディングを使用できます
class MyController @Inject()(cc: ControllerComponents) {
// This will be the action that handles our form post
def myMethod = Action { implicit request: Request[_] =>
// create a new formBinding instance with increased limit
val defaultFormBinding: FormBinding = cc.parsers.formBinding(300*1024) // limit to 300KiB
form.bindFromRequest()(request, formBinding)
...
}
}
コントローラーには、常に`play.http.parser.maxMemoryBuffer`を尊重するように構築された`FormBinding`インスタンスがあります。コントローラー外のコードからフォームを使用する場合は、暗黙的な`FormBinding`を提供する必要がある場合があります。たとえば、ユニットテストを作成する場合は、テストには十分なハードコードされた制限を使用する`play.api.data.FormBinding.Implicits._`で提供される`FormBinding`を使用できます。スコープに暗黙的を追加します
`scala import play.api.data.FormBinding.Implicits._
§`FilePart`と`FileInfo`に追加された新しいフィールドとメソッド
`Scala`と`Java`の`FilePart`クラスには、`multipart/form-data`エンコーディングを介してアップロードされたファイルのファイルサイズとディスポジションタイプを提供する2つの新しいフィールド/メソッドがあります
- Scala API の
fileSize
と Java API のgetFileSize()
- Scala API の
dispositionType
と Java API のgetDispositionType()
Scala の FileInfo
クラスにも、dispositionType
フィールドが追加されました。
Scala で FilePart
または FileInfo
を含む case
文を使用している場合は、これらの新しいフィールドを含めるように文を更新する必要があります。そうしないと、コンパイルエラーが発生します。
- FilePart
-
case FilePart(key, filename, contentType, file, fileSize, dispositionType) => ... // Or if you don't use these new fields: case FilePart(key, filename, contentType, file, _, _) => ...
- FileInfo
-
case FileInfo(partName, filename, contentType, dispositionType) => ... // Or if you don't use these new fields: case FileInfo(partName, filename, contentType, _) => ...
§カスタムボディパーサーを使用する場合、アップロードされたファイルのサイズを FilePart
に渡す
Play Scala または Play Java で multipart/form-data
エンコーディングを使用してファイルをアップロードする場合、FilePart
は、Scala API の fileSize
と Java API の getFileSize()
を介してアップロードされたファイルのサイズを公開するようになりました。
ファイルアップロードにカスタムボディパーサーを使用する場合は、生成された FilePart
インスタンスにファイルサイズを自分で渡す必要があります。そうしないと、ファイルサイズは設定されず、デフォルトで -1
になります。更新されたカスタムマルチパートファイルパートボディパーサーの例を参照してください。これらの例では、処理されたバイト数(アップロードされたファイルの)の count
が、作成された FilePart
に渡されます。
§Java の FilePart
は、アップロードされたファイルの TemporaryFile
を公開する
デフォルトでは、multipart/form-data
エンコーディングを使用した ファイルのアップロード は、一時ファイルシステムにファイルを保存することに依存する TemporaryFile
API を使用します。
ただし、Play 2.6 までは、その TemporaryFile
に直接アクセスすることはできず、それが裏付けとなっている File
にのみアクセスできました。
Http.MultipartFormData<File> body = request.body().asMultipartFormData();
Http.MultipartFormData.FilePart<File> picture = body.getFile("picture");
if (picture != null) {
File file = picture.getFile();
}
上記で使用されている getFile()
メソッドは非推奨になり、代わりに getRef()
を使用する必要があります。これは、いくつかの便利なメソッド を備えた TemporaryFile
インスタンスを提供します。
Play 2.7 以降、上記のコードは次のようにリファクタリングする必要があります。
Http.MultipartFormData<TemporaryFile> body = request.body().asMultipartFormData();
Http.MultipartFormData.FilePart<TemporaryFile> picture = body.getFile("picture");
if (picture != null) {
TemporaryFile tempFile = picture.getRef();
File file = tempFile.path().toFile();
}
§copyTo
を追加し、TemporaryFile
の move メソッドの名前を変更しました
Play 2.5 までは、moveTo
メソッドは実際にはファイルのコピーを宛先に作成し、ソースを削除していました。Play 2.6 では、特定の条件に応じてファイルがアトミックに移動されるという微妙な変更がありました。このような場合、ソースと宛先の両方が同じ inode
を使用することになります。
これに関する API をより明確にするために、ソースファイルの inode
を共有しないコピーを常に作成する copyTo
メソッドが追加されました。
Play 2.7 のもう1つの変更点は、ファイルを移動する TemporaryFile
のメソッドの名前が変更されたことです。
非推奨のメソッド | 新しいメソッド |
---|---|
moveTo(...) |
moveFileTo(...) |
atomicMoveWithFallback(...) |
atomicMoveFileWithFallback(...) |
これらの新しいメソッドは、TemporaryFile
の代わりに Path
を返すようになりました。これらのメソッドから TemporaryFile
を返すのは、最初から間違いでした。なぜなら、誰かが、そのような返されたファイルが実際のテンポラリファイルであり、最終的に Play のテンポラリファイルクリーンアップ機能によって自動的に削除されると誤解する可能性があるからです。しかし、これは真実ではありません。
これらのメソッドは、ファイルを Play の内部一時フォルダー(アップロードされたファイルが最初に保存される場所)から移動するときに使用することを目的としているため、最終的には移動された宛先ファイルをどうするか(そして、いつ、どのように削除するか)は開発者の責任です。戻り値の型を変更することで、それが明確になります。
§Guice の互換性に関する変更
Guice がバージョン 4.2.2 にアップグレードされました(4.2.1 と 4.2.0 リリースノート も参照してください)。これにより、以下の破壊的変更が発生します。
play.test.TestBrowser.waitUntil
は、com.google.common.base.Function
の代わりにjava.util.function.Function
を期待するようになりました。- Scala で、
AbstractModule
のconfigure()
メソッドをオーバーライドする場合、そのメソッドの前にoverride
識別子を付ける必要があります(現在は非抽象メソッドであるため)。
§静的 Logger
シングルトンは非推奨
Java の play.Logger
のほとんどの `static` メソッドと、Scala の `play.api.Logger` シングルトンオブジェクトのほぼすべてのメソッドは非推奨になりました。これらのシングルトンは、`application` ロガーに書き込みました。これは、`logback.xml` で次のように参照されます。
<logger name="application" level="DEBUG" />
ロギング設定の変更が懸念される場合は、`Logger("application")` (Scala) または `Logger.of("application")` (Java) を使用して、独自のシングルトン "application" ロガーを定義するのが最も簡単な移行方法です。このロガーに送信されたすべてのログは、Play シングルトンロガーとまったく同じように機能します。一般的にこのアプローチは推奨しませんが、最終的にはあなた次第です。 Play と Logback は、ロガーに特定の命名スキームを使用することを強制しません.
簡単なコード変更とロギング設定の変更に抵抗がない場合は、代わりに、クラス名と一致する名前で、クラスごとに新しいロガーを作成することをお勧めします。これにより、クラスまたはパッケージごとに異なるログレベルを設定できます。たとえば、すべての `com.example.models` のログレベルを情報レベルに設定するには、`logback.xml` で次のように設定します.
<logger name="com.example.models" level="INFO" />
各クラスでロガーを定義するには、次のように定義できます。
- Java
-
import play.Logger; private static final Logger.ALogger logger = Logger.of(YourClass.class);
- Scala
-
import play.api.Logger private val logger = Logger(classOf[YourClass])
Scala の場合、Play は `val logger: Logger` を自動的に追加するためにクラスまたはトレイトに混在できる `play.api.Logging` トレイトも提供します.
import play.api.Logging
class MyClass extends Logging {
// `logger` is automaticaly defined by the `Logging` trait:
logger.info("hello!")
}
もちろん、SLF4J を直接使用することもできます.
- Java
-
private static final Logger logger = LoggerFactory.getLogger(YourClass.class);
- Scala
-
private val logger = LoggerFactory.getLogger(classOf[YourClass])
Java で SLF4J を直接使用するときに、より簡潔なソリューションが必要な場合は、Project Lombok の `@Slf4j` アノテーション を検討することもできます.
**注**: SLF4J のロギングインターフェースである `org.slf4j.Logger` は、まだ 遅延評価のためのパラメーターとしてラムダ式を受け入れるロギングメソッドを提供していません. `play.Logger` と `play.api.Logger` は、ほとんどの場合 `org.slf4j.Logger` の単純なラッパーですが、そのようなメソッドを提供します.
`application` ロガーの使用を中止したら、それを参照する `logback.xml` の `logger` エントリを削除できます.
<logger name="application" level="DEBUG" />
§アプリケーションローダー API の変更
カスタム `ApplicationLoader` を使用している場合、テストの実行時にこのローダーのインスタンスを手動で作成している可能性があります。そのためには、まず `ApplicationLoader.Context` のインスタンスを作成する必要があります。例:
val env = Environment.simple()
val context = ApplicationLoader.Context(
environment = env,
sourceMapper = None,
webCommands = new DefaultWebCommands(),
initialConfiguration = Configuration.load(env),
lifecycle = new DefaultApplicationLifecycle()
)
val loader = new MyApplicationLoader()
val application = loader.load(context)
ただし、上記のコードで使用されている `ApplicationLoader.Context` apply メソッドは非推奨になり、`webCommands` が null でない場合は例外をスローします. 新しいコードは次のとおりです.
val env = Environment.simple()
val context = ApplicationLoader.Context.create(env)
val loader = new GreetingApplicationLoader()
val application = loader.load(context)
§JPA の削除と非推奨
Play 2.6 ですでに非推奨になっていたクラス `play.db.jpa.JPA` は、ついに削除されました. まだの場合は、Play 2.6 JPA 移行に関する注意事項 を参照してください.
この Play リリースでは、さらに多くの JPA 関連のメソッドとアノテーションが非推奨になりました.
@play.db.jpa.Transactional
play.db.jpa.JPAApi.em()
play.db.jpa.JPAApi.withTransaction(final Runnable block)
play.db.jpa.JPAApi.withTransaction(Supplier<T> block)
play.db.jpa.JPAApi.withTransaction(String name, boolean readOnly, Supplier<T> block)
Play 2.6 JPA 移行に関する注意事項ですでに述べたように、これらの非推奨のメソッドとアノテーションの代わりに、play.db.jpa.JPAApi の使用 で説明されているように、`JPAApi` 注入インスタンスを使用してください.
§Router#withPrefix
は常にプレフィックスを追加する必要があります
以前は、`router.withPrefix(prefix)` はルーターにプレフィックスを追加することを目的としていましたが、「レガシー実装」が既存のプレフィックスを更新することを許可していました. Play の `SimpleRouter` や他のクラスはこの動作に従っていました. 現在、すべての実装がプレフィックスを追加するように更新されたため、`router.withPrefix(prefix)` は常に `s"$prefix/$path"` を `router` が `path` をルーティングするのと同じ方法でルーティングするルーターを返す必要があります.
デフォルトでは、ルーターにはプレフィックスが付いていないため、これは、すでに `withPrefix` によって返されたルーターで `withPrefix` を呼び出している場合にのみ動作の変更を引き起こします. ルーターにすでに設定されているプレフィックスを置き換えるには、プレフィックス付きバージョンではなく、元のプレフィックスなしルーターで `withPrefix` を呼び出す必要があります.
§実行フック
`RunHook.afterStarted()` は、パラメーターとして `InetSocketAddress` を受け取らなくなりました.
§すべての Java フォーム `validate` メソッドは、クラスレベルの制約に移行する必要があります
Java フォームの「古い」`validate` メソッドは、もはや実行されません.
Play 2.6 移行ガイド で発表されたように、そのような `validate` メソッドを クラスレベルの制約 に移行する必要があります.
**重要**: Play 2.7 にアップグレードしても、`validate` メソッドを移行する必要があることを示すコンパイラの警告は表示されません(Play はリフレクションを介してそれらを実行したため).
§Java `Form`、`DynamicForm`、`FormFactory` のコンストラクターが変更されました
`play.data` 内の `Form`、`DynamicForm`、`FormFactory` クラスの `Validator` パラメーターを使用していたコンストラクターは、代わりに `ValidatorFactory` パラメーターを使用するようになりました.
それに加えて、これらのコンストラクターには `com.typesafe.config.Config` パラメーターも必要になりました.
例:`new Form(..., validator)` は `new Form(..., validatorFactory, config)` になります.
この変更は、`formFactory.form(SomeForm.class)` を使用する代わりに、コンストラクターを使用してフォームをインスタンス化する場合にのみ影響します。ほとんどの場合、テスト中です.
§Java Cache API `get` メソッドは、`getOptional` に代わって非推奨になりました
Java `cacheApi` の `getOptional` メソッドは、結果を `Optional` でラップして返します.
`play.cache.SyncCacheApi` の変更
非推奨のメソッド | 新しいメソッド |
---|---|
<T> T get(String key) |
<T> Optional<T> getOptional(String key) |
`play.cache.AsyncCacheApi` の変更
非推奨のメソッド | 新しいメソッド |
---|---|
<T> CompletionStage<T> get(String key) |
<T> CompletionStage<Optional<T>> getOptional(String key) |
§`Server.getHandlerFor` は `Server#getHandlerFor` に移動しました
`Server` トレイトの `getHandlerFor` メソッドは、リクエストのルーティング時に Play サーバーコードによって内部的に使用されていました. 削除され、`Server` オブジェクトの同じ名前のメソッドに置き換えられました.
§Java DI 非依存 Play `Module` API サポートが追加され、すべての組み込み Java `Module` の型が変更されました
Java で DI に依存しない Play の Module
を作成できるようになりました。play.inject.Module
を拡張することで、Java API を使用し、Java でコーディングされているため、より Java フレンドリーになります。さらに、既存の組み込み Java Module
(例:play.inject.BuiltInModule
、play.libs.ws.ahc.AhcWSModule
)は、Scala の play.api.inject.Module
ではなく、Java の play.inject.Module
を拡張するようになりました。
Java の play.inject.Module
は Scala の play.api.inject.Module
のサブクラスであるため、Module
インスタンスは同じ方法で使用できます。ただし、インターフェースが少し異なります。
public class MyModule extends play.inject.Module {
@Override
public java.util.List<play.inject.Binding<?>> bindings(final play.Environment environment, final com.typesafe.config.Config config) {
return java.util.Collections.singletonList(
// Note: it is bindClass() but not bind()
bindClass(MyApi.class).toProvider(MyApiProvider.class)
);
}
}
§play.mvc.Results.TODO は play.mvc.Controller.TODO に移動しました
Play のすべてのエラーページが更新され、CSPFilter が存在する場合、CSP nonce をレンダリングするようになりました。これは、エラーページテンプレートがリクエストをパラメータとして受け取る必要があることを意味します。2.6.x では、TODO
フィールドは HTTP コンテキストを持つアクションではなく静的な結果としてレンダリングされていたため、コントローラ外で呼び出される可能性がありました。2.7.0 では、TODO
フィールドは削除され、代わりに play.mvc.Controller
に TODO(Http.Request request)
メソッドが追加されました。
public abstract class Controller extends Results implements Status, HeaderNames {
public static Result TODO(play.mvc.Http.Request request) {
return status(NOT_IMPLEMENTED, views.html.defaultpages.todo.render(request.asScala()));
}
}
§内部変更
Play の内部 API には多くの変更が加えられました。これらの API は内部的に使用され、通常の非推奨プロセスには従いません。Play の内部 API と直接統合しているユーザーのために、変更点が以下に記載されている場合があります。
§設定の変更
§play.allowGlobalApplication
のデフォルト値は false
になりました
Play 2.7.0 では、play.allowGlobalApplication = false
がデフォルトで設定されています。これは、Play.current
を呼び出すと例外がスローされることを意味します。これを true
に設定すると、Play.current
とその他の非推奨の静的ヘルパーが再び機能しますが、この機能は将来のバージョンで削除されることに注意してください。
今後、アプリケーションコンポーネントの静的インスタンスを使用する必要がある場合は、Guice を使用した 静的インジェクション を使用してそれらをインジェクトするか、アプリケーションローダーの起動時に静的フィールドを手動で設定できます。アプリケーションを同時実行しないように注意すれば(例:テスト中)、これらのアプローチは将来のバージョンの Play と互換性があります。
Play.current
は、一部の非推奨 API によって引き続き呼び出されるため、そのような API を使用する場合、application.conf
ファイルに次の行を追加する必要があります。
play.allowGlobalApplication = true
たとえば、組み込み Play と Scala Sird Router で play.api.mvc.Action
オブジェクトを使用する場合、グローバル状態にアクセスします。
import play.api.mvc._
import play.api.routing.sird._
import play.core.server._
// It can also be NettyServer
val server = AkkaHttpServer.fromRouter() {
// `Action` in this case is the `Action` object which access global state
case GET(p"/") => Action {
Results.Ok(s"Hello World")
}
}
上記の例では、前述のように play.allowGlobalApplication = true
を設定するか、以下のように書き直す必要があります。
import play.api._
import play.api.mvc._
import play.api.routing.sird._
import play.core.server._
// It can also be NettyServer
val server = AkkaHttpServer.fromRouterWithComponents() { components: BuiltInComponents => {
case GET(p"/") => components.defaultActionBuilder {
Results.Ok(s"Hello World")
}
}
}
§HikariCP は即時失敗しなくなりました
Play 2.7 では、HikariCP の initializationFailTimeout
のデフォルト値が -1
に変更されました。つまり、データベースが利用できない場合でもアプリケーションは起動します。initializationFailTimeout
を 1
に設定することで、プールを即時失敗させるようにして、古い動作に戻すことができます。
アプリケーションがデータベースの Evolutions を使用している場合、適用する新しい進化があるかどうかを確認するために、アプリケーションの起動時に接続が要求されます。そのため、接続が必要になるため、データベースが利用できない場合、起動は失敗します。タイムアウトは connectionTimeout
(デフォルトは 30 秒)によって定義されます。
詳細は SettingsJDBC を参照してください。
§CoordinatedShutdown play.akka.run-cs-from-phase
設定
設定 akka.coordinated-shutdown.exit-jvm
はサポートされなくなりました。この設定が有効になっていると、Play は起動せず、エラーがログに記録されます。Play には、ほとんどのシナリオに適した akka.coordinated-shutdown.*
のデフォルト値が付属しているため、それらをオーバーライドする必要はほとんどありません。
設定 play.akka.run-cs-from-phase
はサポートされなくなり、追加してもアプリケーションのシャットダウンには影響しません。存在する場合、警告がログに記録されます。Play は現在、すべてのフェーズを実行して、ApplicationLifecycle
に登録されているすべてのフックと coordinated shutdown に追加されたすべてのタスクが実行されるようにします。特定のフェーズから CoordinatedShutdown
を実行する必要がある場合は、いつでも手動で実行できます。
import akka.actor.ActorSystem
import javax.inject.Inject
import akka.actor.CoordinatedShutdown
import akka.actor.CoordinatedShutdown.Reason
class Shutdown @Inject()(actorSystem: ActorSystem) {
// Define your own reason to run the shutdown
case object CustomShutdownReason extends Reason
def shutdown() = {
// Use a phase that is appropriated for your application
val runFromPhase = Some(CoordinatedShutdown.PhaseBeforeClusterShutdown)
val coordinatedShutdown = CoordinatedShutdown(actorSystem).run(CustomShutdownReason, runFromPhase)
}
}
Java の場合:
import akka.actor.ActorSystem;
import akka.actor.CoordinatedShutdown;
import javax.inject.Inject;
import java.util.Optional;
class Shutdown {
public static final CoordinatedShutdown.Reason customShutdownReason = new CustomShutdownReason();
private final ActorSystem actorSystem;
@Inject
public Shutdown(ActorSystem actorSystem) {
this.actorSystem = actorSystem;
}
public void shutdown() {
// Use a phase that is appropriated for your application
Optional<String> runFromPhase = Optional.of(CoordinatedShutdown.PhaseBeforeClusterShutdown());
CoordinatedShutdown.get(actorSystem).run(customShutdownReason, runFromPhase);
}
public static class CustomShutdownReason implements CoordinatedShutdown.Reason {}
}
§アプリケーションシークレットの最小長のチェック
アプリケーションシークレット 設定 play.http.secret.key
は、本番環境で最小長のチェックを受けます。キーが 15 文字以下の場合、警告がログに記録されます。キーが 8 文字以下の場合、エラーがスローされ、設定は無効になります。このエラーを解決するには、シークレットを head -c 32 /dev/urandom | base64
などの完全にランダムな入力の少なくとも 32 バイトに設定するか、アプリケーションシークレットジェネレータを使用して playGenerateSecret
または playUpdateSecret
を使用します。
アプリケーションシークレット は、Play セッション Cookie が有効であること、つまり攻撃者によって偽装されたのではなくサーバーによって生成されたことを確認するためのキーとして使用されます。ただし、シークレットは文字列のみを指定し、その文字列のエントロピーの量を決定するものではありません。とにかく、シークレットの長さを測定するだけで、シークレットのエントロピー量の上限を設定することができます。シークレットの長さが 8 文字の場合、エントロピーは最大 64 ビットであり、これは現代の標準では不十分です。
§play.filters.headers.contentSecurityPolicy
は CSPFilter のために非推奨になりました
SecurityHeaders フィルタ には contentSecurityPolicy
プロパティがありますが、これは 2.7.0 で非推奨になりました。contentSecurityPolicy
は default-src 'self'
から null
に変更されました。デフォルト設定の null
は、SecurityHeaders フィルタからの HTTP レスポンスに Content-Security-Policy
ヘッダーが追加されないことを意味します。CSP 機能を有効にするには、新しい CSPFilter を使用してください.
play.filters.headers.contentSecurityPolicy
が null
でない場合、警告が表示されます。 技術的には contentSecurityPolicy
と新しい CSPFilter
を同時にアクティブにすることはできますが、お勧めしません。
新しい CSPFilter
は、 play.filters.enabled
プロパティに追加することで有効にできます。
play.filters.enabled += play.filters.csp.CSPFilter
**注意**:コンテンツセキュリティポリシーを綿密にレビューして、ニーズを満たしていることを確認してください. 新しい `CSPFilter` は、`default-src 'self'` よりも特に寛容であり、Google Strict CSP 構成に基づいています。 CSP レポートコントローラ を使用した `report-only` 機能を使用して、ポリシー違反を確認できます。
詳細については、CSPFilter のドキュメントを参照してください。
§CSRF および言語 Cookie の SameSite 属性
Play 2.6 では、SameSite
Cookie 属性は セッションとフラッシュに対してデフォルトで有効 になりました.
Play 2.7 以降では、CSRF Cookie と言語 Cookie についても同じことが当てはまります。 デフォルトでは、CSRF Cookie の SameSite
属性はセッション Cookie と同じ値になり、言語 Cookie はデフォルトで SameSite=Lax
を使用します。
これは設定を使用して微調整できます。 例えば
play.filters.csrf.cookie.sameSite = null // no same-site for csrf cookie
play.i18n.langCookieSameSite = "strict" // strict same-site for language cookie
§デフォルトの変更
Play で使用されるデフォルト値の一部が変更され、アプリケーションに影響を与える可能性があります。 このセクションでは、デフォルトの変更について詳しく説明します。
§JavaScript のデフォルトのコンテンツタイプとしての application/javascript
application/javascript
が、text/javascript
に代わる JavaScript のデフォルトのコンテンツタイプになりました。 生成された <script>
タグでは、type
属性も省略するようになりました。 type
属性の省略の詳細については、HTML 5 仕様 を参照してください。
§自己署名 HTTPS 証明書の変更
ルートフォルダに直接ではなく、target/dev-mode/generated.keystore
の下に生成されるようになりました.
§text/plain
コンテンツタイプのデフォルトの文字セットの変更
テキストおよび許容テキストボディパーサーは、以前のデフォルトの ISO-8859-1
に代わって、デフォルトの文字セットとして US-ASCII
を使用するようになりました。
これは、いくつかの新しい HTTP 標準、特に「テキストメディアタイプのデフォルトの文字セットである ISO-8859-1 は削除されました。デフォルトは、メディアタイプの定義が示すものです」と述べている RFC 7231、付録 B のためです。 text/plain
メディアタイプの定義は、US-ASCII を指定する RFC 6657、セクション 4 によって定義されています。 テキストおよび許容テキストボディパーサーはコンテンツタイプとして text/plain
を使用するため、現在は適切にデフォルト設定されています。
§更新されたライブラリ
このセクションでは、依存関係に加えられた重要な更新を示します。
§Akka の更新
Play 2.7 は、Akka 2.5 シリーズの最新バージョンを使用しています。 Akka ライブラリのバージョンの混在は 許可されていません。 最新バージョンは、複数のバージョンの Akka アーティファクトが使用されていることを検出すると警告を記録します。 次のようなものが表示されます
Detected possible incompatible versions on the classpath. Please note that a given Akka version MUST be the same across all modules of Akka that you are using, e.g. if you use [2.5.19] all other modules that are released together MUST be of the same version. Make sure you're using a compatible set of libraries. Possibly conflicting versions [2.5.4, 2.5.19] in libraries [akka-actor:2.5.19, akka-remote:2.5.4]
この例では、修正は akka-remote
を Play が使用しているのと同じバージョンに更新することです。例:
val AkkaVersion = "2.5.19" // should match the version used by Play
libraryDependencies += "com.typesafe.akka" %% "akka-remote" % AkkaVersion
アプリケーションが Play で使用されているバージョンよりも新しいバージョンを使用している場合は、build.sbt
ファイルで Akka バージョンを更新 できます。
§HikariCP の更新
HikariCP は最新バージョンに更新され、最終的に設定 initializationFailFast
が削除され、initializationFailTimeout
に置き換えられました。 HikariCP changelog および initializationFailTimeout
のドキュメント を参照して、この設定の使用方法を理解してください。
§Guava
バージョンが 27.1-jre に更新されました
Play 2.6.x は Guava ライブラリのバージョン 23.0 を提供していました。 現在、最新のバージョンである 27.1-jre に更新されています. ライブラリには多くの変更が加えられました。完全な changelog は こちら を参照してください。
§specs2 のバージョンを 4.3.5 に更新
以前のバージョンは 3.8.x
でした。多くの変更と改善が含まれているため、Specs2 の最新バージョンの リリースノート をお読みになることをお勧めします。使用されるバージョンでは、使用されている Mockito のバージョンが 2.18.x
に更新されたため、こちらも更新しました。
§Jackson のバージョンを 2.9 に更新
Jackson のバージョンが 2.8 から 2.9 に更新されました。このバージョンのリリースノートは こちら です。互換性を維持したリリースであるため、アプリケーションに影響はないはずです。しかし、新機能に興味があるかもしれません。
§Hibernate Validator のバージョンを 6.0 に更新
Hibernate Validator がバージョン 6.0 に更新され、Bean Validation 2.0 と互換性を持つようになりました。新機能については こちら をご覧ください。または、新しいバージョンに関する 詳細なブログ記事 をお読みください。
注意: このバージョンは、プロジェクトで使用している他の Hibernate 依存関係と完全には互換性がない可能性があることに注意してください。たとえば、hibernate-jpamodelgen を使用している場合は、すべてが連携して動作するように最新バージョンを使用する必要があります。
// Visit https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen to see the list of versions available libraryDependencies += "org.hibernate" % "hibernate-jpamodelgen" % "5.3.7.Final" % "provided"
§ライブラリの削除
デフォルトの Play ディストリビューションのサイズを小さくするために、いくつかのライブラリを削除しました。次のライブラリは Play 2.7 では依存関係ではなくなったため、使用する場合はビルドに手動で追加する必要があります。
§BoneCP の削除
BoneCP は削除されました。アプリケーションが BoneCP を使用するように設定されている場合は、デフォルトの JDBC 接続プールである HikariCP に切り替える必要があります。
play.db.pool = "default" # Use the default connection pool provided by the platform (HikariCP)
play.db.pool = "hikaricp" # Use HikariCP
HikariCP を使用するようにプールを再設定する必要がある場合があります。たとえば、HikariCP の最大接続数を設定する場合は、次のようになります。
play.db.prototype.hikaricp.maximumPoolSize = 15
詳細は、JDBC 設定セクション を参照してください。
また、完全修飾クラス名を指定することで、play.api.db.ConnectionPool
を実装する独自のプールを使用することもできます。
play.db.pool=your.own.ConnectionPool
§Apache Commons (commons-lang3
および commons-codec
)
Play は、プロジェクトで commons-codec
と commons-lang3
を使用していた場合に、内部的に使用していました。使用する場合は、build.sbt
に追加する必要があります。
// Visit https://mvnrepository.com/artifact/commons-codec/commons-codec to see the list of versions available
libraryDependencies += "commons-codec" % "commons-codec" % "1.11"
そして、commons-lang3 の場合は次のようになります。
// Visit https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 to see the list of versions available
libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.8.1"
§その他の重要な変更
§DEV
モードで evolution スクリプトを適用する必要がある場合にアプリケーションが起動する
Play 2.6 までは、DEV
モードでデータベースに evolution スクリプトを実行する必要がある場合、アプリケーションは起動時に中止されていました。そのため、ApplicationEvolutions
に依存するモジュールは初期化さえされませんでした。これは、モジュールで ApplicationEvolutions
に依存している場合、モジュールが初期化されるまでにすべての evolution スクリプトが正常に実行され、たとえば、evolution スクリプトによってテーブルやその他のデータベースオブジェクトが作成されていることに依存して、モジュール内からデータベースにデータを挿入できることを意味していました。クエリに必要なデータベースオブジェクトです。
しかし、Play 2.7 以降では、DEV
モードでは、evolution スクリプトを適用する必要があるかどうかに関係なく、アプリケーション (およびすべてのモジュール) は *常に* 起動するようになりました。これは、evolution スクリプトが正常に実行され、モジュールが初期化される時点で特定のデータベース構造が利用可能であるという事実に *依存できない* ことを意味します。
そのため、ApplicationEvolutions.upToDate
を追加しました。これは、evolution の適用プロセスが完了したかどうかを示します。このメソッドが true
を返した場合にのみ、すべての evolution スクリプトが正常に実行されたことを確認できます。DEV
モードで evolution スクリプトを適用または解決するたびに、アプリケーションは自動的に再起動し、すべてのモジュールを再初期化するため、upToDate
は最終的に true
を返します。
§Evolutions コメント構文
Play Evolutions は、SQL92 コメント構文を正しくサポートするようになりました。つまり、好きな場所で #
の代わりに、行頭に --
を使用して evolution を記述できます。Evolutions API を使用して新しく生成された evolution は、すべての領域で SQL92 スタイルのコメント構文も使用するようになりました。ドキュメントもそれに応じて更新され、SQL92 スタイルが優先されるようになりましたが、古いコメントスタイルも完全にサポートされています。
§クエリ文字列パラメータのバインディング動作の変更
§パラメータ値が空の場合 (例: ?myparam=
)
以下のタイプのクエリ文字列パラメータを定義するルート
UUID
、Char
、Double
、Float
、Long
、Int
、またはBoolean
- または、それらの Java での相当物
そして、以下の型でラップされているもの
- Scala の
Option
(例:myparam: Option[Int]
) または - Java の
Optional
(例:myparam: java.util.Optional[Integer]
) または - Scala の
List
(例:myparam: List[Int]
) または - Java の
List
(例:myparam: java.util.List[Integer]
)
Play 2.6 までは、リクエストのクエリ文字列パラメータが空の場合 (例: ?myparam=
)、このようなケースでは 400 Bad Request
が返されていました。
これは、空の文字列から上記の型を解析できなかったためです (例: Scala では、"".toInt
は例外を発生させます。他の上記のすべての型も、それぞれの解析メソッドで例外を発生させます)。
Play 2.7 以降では、不正なリクエストは発生しなくなりますが、代わりに None
(Scala の Option
の場合)、Optional.empty()
(Java の Optional
の場合)、または空のリストが、このようなクエリパラメータのアクションメソッドに渡されます。
デフォルト値が定義されている場合 (例: myparam: Option[Int] ?= Option(123)
)、もちろんそのデフォルト値が渡されます。
注意: 上記の型が
Option
、Optional
、またはリストでラップされていない場合 (例:myparam: Int ?= 3
)、デフォルト値の動作も変更されました。Play 2.7 より前は、デフォルト値を選択する代わりに400 Bad Request
が発生していました。
§パラメータがまったく存在しない場合
以下の型でラップされたクエリ文字列パラメータにデフォルト値を定義するルート
- Scala の
Option
(例:myparam: Option[...] ?= Option(...)
) または - Java の
Optional
(例:myparam: java.util.Optional[...] ?= java.util.Optional.of(...)
) または - Scala の
List
(例:myparam: List[...] ?= List(...)
) または - Java の
List
(例:myparam: java.util.List[...] ?= java.util.Arrays.asList(...)
)
は、リクエストのクエリ文字列パラメータがまったく存在しない場合、そのデフォルト値をアクションメソッドに渡していませんでした。代わりに、None
、Optional.empty()
、または空のリストが渡されました。
Play 2.7 以降では、このような存在しないクエリパラメータに対して、デフォルト値がアクションメソッドに渡されるようになりました。
§multipart/form-data
ファイルアップロードの変更
Play 2.6 までは、multipart/form-data
エンコーディングを介して空のファイルをアップロードすることは、空でないファイルをアップロードすることと同じように扱われていました。しかし、明らかな理由から、空のファイルをアップロードすることはあまり意味がありません。そのため、Play 2.7 以降では、アップロードされた空のファイルは、ファイルがまったくアップロードされなかったのと同じように扱われます。
したがって、Scala API または Java API を介してアップロードされたファイルを取得する場合、ファイルが空になることはありません。
注意:
multipart/form-data
ファイルアップロードパートのfilename
ヘッダーが空の場合、ファイル自体が空でない場合でも、同じロジックが適用されます。
§Twirl 構文解析の改善
Twirl テンプレートの解析を改善するために、これまで有効だったコードがサポートされなくなりました。詳細については、この問題 を参照してください。
このドキュメントに誤りを見つけましたか? このページのソースコードは こちら にあります。ドキュメントガイドライン を読んだ後、プルリクエストを送信してください。質問やアドバイスがありましたら、コミュニティフォーラム にアクセスして、コミュニティとの会話を始めてください。