From b77269967cc3334f3a99d2ec68f6099ce7298d71 Mon Sep 17 00:00:00 2001 From: Mirco Dotta Date: Tue, 6 Oct 2015 10:59:13 +0200 Subject: [PATCH] ApplicationLifecycle stop hook can take an existential type Using an existential type instead of a specific `Unit` or `Void` allows for better code reuse, and avoids having to map a `Future`/`CompletionStage` just to make the compiler happy. We do the same in many places when using an Akka Streams `Source`. --- .../inject/DelegateApplicationLifecycle.java | 2 +- .../src/main/scala/play/api/test/Fakes.scala | 2 +- .../java/play/inject/ApplicationLifecycle.java | 2 +- .../src/main/scala/play/api/Application.scala | 2 +- .../play/api/inject/ApplicationLifecycle.scala | 16 +++++++--------- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/framework/src/play-java/src/main/java/play/inject/DelegateApplicationLifecycle.java b/framework/src/play-java/src/main/java/play/inject/DelegateApplicationLifecycle.java index 5f6b3a14fbb..30245158657 100644 --- a/framework/src/play-java/src/main/java/play/inject/DelegateApplicationLifecycle.java +++ b/framework/src/play-java/src/main/java/play/inject/DelegateApplicationLifecycle.java @@ -20,7 +20,7 @@ public DelegateApplicationLifecycle(play.api.inject.ApplicationLifecycle delegat } @Override - public void addStopHook(final Callable> hook) { + public void addStopHook(final Callable> hook) { delegate.addStopHook(hook); } } diff --git a/framework/src/play-test/src/main/scala/play/api/test/Fakes.scala b/framework/src/play-test/src/main/scala/play/api/test/Fakes.scala index 363f626780f..0077c01376e 100644 --- a/framework/src/play-test/src/main/scala/play/api/test/Fakes.scala +++ b/framework/src/play-test/src/main/scala/play/api/test/Fakes.scala @@ -225,7 +225,7 @@ case class FakeApplication( override def plugins: Seq[Plugin.Deprecated] = app.plugins override def requestHandler: HttpRequestHandler = app.requestHandler override def errorHandler: HttpErrorHandler = app.errorHandler - override def stop(): Future[Unit] = app.stop() + override def stop(): Future[_] = app.stop() override def injector: Injector = app.injector } diff --git a/framework/src/play/src/main/java/play/inject/ApplicationLifecycle.java b/framework/src/play/src/main/java/play/inject/ApplicationLifecycle.java index 61366f5e064..2e9850edd4f 100644 --- a/framework/src/play/src/main/java/play/inject/ApplicationLifecycle.java +++ b/framework/src/play/src/main/java/play/inject/ApplicationLifecycle.java @@ -25,5 +25,5 @@ public interface ApplicationLifecycle { * The stop hook should redeem the returned future when it is finished shutting down. It is acceptable to stop * immediately and return a successful future. */ - public void addStopHook(Callable> hook); + public void addStopHook(Callable> hook); } diff --git a/framework/src/play/src/main/scala/play/api/Application.scala b/framework/src/play/src/main/scala/play/api/Application.scala index 2c343e025ad..a9a339f4806 100644 --- a/framework/src/play/src/main/scala/play/api/Application.scala +++ b/framework/src/play/src/main/scala/play/api/Application.scala @@ -204,7 +204,7 @@ trait Application { /** * Stop the application. The returned future will be redeemed when all stop hooks have been run. */ - def stop(): Future[Unit] + def stop(): Future[_] /** * Get the injector for this application. diff --git a/framework/src/play/src/main/scala/play/api/inject/ApplicationLifecycle.scala b/framework/src/play/src/main/scala/play/api/inject/ApplicationLifecycle.scala index 148e6754860..443c917b87a 100644 --- a/framework/src/play/src/main/scala/play/api/inject/ApplicationLifecycle.scala +++ b/framework/src/play/src/main/scala/play/api/inject/ApplicationLifecycle.scala @@ -54,7 +54,7 @@ trait ApplicationLifecycle { * The stop hook should redeem the returned future when it is finished shutting down. It is acceptable to stop * immediately and return a successful future. */ - def addStopHook(hook: () => Future[Unit]): Unit + def addStopHook(hook: () => Future[_]): Unit /** * Add a stop hook to be called when the application stops. @@ -62,10 +62,8 @@ trait ApplicationLifecycle { * The stop hook should redeem the returned future when it is finished shutting down. It is acceptable to stop * immediately and return a successful future. */ - def addStopHook(hook: Callable[F.Promise[Void]]): Unit = { - import play.api.libs.iteratee.Execution.Implicits.trampoline - addStopHook(() => hook.call().wrapped().map(_ => ())) - } + def addStopHook(hook: Callable[F.Promise[_]]): Unit = + addStopHook(() => hook.call().wrapped()) } /** @@ -74,9 +72,9 @@ trait ApplicationLifecycle { @Singleton class DefaultApplicationLifecycle extends ApplicationLifecycle { private val mutex = new Object() - @volatile private var hooks = List.empty[() => Future[Unit]] + @volatile private var hooks = List.empty[() => Future[_]] - def addStopHook(hook: () => Future[Unit]) = mutex.synchronized { + def addStopHook(hook: () => Future[_]) = mutex.synchronized { hooks = hook :: hooks } @@ -85,12 +83,12 @@ class DefaultApplicationLifecycle extends ApplicationLifecycle { * * @return A future that will be redeemed once all hooks have executed. */ - def stop(): Future[Unit] = { + def stop(): Future[_] = { // Do we care if one hook executes on another hooks redeeming thread? Hopefully not. import play.api.libs.iteratee.Execution.Implicits.trampoline - hooks.foldLeft(Future.successful(())) { (future, hook) => + hooks.foldLeft(Future.successful[Any](())) { (future, hook) => future.flatMap { _ => hook().recover { case e => Logger.error("Error executing stop hook", e)