Cameron Hotchkies

Categories

  • coding

Tags

  • globalsettings
  • play
  • scala

My Scala development has gone from occasionally reading on the bus to actually using it as my primary development language 9-5. Which is awesome. After having done Martin Odersky’s course and having read the stairway book, I’d also recommend Scala for the Impatient to anyone as a second Scala book. The reason I’d recommend it second is that it’s very good at filling gaps that inevitably come up after the fact. (I still strongly recommend the stairway book as well).

Part of the work I’ve been doing lately is with Akka, the actor framework. I probably will be mis-stating things as I normally do, but actors are effectively threaded operations that you communicate with via message passing, instead of direct calls. There’s more to them than that but I don’t have much value to add to the description at this point. The rest of the work I’ve been doing is in the Play framework. I mention this because I ran into a curious situation that stumped me for a while.

When working with Play, it becomes very likely that you will want to have some initialization code start when the application starts. This is easy enough to google for.

 
import play.api.GlobalSettings 

// This file is named Global.scala in the root namespace 
object Global extends GlobalSettings { 
  override def onStart(app: Application) {
    Logger.info("[+] Initializing database sessions...") 
    Logger.info("[+] Initializing Other Stuff like the actors here...") 
  } 
} 

One thing I noticed however is that when I was running my application outside of Specs2 (the unit testing framework), was that none of the actors I’d initialized to run on a regular basis were actually running.

After some poking and prodding, NONE of the log statements or anything else was running at all. I could hit all of the endpoints on the web application, just the actors were not firing. Or they were firing silently.

It turned out that a library I had included ALSO had a Global object that extended GlobalSettings and since they were both in the default namespace, the random other one I wasn’t expecting to load was the one to load.

There are several ways to fix this once you have identified the error, but searching for “akka actors don’t start play framework globalsettings” doesn’t really turn up much on the subject directly. One of the solutions for this (assuming the library that is colliding is not editable by you) is to just use a different name.

 
import play.api.GlobalSettings 
// This file is named Global.scala in the root namespace 
object SsfwGlobal extends GlobalSettings { 
  override def onStart(app: Application) { 
    Logger.info("[+] Initializing database sessions...") 
    Logger.info("[+] Initializing Other Stuff like the actors here...") 
  } 
}

then, in your application.conf

 
# Global object class 
# ~~~~~ 

# Define the Global object class for this application. 
# Default to Global in the root package. 
application.global=SsfwGlobal 

From this point onwards, you don’t have to worry about anything else hijacking your GlobalSettings.

Fun fact, the application.conf is compiled directly into the jar, so if you’re using the play clean compile stage command, you’ll want to ensure you have your app loading the configuration from a local file. To do this, you can edit the pre-made “start” script as follows:

exec java -Dconfig.file=$LOCALDIR/custom.conf ... <other stuff here> 

The custom conf file is pretty much required if you have any form of QA environment differences, which is probably everyone. ever.