Skip to content

Instantly share code, notes, and snippets.

@alexandru
Last active December 27, 2015 13:49
Show Gist options
  • Select an option

  • Save alexandru/7336282 to your computer and use it in GitHub Desktop.

Select an option

Save alexandru/7336282 to your computer and use it in GitHub Desktop.
Play / Subcut dependency injection in modules
// Helper for keeping track of the active project bindings
// (because we don't want to hard-code those inside singleton objects)
object Environment {
def currentBindings =
ref.get match {
case null =>
throw new NullPointerException("No BindingModule currently registered (app not running?)")
case value =>
value
}
def registerCurrentBindings(update: => BindingModule) {
if (ref.get != null || !ref.compareAndSet(null, update))
throw new IllegalStateException("Cannot register new BindingModule (the current one must be deregistered)")
}
def unregisterBindings(current: BindingModule) {
if (!ref.compareAndSet(current, null) && !ref.compareAndSet(null, null))
throw new IllegalStateException("Cannot unregister given BindingModule (not current)")
}
private[this] val ref = Atomic(null : BindingModule)
}
trait HelloWorldController extends Controller {
// abstract
def usersDAL: UsersDAL
def list = Action { req =>
val response = usersDAL.list(0, 100).map { list => OK(html.showUsers(list)) }
Async(response)
}
// ...
}
object HelloWorldController extends HelloWorldController with Injectable {
def bindingModule = Environment.current
def usersDAL = inject [UsersDAL]
}
class LifeCyclePlugin(app: play.Application) extends Plugin with Injectable {
val bindingModule = new StandardBindings(app.getWrappedApplication)
override def onStart() {
Environment.registerCurrentBindings(bindingModule)
}
override def onStop() {
Environment.unregisterBindings(bindingModule)
}
}
import com.escalatesoft.subcut.inject._
import play.api.libs.concurrent.Akka
import play.api.{Play, Application}
import akka.actor.ActorSystem
import play.api.libs.concurrent.Execution.Implicits.defaultContext
class StandardBindings(app: => Application) extends NewBindingModule(module => {
import module._
lazy val config = Configuration.load()
lazy val system = Akka.system(app)
bind [Configuration] toSingle config
bind [DBConnection] toSingle DBConnection(config.db, system)(app)
bind [ActorSystem] toSingle system
bind [Application] toSingle Play.current
bind [GeoIP] toSingle GeoIP()
// ...
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment