Created
May 28, 2012 14:21
-
-
Save kevinwright/2819427 to your computer and use it in GitHub Desktop.
Init spray 1.0 with a customisable ActorSystem name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.zeebox.starwatch | |
import javax.servlet.{ServletContextEvent, ServletContextListener} | |
import java.net.InetAddress | |
import akka.actor.ActorSystem | |
import cc.spray.SprayServletSettings | |
import akka.config.ConfigurationException | |
import akka.util.{Reflect, Switch} | |
class Initializer extends ServletContextListener { | |
private val booted = new Switch(false) | |
private[this] var actorSystem: Option[ActorSystem] = None | |
private[this] def findConfigClassLoader(): ClassLoader = { | |
def findCaller(get: Int ⇒ Class[_]): ClassLoader = | |
Iterator.from(2 /*is the magic number, promise*/ ).map(get) dropWhile { c ⇒ | |
c != null && | |
(c.getName.startsWith("akka.actor.ActorSystem") || | |
c.getName.startsWith("scala.Option") || | |
c.getName.startsWith("scala.collection.Iterator") || | |
c.getName.startsWith("akka.util.Reflect")) | |
} next () match { | |
case null ⇒ getClass.getClassLoader | |
case c ⇒ c.getClassLoader | |
} | |
Option(Thread.currentThread.getContextClassLoader) orElse | |
(Reflect.getCallerClass map findCaller) getOrElse | |
getClass.getClassLoader | |
} | |
def loadConfig(loader: ClassLoader) = { | |
//start by seeding some system props | |
System.setProperty("env.hostname", InetAddress.getLocalHost.getHostName) | |
com.typesafe.config.ConfigFactory.load(loader) | |
} | |
def contextInitialized(e: ServletContextEvent) { | |
booted switchOn { | |
println("Starting spray application ...") | |
val ctx = e.getServletContext | |
val loader = getClass.getClassLoader | |
Thread.currentThread.setContextClassLoader(loader) | |
val configLoader = findConfigClassLoader() | |
val config = loadConfig(configLoader) | |
val systemName = config.getString("zeebox.actor-system-name") | |
val system = ActorSystem(systemName, config, configLoader) | |
actorSystem = Some(system) | |
ctx.setAttribute(Initializer.SystemAttrName, system) | |
SprayServletSettings.BootClasses match { | |
case Nil => | |
val e = new ConfigurationException("No boot classes configured. Please specify at least one boot class " + | |
"in the spray.servlet.boot-classes config setting.") | |
ctx.log(e.getMessage, e) | |
case classes => { | |
for (className <- classes) { | |
try { | |
loader | |
.loadClass(className) | |
.getConstructor(classOf[ActorSystem]) | |
.newInstance(system) | |
} catch { | |
case e: ClassNotFoundException => | |
ctx.log("Configured boot class " + className + " cannot be found", e) | |
case e: NoSuchMethodException => | |
ctx.log("Configured boot class " + className + " does not define required constructor " + | |
"with one parameter of type `akka.actor.ActorSystem`", e) | |
case e: Exception => | |
ctx.log("Could not create instance of boot class " + className, e) | |
} | |
} | |
} | |
} | |
} | |
} | |
def contextDestroyed(e: ServletContextEvent) { | |
booted switchOff { | |
println("Shutting down spray application ...") | |
actorSystem foreach {_.shutdown()} | |
actorSystem = None | |
} | |
} | |
} | |
object Initializer { | |
private[starwatch] val SystemAttrName = "spray.servlet.system" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment