I am trying to learn play framework. I want to implement the lifecycle callbacks of play framework in my application. Now i saw that it can be easily done using GlobalSettings below:
object Global extends GlobalSettings {
override def onStart(app: Application) {
Logger.info("Application has started")
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
}
But it's been deprecated in the play framework(2.5.x). And they are providing eager binding for onStart
callbacks and for onStop
and onError
there are other mechanisms. I looked into the documentation of release 2.5.x and saw a code there like below:
import com.google.inject.AbstractModule
import com.google.inject.name.Names
class Module extends AbstractModule {
def configure() = {
bind(classOf[Hello])
.annotatedWith(Names.named("en"))
.to(classOf[EnglishHello]).asEagerSingleton
bind(classOf[Hello])
.annotatedWith(Names.named("de"))
.to(classOf[GermanHello]).asEagerSingleton
}
}
But unfortunately i couldn't understand it. As using GlobalSettings, it was easy enough to implement the lifecycle callbacks. Suppose that i will just implement a Logger info in the lifecycle callbacks. No complex codes.
How can i implement this for start, stop and error callbacks in 2.5.x ??
In general having moved these mechanisms away from the GlobalSettings
thing also means that you no longer register such 'callbacks' globally, but you tie them to a component/class. This gives the benefit that initialization and shutdown of a certain component may happen directly inside the respective class. However if you have code that you want to run at startup (or shutdown) that is not tied to a specific component (eg. logging, startup checks, etc) you will have to create new classes for them and bind them in you module.
Note that in the latter case you typically bind the respective classes as eager singletons (to make sure they are instantiated) whereas in the former case, the classes are instantiated as part of the dependency tree.
Startup: Run code in constructor of any class that is managed by the dependency injection container.
Bind class in module
bind(classOf[Hello]).to(classOf[EnglishHello]).asEagerSingleton
Put code in constructor
class EnglishHello extends Hello {
println("hello")
}
Note that the asEagerSingleton
is not required per se. As I'm assuming you're using Guice as DI-provider, you may read more about that here: https://github.com/google/guice/wiki/Scopes
Shutdown: In any class that needs to run some shutdown code, register a lifecycle callback.
Bind class in module
bind(classOf[Hello]).to(classOf[EnglishHello]).asEagerSingleton
Register lifecycle callback (and inject ApplicationLifecycle
)
class EnglishHello @Inject() (lifecycle: ApplicationLifecycle) extends Hello {
lifecycle.addStopHook { () =>
Future.successful(connection.stop())
}
}
Note that you may want to scope these classes as singletons, as otherwise you end up registering stop hooks for each instance - depending on what your stop hook does, this may be what you want. Read more about this here: https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection#Stopping/cleaning-up
Errors: Implement your own HttpErrorHandler
. The basic idea is that you implement a class with a number of methods that will be called by Play! on the respective errors. This is documented here: https://www.playframework.com/documentation/2.5.x/ScalaErrorHandling
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With