How to run code on startup in Play! framework 2.4 - scala

I im trying to print "Hello" to console on application start. Can You explain how to do it?
What i tried myself:
app/modules/HelloModule.scala:
package modules
import com.google.inject.AbstractModule
trait Hello {}
class MyHelloClass extends Hello {
initialize() // running initialization in constructor
def initialize() = {
println("Hello")
}
}
class HelloModule extends AbstractModule {
def configure() = {
bind(classOf[Hello])
.to(classOf[MyHelloClass]).asEagerSingleton
}
}
in conf/application.conf i added:
play.modules.enabled += "modules.HelloModule"
and "Hello" is not printed when i run activator run

You need to use Global object, and override "onStart" method:
Defining a Global object in your project allows you to handle global
settings for your application. This object must be defined in the
default (empty) package and must extend 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...")
}
}
You can also specify a custom GlobalSettings implementation class name
using the application.global configuration key.
Update:
The correct way would be to use Dependency Injection, exactly like it described in the question. GlobalSettings could be removed later
There is no problem with the code in the question. I verified it on my local setup. The code write "Hello" after first request in the development mode "activator run" and after application start in the production mode "activator start".
Btw, try to use some more easy to find string in the log, like
"--------APP DZIABLO HAS BEEN STARTED--------"
It could be so you just missed "Hello" in the log (I did not recognise it from the start)

Related

share table creation and drop between many tests [duplicate]

I have a suite of scalatest tests that test different endpoints of a RESTful API.
I really want them separated into different files for best organization.
My problem is how to start something (an HTTP server in my case, but it doesn't matter what it is) before all the tests and shut it down after all the tests are done.
I know about BeforeAndAfterAll, but that only accomplishes before/after inside one test file. I need something like that, but for all tests, for example:
-- start http server before tests
-- run all test suites
-- shut down http server
The intended way to do this is to use nested suites. Suite has a nestedSuites method that returns an IndexedSeq[Suite] (in 2.0, in 1.9.1 it was a List[Suite]). Suite also has a runNestedSuites method that is responsible for executing any nested suites. By default runNestedSuites calls nestedSuites, and on each returned Suite either invokes run directly, or if a Distributor is passed, puts the nested suites in the distributor so that they can be run in parallel.
So what you really probably want to do is make Foo and Bar into classes, and return instances of them from the nestedSuites method of EndpointTests. There's a class that makes that easy called Suites. Here's an example of its use:
import org.scalatest._
import matchers.MustMatchers
class Foo extends FunSpec with MustMatchers {
describe("Message here...") {
it("Must do something") { }
it("Must be ok") { }
}
}
class Bar extends FunSpec with MustMatchers {
describe("Hello you...") {
it("One more!") { }
}
}
class EndpointTests extends Suites(new Foo, new Bar) with BeforeAndAfterAll {
override def beforeAll(configMap: Map[String, Any]) {
println("Before!") // start up your web server or whatever
}
override def afterAll(configMap: Map[String, Any]) {
println("After!") // shut down the web server
}
}
One potential problem, though, is that if you are using discovery to find Suites to run, all three of EndpointTests, Foo, and Bar will be discovered. In ScalaTest 2.0 you can annotate Foo and Bar with #DoNotDiscover, and ScalaTest's Runner will not discover them. But sbt still will. We are currently enhancing sbt so that it passes over otherwise discoverable Suites that are annotated with DoNotDiscover, but this will be in sbt 0.13, which isn't out yet. In the meantime you can get sbt to ignore them by adding an unused constructor parameter to Foo and Bar.
Ok, found a way. It seems (unless someone here can correct me) that Scalatest does not have the facility of a "master" suite. But... you can kinda build one.
You can compose a suite from traits. So using my endpoint example:
class EndpointTests extends FunSpec with MustMatchers with BeforeAndAfterAll
with Foo with Bar {
override def beforeAll(configMap: Map[String, Any]) {
println("Before!") // start up your web server or whatever
}
override def afterAll(configMap: Map[String, Any]) {
println("After!") // shut down the web server
}
}
Ok, but what about the tests? Notice the with Foo with Bar. I'm bringing the dependent tests in as traits.
See here:
trait Foo extends FunSpec with MustMatchers {
describe("Message here...") {
it("Must do something") { }
it("Must be ok") { }
}
}
trait Bar extends FunSpec with MustMatchers {
describe("Hello you...") {
it("One more!") { }
}
}
Alternatively you can just use an object.
object TestServer {
startServer()
}
When you access the object it will be initialised, starting the server.
Just create a common trait in the body of which you access the object.
Then mixin that trait into all your tests. Done.
If your server runs in daemon mode (e.g. a Play! application in test mode) it will be automatically shut down after all tests are run.

How do I kick off a Runnable RabbitMQ listener when my play framework scala application starts?

So I have a RESTful play app that interacts (or is going to interact very soon) with a couple of other micro-restful-services.
However I need to start my Runnable RabbitMQ class shortly after play startup so that I can trigger some akka actors to do stuff.
So far I've got the application responding to "GET" routes / /status and all is good, but I keep getting linked to "Scheduled Tasks" as a way to do a background job in Play. Is that the right way to do so?
system.scheduler().scheduleOnce() ??
As suggested here: Running a continuous background task in Play 2.4.2 server
Edit: Trying what Lief Ericson suggested but get an error:
//#Singleton Get the error below when I uncomment this <<-----
class Test extends Runnable {
val logger: Logger = LoggerFactory.getLogger(this.getClass.getName)
def run() = {
while(true) {
logger.info("I'm here #################")
Thread.sleep(10000)
}
}
}
class Bindings extends AbstractModule {
val logger: Logger = LoggerFactory.getLogger(this.getClass.getName)
override def configure() = {
logger.info("Configuring application ....")
bind(classOf[Test]).asEagerSingleton()
}
}
Error:
[error] C:\PROJECTS\active\voldemort\app\controllers\Application.scala:29: trait Singleton is abstract; cannot be instantiated
[error] #Singleton
[error] ^
But when i comment out the singleton decorator, I get the log message "Configuring application ..." just fine but not I'm here ######### log line
You need to create a class, say RabbitListener, and start that listener in the class constructor:
#Singleton
class RabbitListener(listener: Listener[T]) {
listener.run()
...
}
Then, you need to make that class eagerly load using Guice Module:
import com.google.inject.AbstractModule
class Bindings extends AbstractModule {
override def configure() = {
bind(classOf[RabbitListener]).asEagerSingleton()
}
}
Then, you need to register the module in application.conf:
play.modules.enabled += org.example.Bindings
Some reference here:
https://www.playframework.com/documentation/2.5.x/GlobalSettings#scala
I got it working, here's the ugly solution (which i know isn't the right way of doing things, so hopefully someone can respond) but it works and does what I need it to (which is listen for Rest Calls but also run an RMQ background listener)
case object StartConsumingMessage
class RabbitMQConsumer {
val logger: Logger = LoggerFactory.getLogger(this.getClass.getName)
logger.info("Voldemort Actor System starting...")
val system = ActorSystem("VoldemortSystem")
val actor = system.actorOf(Props(new RMQConsumerActor()))
implicit val timeout = Timeout(300 seconds)
actor ! StartConsumingMessage
}
class Bindings extends AbstractModule {
val logger: Logger = LoggerFactory.getLogger(this.getClass.getName)
override def configure() = {
logger.info("Configuring application ....")
bind(classOf[RabbitMQConsumer]).asEagerSingleton()
}
}

How to do database initialization when using DI in Play 2.4?

Play 2.4 discourages using GlobalSettings.onStart and whole Global object.
I'm using play-slick and it has great DI sample in GitHub, but it is missing a example how to do database initialization.
How does one implement the database initialization when using DI and when GlobalSettings.onStart is not available?
Common cases for database initialization is: If in DEV mode, add these rows, if PROD do these. Examples wanted.
The trick is to place the initialisation in the constructor of the injected class. Here's an example:
Add app/modules/Database.scala:
package modules
import com.google.inject.AbstractModule
import com.google.inject.name.Names
trait Database {
def create(): Unit
def drop(): Unit
}
class TestDatabase extends Database {
initialize() // running initialization in constructor
def initialize() = {
println("Setup database with test data here")
}
def create() = ()
def drop() = ()
}
class ProdDatabase extends Database {
// similar to above
}
class DatabaseModule extends AbstractModule {
def configure() = {
bind(classOf[Database])
.annotatedWith(Names.named("development"))
.to(classOf[TestDatabase]).asEagerSingleton
bind(classOf[Database])
.annotatedWith(Names.named("production"))
.to(classOf[TestDatabase])
}
}
Add in conf/application.conf:
play.modules.enabled += "DatabaseModule"
That's to start with. The .asEagerSingleton will run the constructor code without needing you to inject it. When you want to choose which one to inject, then you'd need to remove the .asEagerSingleton and load the appropriate database implementation either:
based on configuration in the bindings (see link for example); or
in the service/controller, for example:
#Inject #Named("development") Database database

Doing something before or after all Scalatest tests

I have a suite of scalatest tests that test different endpoints of a RESTful API.
I really want them separated into different files for best organization.
My problem is how to start something (an HTTP server in my case, but it doesn't matter what it is) before all the tests and shut it down after all the tests are done.
I know about BeforeAndAfterAll, but that only accomplishes before/after inside one test file. I need something like that, but for all tests, for example:
-- start http server before tests
-- run all test suites
-- shut down http server
The intended way to do this is to use nested suites. Suite has a nestedSuites method that returns an IndexedSeq[Suite] (in 2.0, in 1.9.1 it was a List[Suite]). Suite also has a runNestedSuites method that is responsible for executing any nested suites. By default runNestedSuites calls nestedSuites, and on each returned Suite either invokes run directly, or if a Distributor is passed, puts the nested suites in the distributor so that they can be run in parallel.
So what you really probably want to do is make Foo and Bar into classes, and return instances of them from the nestedSuites method of EndpointTests. There's a class that makes that easy called Suites. Here's an example of its use:
import org.scalatest._
import matchers.MustMatchers
class Foo extends FunSpec with MustMatchers {
describe("Message here...") {
it("Must do something") { }
it("Must be ok") { }
}
}
class Bar extends FunSpec with MustMatchers {
describe("Hello you...") {
it("One more!") { }
}
}
class EndpointTests extends Suites(new Foo, new Bar) with BeforeAndAfterAll {
override def beforeAll(configMap: Map[String, Any]) {
println("Before!") // start up your web server or whatever
}
override def afterAll(configMap: Map[String, Any]) {
println("After!") // shut down the web server
}
}
One potential problem, though, is that if you are using discovery to find Suites to run, all three of EndpointTests, Foo, and Bar will be discovered. In ScalaTest 2.0 you can annotate Foo and Bar with #DoNotDiscover, and ScalaTest's Runner will not discover them. But sbt still will. We are currently enhancing sbt so that it passes over otherwise discoverable Suites that are annotated with DoNotDiscover, but this will be in sbt 0.13, which isn't out yet. In the meantime you can get sbt to ignore them by adding an unused constructor parameter to Foo and Bar.
Ok, found a way. It seems (unless someone here can correct me) that Scalatest does not have the facility of a "master" suite. But... you can kinda build one.
You can compose a suite from traits. So using my endpoint example:
class EndpointTests extends FunSpec with MustMatchers with BeforeAndAfterAll
with Foo with Bar {
override def beforeAll(configMap: Map[String, Any]) {
println("Before!") // start up your web server or whatever
}
override def afterAll(configMap: Map[String, Any]) {
println("After!") // shut down the web server
}
}
Ok, but what about the tests? Notice the with Foo with Bar. I'm bringing the dependent tests in as traits.
See here:
trait Foo extends FunSpec with MustMatchers {
describe("Message here...") {
it("Must do something") { }
it("Must be ok") { }
}
}
trait Bar extends FunSpec with MustMatchers {
describe("Hello you...") {
it("One more!") { }
}
}
Alternatively you can just use an object.
object TestServer {
startServer()
}
When you access the object it will be initialised, starting the server.
Just create a common trait in the body of which you access the object.
Then mixin that trait into all your tests. Done.
If your server runs in daemon mode (e.g. a Play! application in test mode) it will be automatically shut down after all tests are run.

How to execute on start code in scala Play! framework application?

I need to execute a code allowing the launch of scheduled jobs on start of the application, how can I do this? Thanks.
Use the Global object which - if used - must be defined in the default package:
object Global extends play.api.GlobalSettings {
override def onStart(app: play.api.Application) {
...
}
}
Remember that in development mode, the app only loads on the first request, so you must trigger a request to start the process.
Since Play Framework 2.6x
The correct way to do this is to use a custom module with eager binding:
import scala.concurrent.Future
import javax.inject._
import play.api.inject.ApplicationLifecycle
// This creates an `ApplicationStart` object once at start-up and registers hook for shut-down.
#Singleton
class ApplicationStart #Inject() (lifecycle: ApplicationLifecycle) {
// Start up code here
// Shut-down hook
lifecycle.addStopHook { () =>
Future.successful(())
}
//...
}
import com.google.inject.AbstractModule
class StartModule extends AbstractModule {
override def configure() = {
bind(classOf[ApplicationStart]).asEagerSingleton()
}
}
See https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection#Eager-bindings
I was getting a similar error.
Like #Leo said, create Global object in app/ directory.
Only thing I had to make sure was to change "app: Application" to "app: play.api.Application".
app: Application referred to class Application in controllers package.