How to add 'init' and 'destroy' like methods in scala play webapp? - scala

I am very new to Play, I am writing a webapp using scala, in which I wish to implement the following functionality (Play version - 2.3.9):
When the application runs for the first time, five separate variables are to be read from a file (or a DB - this is yet to be decided).
These variables can be globally interfered with and updated while the app runs.
When the app shuts down, the file (or DB) is to be saved with the latest values for these variables.
I need to define sort of java servlet-like init and destroy functionalities to achieve this task. Could somebody guide me on how to achieve this?

Based on play 2.3.9 documentation you should define your hooks via the GlobalSettings:
import play.api._
object Global extends GlobalSettings {
override def onStart(app: Application) {
Logger.info("Application has started")
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
}
But I recommend to move to a newer version >= 2.4, there the GlobalSetting was deprecated, and so the way to add start and end hooks was changed.
In order to define a "start hook" you can add your own Guice module to the application configuration, there you can write what ever you need to heppen when the application starts.
And in order to add a "stop hook" you should use ApplicationLifecycle, see here more.
import scala.concurrent.Future
import javax.inject._
import play.api.inject.ApplicationLifecycle
#Singleton
class MessageQueueConnection #Inject() (lifecycle: ApplicationLifecycle) {
val connection = connectToMessageQueue()
lifecycle.addStopHook { () =>
Future.successful(connection.stop())
}
//...
}

Related

Migrating Play Framework 2.5 - moving from Global.onStart to Dependency Injection

So I am trying to migrate a PlayFramework application from version 2.4.3 to 2.5.6. I am using Squeryl and akka-quartz-scheduler, and Squeryl requires setting up a session manually and akka-quartz-scheduler runs as its own entity, as none of the other modules really depend on it, though it will depend on others. So previously there has been a Global-object to handle them on start up:
import org.squeryl.{Session, SessionFactory}
object Global extends GlobalSettings {
private lazy val injector = Guice.createInjector(CustomModule)
override def onStart(app: Application) {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
injector.getInstance(classOf[CustomScheduler]).initialize()
}
}
This has worked before. However, on 2.5.6 I'm trying to shift away from Global.scala altogether. I'm not sure if this is the best way to do this, but from documentation it seems like it. So I'm trying to create Singleton classes, and load them eagerly before the application loads like instructed here as a replacement for onStart. So like instructed on eager bindings -page I have:
import com.google.inject._
class CustomModule extends AbstractModule {
override def configure() = { // or without override
println("configure called")
bind(classOf[SquerylInitialization]).to(classOf[SquerylInitialization]).asEagerSingleton()
bind(classOf[CustomScheduler]).to(classOf[CustomScheduler]).asEagerSingleton()
}
}
import play.api.{Configuration, Application}
import play.api.db.{DB, DBApi}
import org.squeryl.{SessionFactory, Session}
#Singleton
class SquerylInitialization #Inject()(conf: Configuration, dbApi: DBApi) extends Logging {
SessionFactory.concreteFactory = // Squeryl initialization http://squeryl.org/sessions-and-tx.html
}
import akka.actor.{ActorSystem, ActorRef}
#Singleton
class CustomScheduler #Inject()(system: ActorSystem) extends Logging {
val scheduler: QuartzSchedulerExtension = QuartzSchedulerExtension(system)
// other initialize code here
}
The CustomModule inheriting the AbstractModule and its configure()-method is never called. It is said in Guice documentation that "Alternatively, play will scan the classpath for classes that implement AbstractModule". Documentation might not be the most recent, but that seems to be the way it works.
If for instance on all classes using Squeryl I use dependency injection to load SquerylInitialization it works, but I'm not sure if that's good way to do it as it would have to be required by tons of Classes, and there is hardly any Class depending on the CustomScheduler.
So basically the questions are:
Why isn't the CustomModule calling the configure()-method and eager
loading the Classes, and how that should be fixed?
Is this the standard way to load this kind of functionality, or should some other way used?
So basically comments are correct and the documentation was just out of date, so including
play.modules.enabled += "module.CustomModule"
helped. Thought I tried that as well, but turns out I didn't. Answer just a comment so can't accept that.

How do I create thread pools in Play 2.5.x?

I am currently on Play 2.4.2 and have successfully created thread pools using the following below:
package threads
import scala.concurrent.ExecutionContext
import play.api.libs.concurrent.Akka
import play.api.Play.current
object Contexts {
implicit val db: ExecutionContext = Akka.system.dispatchers.lookup("contexts.db-context")
implicit val pdf: ExecutionContext = Akka.system.dispatchers.lookup("contexts.pdf-context")
implicit val email: ExecutionContext = Akka.system.dispatchers.lookup("contexts.email-context")
}
and then in the code with...
Future{....}(threads.Contexts.db)
We are ready to upgrade to Play 2.5 and having trouble understanding the documentation. The documentation for 2.4.2 uses Akka.system.dispatchers.lookup, which we use without issue. The documentation for 2.5.x uses app.actorSystem.dispatchers.lookup. As far as I know, I have to inject the app into a Class, not an Object. Yet the documentation clearly uses an Object for the example!
Has anyone successfully created thread pools in Play 2.5.x that can help out? Is it as simple as changing Contexts to a class, then injecting it wherever I would like to use this threading? Seems odd since to use the default ExecutionContext I just have to make an implicit import.
Also, we are using Play scala.
If you simply change your Contexts to a class, then you will have to deal with how to get an instance of that class.
In my opinion, if you have a number of thread pools that you want to make use of, named bindings are the way to go. In the below example, I will show you how you could accomplish this with guice.
Note that guice injects depedencies at runtime, but it is also possible to inject dependencies at compile time.
I'm going to show it with the db context as an example. First, this is how you will be using it:
class MyService #Inject() (#Named("db") dbCtx: ExecutionContext) {
// make db access here
}
And here's how you could define the binding:
bind[ExecutionContext].qualifiedWith("db").toProvider[DbExecutionContextProvider]
And somewhere define the provider:
class DbExecutionContextProvider #Inject() (actorSystem: ActorSystem) extends Provider[ExecutionContext] {
override def get(): ExecutionContext = actorSystem.dispatchers.lookup("contexts.db-context")
}
You will have to do this for each of your contexts. I understand this may be a little cumbersome and there may actually be more elegant ways to define the bindings in guice.
Note that I have not tried this out. One issue you might stumble upon could be that you'll end up with conflicts, because play already defines a binding for the ExecutionContext in their BuiltinModule. You may need to override the binding to work around that.

Play 2.4: Schedule a recurring task at app startup with dependency injection

I need to schedule a recurring task on the application start, the task itself is very simple just send to the application a fire-and-forget HTTP call. I'm not a play expert, buy i would assume that s straightforward solution would be something like using play.api.libs.concurrent.Akka.system.schedule in Global.onStart. Since Play 2.4, Global configuration is somewhat deprecated in favor of new Guice DI. Hacking the advice from the DI documentation i couldn't come up with a nice solution for this issue. The best i managed to get is writing a wrapper on top of GuiceApplicationLoader calling a custom implementation of BuiltInComponentsFromContext, but in this case i can't use injection to get WSClient. What's the best way to rewrite something like this with Play 2.4:
object Global extends GlobalSettings {
override def onStart(app: Application) = {
Akka.system.schedule(2.hours, 2.hours, theTask)
}
}
Update: this is now better documented for Play 2.6: https://www.playframework.com/documentation/2.6.x/ScheduledTasks
You can solve this by creating a module like this (attention to code comments):
package tasks
import javax.inject.{Singleton, Inject}
import akka.actor.ActorSystem
import com.google.inject.AbstractModule
import play.api.inject.ApplicationLifecycle
// Using the default ExecutionContext, but you can configure
// your own as described here:
// https://www.playframework.com/documentation/2.4.x/ThreadPools
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import scala.concurrent.Future
import scala.concurrent.duration._
class MyRecurrentTaskModule extends AbstractModule {
override def configure() = {
// binding the RecurrentTask as a eager singleton will force
// its initialization even if RecurrentTask is not injected in
// any other object. In other words, it will starts with when
// your application starts.
bind(classOf[RecurrentTask]).asEagerSingleton()
}
}
#Singleton
class RecurrentTask #Inject() (actorSystem: ActorSystem, lifecycle: ApplicationLifecycle) {
// Just scheduling your task using the injected ActorSystem
actorSystem.scheduler.schedule(1.second, 1.second) {
println("I'm running...")
}
// This is necessary to avoid thread leaks, specially if you are
// using a custom ExecutionContext
lifecycle.addStopHook{ () =>
Future.successful(actorSystem.shutdown())
}
}
After that, you must enable this module adding the following line in your conf/application.conf file:
play.modules.enabled += "tasks.MyRecurrentTaskModule"
Then, just start you application, fire a request to it and see the scheduled task will run every each second.
References:
Understanding Play thread pools
Play Runtime Dependency Injection for Scala
Integrating with Akka
Related questions:
How to correctly schedule task in Play Framework 2.4.2 scala?
Was asynchronous jobs removed from the Play framework? What is a better alternative?

How to gain access to the akka system created via guice?

So I'm following the template here:
https://github.com/rocketraman/activator-akka-scala-guice#master
I've ported this code over to a version 2.4 Play app.
Now I am able to create the actor system and create the actors inside the Global class and send the initial messages to the actors. I've also set up routes to try to talk to certain actors and get status but I am unable to since I cannot access that original actor system.
How can I accomplish this? I think in the older Play versions, we have getControllerInstance; which is used in the following:
/**
* Controllers must be resolved through the application context. There is a special method of GlobalSettings
* that we can override to resolve a given controller. This resolution is required by the Play router.
*/
override def getControllerInstance[A](controllerClass: Class[A]): A = injector.getInstance(controllerClass)
From that, we can inject certain dependencies in the controller. Now that this is removed, we can no longer do that. Is there a way around this?
It's pretty clear how to inject Akka system in to the controller
import play.api.mvc._
import akka.actor._
import javax.inject._
import actors.HelloActor
#Singleton
class Application #Inject() (system: ActorSystem) extends Controller {
val helloActor = system.actorOf(HelloActor.props, "hello-actor")
//...
}
take in to attention #Singleton here is only to store reference to the actor - not the ActorSystem, it's handled by the Play in backend
A Play application defines a special actor system to be used by the
application. This actor system follows the application life-cycle and
restarts automatically when the application restarts.

Where does one place a scala file in the Play Framework 2.0 so that it is compiled as part of the default package?

I am new to Play and Scala, and I am reading Play for Scala from Manning press. I would like to use the instructions to use Squeryl instead of Anorm.
The book mentions that I need to initialize Squeryl in a class that extends GlobalSettings.
import org.squeryl.adapters.H2Adapter
import org.squeryl.{Session, SessionFactory}
import play.api.db.DB import play.api.{Application, GlobalSettings}
object Global extends GlobalSettings {
SessionFactory.concreteFactory = Some(() =>
Session.create(DB.getConnection()(app), new H2Adapter) )
...
As this is an early edition (MEAP) it is not clear about where to place this code...
So I after a little digging on the play site I found the following example that extends GlobalSettings
import play.api._
object Global extends GlobalSettings {
override def onStart(app: Application) {
Logger.info("Application has started")
}
override def onStop(app: Application) {
Logger.info("Application shutdown...")
}
}
The play example gives a little more help but I am still unable to follow the directions, which state : This object must be defined in the default (empty) package.
Which leads to my question: Where does one place a scala file in the Play Framework 2.0 so that it is complied as part of the default package?
Thanks for any help...
GlobalSettings object typically resides in app/Global.scala. Look at zentasks sample.
This does not answer your specific asked question
But, if your question is about "how to use squeryl with Play2 ?", there are some resources you can have a look at :
How to make Squeryl work with the Play! Framework?
https://groups.google.com/d/topic/squeryl/d7hBDNUjE2Y/discussion
And an example : https://github.com/jamesward/play2bars/tree/scala-squeryl