by Oleg Ilyenko / @easyangel
inject [SomeClass]
inject [Database] (identified by 'remote and by default new Riak)
class UserModule extends Module {
bind [MessageService] to new OfficialMessageService
binding identifiedBy "greeting.official" to "Welcome"
}
Usage
class OfficialMessageService(implicit inj: Injector)
extends MessageService with Injectable {
val officialGreeting =
inject [String] (identified by "greeting.official")
def getGreetMessage(name: String) =
s"$officialGreeting, $name!"
}
def tokenModule = new Module {
bind [Tokens] to new TokenRepo(db = inject [Database])
}
def dbModule = new Module {
bind [Database] to new Riak
}
def appModule = tokenModule :: dbModule
and then test it
def mocksModule = new Module {
bind [Database] to new InMemoryDb
}
implicit val testModule = mocksModule :: appModule
Constructor injection
class TokenRepo(db: Database, metrics: Metrics) extends Tokens
bind [Tokens] to injected [TokenRepo]
Conditions
class UserModule extends Module {
bind [MessageService] when (inDevMode or inTestMode) to
new SimpleMessageService
bind [MessageService] when inProdMode to
new OfficialMessageService
}
object Pets extends Controller {
def show(id : Long) = Action {
Ok(views.html.pet(Pet.findById(id)))
}
}
object Pet {
def findById(id : Long) : Pet =
DB.withConnection({ implicit c =>
SQL(basicQuery + "id = {id}").on("id" -> id)().map(rowToPet)
}).head
}
package play.api
trait GlobalSettings {
def getControllerInstance[A](controllerClass: Class[A]): A = ...
// ...
}
package scaldi.play
trait ScaldiSupport extends GlobalSettings with Injectable {
def applicationModule: Injector
private var currentInjector: Option[Injector] = None
abstract override def onStart(app: Application) =
currentInjector = Some(createApplicationInjector(app))
abstract override def onStop(app: Application) =
currentInjector foreach (_.destroy())
override def getControllerInstance[A](controllerClass: Class[A]): A =
currentInjector map (_.getBinding(...)) getOrElse (...)
}
class Application(implicit inj: Injector)
extends Controller with Injectable {
val messageService = inject [MessageService]
}
class MyModule extends Module {
binding to new Application
bind [MessageService] to new OfficialMessageService
}
object Global extends GlobalSettings with ScaldiSupport {
def applicationModule = new MyModule :: new SomeOtherModule
}
GET / @controllers.Application.index
import javax.inject.{Inject, Provider, Singleton}
@Singleton
class RoutesProvider @Inject() (
injector: Injector,
environment: Environment,
configuration: Configuration,
httpConfig: HttpConfiguration) extends Provider[Router] {
// ...
}
@Singleton
class Crypto @Inject() (config: CryptoConfig) {
// ...
}
implicit val inj = new Module {
binding to annotated [RoutesProvider]
binding identifiedBy qualifier[SomeQualifier] to annotated [MyService]
binding identifiedBy annotation(SomeQualifierImpl.of("dep1")) to
annotated [MyService]
}
+ OnDemandAnnotationInjector
package play.api.inject
class BuiltinModule extends play.api.inject.Module {
def bindings(env: Environment, configuration: Configuration) =
Seq(
bind[ApplicationLifecycle].to(bind[DefaultApplicationLifecycle])
bind[Router].toProvider[RoutesProvider],
bind[ActorSystem].toProvider[ActorSystemProvider],
bind[ExecutionContext].toProvider[ExecutionContextProvider],
// ...
)
}
class EhCacheModule extends play.api.inject.Module {
def bindings(environment: Environment, configuration: Configuration) = {
// ...
Seq(
bind[CacheManager].toProvider[CacheManagerProvider],
bind[CacheApi].to(bind[CacheApi]
.qualifiedWith(named(defaultCacheName))),
bind[JavaCacheApi].to[DefaultJavaCacheApi]
)
}
}
play {
modules {
enabled += "play.api.cache.EhCacheModule"
}
cache {
# ...
}
}
ScaldiSupport trait is also deprecated...
... use application.conf instead
play.application.loader = scaldi.play.ScaldiApplicationLoader
play.modules.enabled += "modules.MyModule"
play.modules.enabled += "modules.SomeOtherModule"
play.modules.enabled += "scaldi.play.ControllerInjector"
package scaldi.play
class ScaldiApplicationLoader extends ApplicationLoader {
def load(context: Context) =
new ScaldiApplicationBuilder()
.in(context.environment)
.loadConfig(context.initialConfiguration)
.prependModule(new Module {
bind [OptionalSourceMapper] to
new OptionalSourceMapper(context.sourceMapper)
bind [WebCommands] to context.webCommands
})
.build
}
val application = new ScaldiApplicationBuilder()
.prependModule(new TestModule).build()
running(application) {
val home = route(FakeRequest(GET, "/")).get
// ...
}
or simply
withScaldiApp(modules = Seq(new TestModule)) {
val home = route(FakeRequest(GET, "/")).get
// ...
}
val module = new TestModule :: new MyModule :: new ControllerInjector
withScaldiApp(modules = Seq(module, new EhCacheModule, new BuiltinModule),
loadModules = (_, _) => Seq.empty) {
val home = route(FakeRequest(GET, "/")).get
// ...
}
libraryDependencies +=
"org.scaldi" %% "scaldi-play" % "0.5-play-2.4.0-RC3-10"
Example Project