What's the best way to handle initialization errors in Play! Framework 2.0? - scala

Imagine I have an application written using Play 2. Imagine that application needs to grab hold of some things on startup (read a config file, grab some resources from JNDI, that kind of thing). Play handily gives us the GlobalSettings object that we can use to hook into start and stop events:
import play.api._
object Global extends GlobalSettings {
var someResource: Resource = _
override def onStart(app: Application) {
// might throw an exception if the path doesn't exist
resource = JNDI.grabThing("/some/path").asInstanceOf[Resource]
}
}
The problem is - what can we do if the initialisation fails? It seems that this is only executed when Play receives the first request for the application. If we throw an exception, that causes that request to fail, but the application keeps on running.
Ideally, what I'd like is to stop the application from starting at all if this block doesn't complete successfully. Unfortunately, calling Play.stop() doesn't actually seem to, well, stop Play. I can see that the Server trait defines def stop(), which looks promising but I can't figure out a way to get hold of the Server instance from inside my application.
Perhaps I'm looking at this the wrong way, and I'm not supposed to be able to stop Play (or even just my app) from inside my application, so suggestions for other approaches are welcome.
What's the best way to handle these errors?

It seems I'm lying. Play only continues to serve requests after an exception in onStart if you're running in dev mode (play run). If started with play start (i.e. production mode) an exception here will terminate the server, which is exactly what I wanted.
It does appear to leave the RUNNING_PID file lying around, which is irritating, but that's a separate issue...

Related

Is it OK to block a thread on application startup?

In my Play app, I do this in Module.configure():
bind(classOf[GadgetsReader]).toInstance(GadgetsCsvReader)
bind(classOf[Gadgets]).asEagerSingleton()
Then, I do this:
#Singleton
class Gadgets #Inject()(reader: GadgetsReader) {
val all:Seq[Gadget] = reader.readGadgets()
}
That synchronously loads a large collection of gadgets from a CSVfile into memory on startup, in a Play's rendering thread.
I did not see a similar scenario implemented anywhere in Play examples. I would like to know whether what I am doing is idiomatic Scala & Play.
Is it OK to load a very large file synchronously like this, given that I don't want any requests served until the data is fully loaded?
Is it a good thing that I created aGadgets class and then injected it, as opposed to a static/object method Gadget.all?
Should Gadget and Gadgets classes live under model?
Any other comments would be appreciated, too.
I guess it depends how large, how fast you want your startup to be, etc. In general, I'd say yes, even Akka's cluster sharding has (or at least, last I read, had) a blocking call that waits for initialisation to complete before returning. In your case it's probably fine, but one gotcha with blocking calls like this is blocking generally means doing IO, and IO can fail (eg, what if you're reading from a network filesystem, and the network fails when you're starting up?). So sometimes, it's better to design your app so that it's capable of responding (perhaps with a not available status) without the operation having being done yet, and do that operation asynchronously, with retries etc in case it fails. But perhaps this is overkill in your case.
To answer your other questions - yes, it is definitely better to dependency inject Gadgets than use a static singleton, this means you can control how Gadgets is created (perhaps you might want to initialise it differently in tests).
It's probably fine to be in the model package, but this is greatly dependent on your domain and what it looks like.

Where was global scope in playframework and what are the benefits of it going away?

I am reading that the playframework is removing global state that is in older 2.4.x versions.
Can someone explain where the global state currently is and what are the benefits of removing global state?
What is the global state?
There is an object play.api.Play with the following field:
#volatile private[play] var _currentApp: Application = _
Where is it used?
Whenever you do Play.current you refer to that single mutable global field. This is used all across the framework to access things such as:
play.api.Play.configuration takes an implicit app
play.api.libs.concurrent.Execution.defaultContext calls the internal context, which uses the currently running app to get the actor system
play.api.libs.concurrent.Akka.system takes an implicit app
play.api.libs.ws.WS.url takes an implicit app
and many more places..
Why is that bad?
A number of functions just take an implicit app, so that's not really global state, right? I mean, you could just pass in that app. However where do you get it from? Typically, people would import play.api.Play.current.
Another example: Let's say you want to develop a component that calls a webservice. What are the dependencies of such a class? The WSClient. Now if you want to get an instance of that, you need to call play.api.libs.ws.WS.client and pass in an application. So your pretty little component that logically only relies on a webservice client, now relies on the entire application.
Another big factor and a direct consequence of the previous point is testing. Let's say you want to test your webservice component. In theory, you'd only need to mock (or provide some dummy implementation of) the webservice client. However now that somewhere in your code you're calling play.api.Play.current, you need to make sure that that field is set at the time it is called. And the easiest way to ensure that is to start the play application. So you're starting an entire application just to test your little component.

Running actor manually?

I'm working on my first Play Framework 2 application. I want to call a web service every once in a while and store data in the database so I've started writing an actor that is scheduled to every hour.
Problem is, I'm wasting a lot of time simply waiting for the job to be triggered (even if I've scheduled to be ran every minute while I'm testing. I'd love to be able to start the import manually, simply to make sure it works.
I've tried using the scala console, but it doesn't automatically reload my code every time I save so I have to restart the console manually. I've considered wrapping the import process in a class and use unit testing and mocking but I'm looking for a quicker way, especially because I'm new to Play and Scala.
Any idea or suggestion?
Thanks!
How about writing a custom sbt task?
A simple way to write an sbt task that loads your application class path, so you can implement the behavior with a method call in your application code, can be found at sbt-tasks.
I'm assuming you are using the Akka scheduler inside the Actor to trigger a message to itself which then invokes web service. You can just send same message (ActorRef ! Message) to the actor while you are doing your testing.

Play Framework: Block the bootstrap thread onStart

When you override onStart in Global, would it block the thread running the bootstrap process?
In other words I want to make sure that Play does not start until call returns from onStart.
If this is not the case, what are good solution to do critical init process which need to happen before Play start accepting requests?
Yes, Global.onStart will block before the first request.
The GlobalSettings object in Play is a plugin. When the application is started, the routes are loaded first, then the plugins are loaded serially by calling the onStart method of each. The GlobalSettings plugin comes last in this initialization, which ensures that all other plugins are loaded first so that all of your db connections, cache, etc are available there.
The plugin initialization has to block a single thread to guarantee that:
All plugins are initialized in the exact order that is desired to prevent initialization order errors (if one plugin depends on another initializing first--for example the database plugin must always initialize before the evolutions plugin).
All plugins are initialized before the application can start processing requests. (Otherwise, you wouldn't be able to guarantee the the DB plugin was ready on the first request, for example).

Play Framework as Service inside a scala application

i have a little problem. I have to create a scala application. This application have to do some stuff. Create threads and other stuff. That isnt important for this question.
But to interact with this application it is neccessary to create a webinterface. I would like to create this interface by play.
The problem is, i have to integrate the play application inside my normal application. As component. And in the same moment as the application is runnig, he has to start also the play component. And if this worker is fail sometime, to restart it.
Is that possible? And if yes which way you would suggest.
You can invoke your normal application when play framework is starting. (http://www.playframework.com/documentation/2.2.x/ScalaGlobal) More specifically, onStart method in global object may be right place where you call your normal codes.
import play.api._
object Global extends GlobalSettings {
val yourInstance = new YourInstance()
override def onStart(app: Application) {
yourInstance.start()
}
}
Additionally, you can change your thread model to actor model. (http://www.playframework.com/documentation/2.2.x/ScalaAkka)