§Java移行ガイド
Java 8のエコシステムにより適合させ、Play JavaユーザーがアプリケーションでJavaをより慣用的に使用できるようにするために、PlayはCompletionStage
やFunction
などのいくつかのJava 8型を使用するように切り替えました。Playには、EssentialAction
、EssentialFilter
、Router
、BodyParser
、HttpRequestHandler
用の新しいJava APIもあります。
§新しいJava API
特にHttpRequestHandler
インターフェースにおいて、JavaでフィルターとHTTPリクエストハンドラーを作成できるようにするためのAPI変更がいくつかあります。これらのコンポーネントにScalaを使用している場合は、必要に応じてScala APIを自由に使用できます。
§フィルターAPI
フィルターを作成するときは、ほとんどの場合、EssentialAction
を使用します。Filter
APIまたは、EssentialAction
で動作する下位レベルのEssentialFilter
APIを使用できます。
§HttpRequestHandlerとActionCreator
HttpRequestHandler
はPlay 2.4に実際に存在していましたが、現在は異なる目的を果たしています。createAction
メソッドとwrapAction
メソッドは、ActionCreator
という新しいインターフェースに移動され、HttpRequestHandler
では非推奨になりました。これらのメソッドはJavaアクションにのみ適用され、コントローラーのメソッド呼び出しへのリクエストをインターセプトするために使用されますが、すべてのリクエストではありません。
2.5では、HttpRequestHandler
の主な目的は、リクエストが到着した直後にリクエストのハンドラーを提供することです。これはScalaの実装が行うことと一致するようになり、JavaユーザーがすべてのHTTPリクエストの処理をインターセプトする方法を提供します。通常、HttpRequestHandler
はルーターを呼び出してリクエストのアクションを検索するため、新しいAPIを使用すると、ルーターに送信する前にJavaでリクエストをインターセプトできます。
§アクション内でのCompletionStageの使用
HTTP.Contextがスコープ内にとどまるように、Action内でJava CompletionStage
を使用する場合は、HTTP実行コンテキストを実行者として明示的に指定する必要があります。HTTP実行コンテキストを指定しないと、request()
またはHttp.Context
に依存するその他のメソッドを呼び出すときに、「ここからHTTPコンテキストは使用できません」というエラーが発生します。
依存性注入を介してplay.libs.concurrent.HttpExecutionContext
インスタンスを指定できます
public class Application extends Controller {
@Inject HttpExecutionContext ec;
public CompletionStage<Result> index() {
someCompletableFuture.supplyAsync(() -> {
// do something with request()
}, ec.current());
}
}
§関数型をJava 8の関数型に置き換え
Play 2.5の大きな変更は、可能な限り標準のJava 8クラスを使用するように変更されたことです。すべての関数型はJava 8の対応するものに置き換えられました。たとえば、F.Function1<A,R>
はjava.util.function.Function<A,R>
に置き換えられました。
Java 8型への移行により、他のJavaライブラリやJava 8の組み込み機能との統合が向上するはずです。
§移行方法
ステップ1:Playの関数インターフェースを参照するすべてのコードを、代わりにJava 8インターフェースを参照するように変更します。
F.Function1
のような型を明示的に記述しているコードを変更する必要があります。たとえば、
void myMethod(F.Callback0 block) { ... }
次のようになります
void myMethod(Runnable block) { ... }
下の表に、すべての変更を示します
古いインターフェース | 新しいインターフェース |
---|---|
F.Callback0 |
java.lang.Runnable |
F.Callback<A> |
java.util.function.Consumer<A> |
F.Callback2<A,B> |
java.util.function.BiConsumer<A,B> |
F.Callback3<A,B,C> |
Java 8には対応するものがありません。akka.japi.function.Function3 の使用を検討してください |
F.Predicate<A> |
java.util.function.Predicate<A> |
F.Function0<R> |
java.util.function.Supplier<R> |
F.Function1<A,R> |
java.util.function.Function<A,R> |
F.Function2<A,B,R> |
java.util.function.BiFunction<A,B,R> |
ステップ2:ラムダ内でスローされるチェック例外によって発生するエラーを修正します。
Playの関数インターフェースとは異なり、Java 8の関数インターフェースでは、チェック例外をスローすることはできません。ラムダ式がチェック例外をスローする場合は、コードを変更する必要があります。(チェック例外をスローしない場合は、コードをそのままにしておくことができます。)
コンパイラーエラーが多数発生する可能性がありますが、コードを再び動作させるのは非常に簡単です。Play 2.4コードが、データベースを停止するためにF.Callback0
ラムダを使用していると仮定しましょう
onClose(() -> {
database.stop(); // <-- can throw an IOException
})
Play 2.5では、onClose
メソッドはF.Callback0
の代わりにjava.lang.Runnable
引数を取るように変更されました。Runnable
はチェック例外をスローできないため、上記のコードはPlay 2.5ではコンパイルされません。
コードをコンパイルするには、チェック例外(IOException
)をキャッチし、それをアンチェック例外(RuntimeException
)でラップするようにラムダコードを変更できます。Runnable
がアンチェック例外をスローしても問題ないため、コードはコンパイルされるようになります。
onClose(() -> {
try {
database.stop(); // <-- can throw an IOException
} catch (IOException e) {
throw new RuntimeException(e);
}
})
コードにtry-catchブロックを追加したくない場合は、DurianライブラリのErrors
クラスを使用して、例外を処理できます。
たとえば、チェック例外をアンチェック例外に変換するという、上記と同じ動作を、次のコードで実現できます
onClose(Errors.rethrow().wrap(database::stop));
Durianは、例外のログ記録や、独自の例外ハンドラーの作成など、他の動作も提供します。Durianを使用する場合は、プロジェクトの依存関係として含めるか、2つのクラスからソースをプロジェクトにコピーすることで含めることができます。
§F.Promise
をJava 8のCompletionStage
に置き換え
F.Promise
を使用するAPIは、標準のJava 8 CompletionStage
クラスを使用するようになりました。
§移行方法
ステップ1:F.Promise
を返すコードをすべて、代わりにCompletionStage
を返すように変更します。移行を容易にするため、F.Promise
はCompletionStage
インターフェースも実装します。つまり、Promise
を返す既存のコードは、CompletionStage
を使用するように移行されたコードから引き続き呼び出すことができます。
ステップ2:F.Promise
の関連する静的メソッドを、同等のメソッドに置き換えます(これらの多くは、play.libs.concurrent.Futures
ヘルパー、またはCompletableFuture
の静的メソッドを使用します)
F.Promise メソッド |
代替 |
---|---|
Promise.wrap |
scala.compat.java8.FutureConverters.toJava |
Promise.sequence |
Futures.sequence |
Promise.timeout |
Futures.timeout |
Promise.pure |
CompletableFuture.completedFuture |
Promise.throwing |
CompletableFuture を構築し、completeExceptionally を使用します |
Promise.promise |
CompletableFuture.supplyAsync |
Promise.delayed |
Futures.delayed |
ステップ3:既存のインスタンスメソッドを、CompletionStage
の同等のメソッドに置き換えます
F.Promise |
CompletionStage |
---|---|
または |
applyToEither |
onRedeem |
thenAcceptAsync |
map |
thenApplyAsync |
transform |
handleAsync |
zip |
thenCombine (および手動でタプルを構築) |
fallbackTo |
handleAsync の後にthenCompose(Function.identity()) |
recover |
exceptionally (またはHttp.Context をキャプチャする場合は、HttpExecution#defaultContext() を指定したhandleAsync ) |
recoverWith |
recover と同じで、その後.thenCompose(Function.identity()) を使用 |
onFailure |
whenCompleteAsync (必要な場合はHttpExecution#defaultContext() を使用) |
flatMap |
thenComposeAsync (必要な場合はHttpExecution#defaultContext() を使用) |
filter |
thenApplyAsync を使用してフィルターを手動で実装(必要な場合はHttpExecution#defaultContext() を使用) |
これらの移行については、F.Promise
のJavadocで詳しく説明されています。
§F.Option
をJava 8のOptional
に置き換え
Play Java APIは、PlayのF.Option
型の代わりに、Java 8のOptional
クラスを使用するように変換されました。F.Option
型は削除されました。
§移行方法
F.Option
を使用しているコードを Optional
に置き換えてください。2つの型は似ていますが、APIが異なるため、コードを更新する必要があります。2つの型の主な違いは、F.Option
が java.util.Collection
を継承するのに対し、Optional
は継承しないことです。
移行を容易にするための簡単な表を以下に示します。
F.Option |
Optional |
---|---|
F.Option.None() |
Optional.empty() |
F.Option.Some(v) |
Optional.ofNullable(v) |
o.isDefined() |
o.isPresent() |
o.isEmpty() |
!o.isPresent() |
o.get() |
o.get() |
o.getOrElse(f) |
o.orElseGet(f) または o.orElse(v) |
o.map(f) |
o.map(f) |
Optional
はさらに多くのコンビネータを備えているため、まだ慣れていない場合は、そのAPIを学習することを強く推奨します。
§スレッドローカル属性
Http.Context
、Http.Session
などのスレッドローカル属性は、CompletionStage
および*Async
コールバックで使用した場合、異なる実行コンテキストに渡されなくなりました。
詳細については、こちらを参照してください。
§非推奨のstatic API
Play 2.5では、いくつかのstatic APIが非推奨となり、代わりに依存性注入コンポーネントを使用することが推奨されています。staticなグローバル状態を使用することはテスト容易性とモジュール性を損なうため、これらのAPIへのアクセスには依存性注入に移行することを推奨します。静的APIに対応する依存性注入コンポーネントについては、Play 2.4移行ガイドのリストを参照してください。
次へ: 暗号化移行ガイド
このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、お気軽にプルリクエストを送信してください。質問や共有したいアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。