SpringSource/spring-scala — pull request #17 by hekonsek (2013-05-09 12:41:46+00:00)
Title: Basic support for Cake pattern based configuration.

Hi,

Some people complain that using type-scafe Scala with type-unsafe Spring dependency injection makes no sense. I personally disgaree with such statements, although I think that we could add some optional type-safe checking to the project to laverage the pros of Scala. I therefore created the Cake support for Spring Scala.

Cake support for Spring Scala allows to create type-safe cake view over the entire-, or part of the-, functional application context.

I would like to elaborate a little bit on some concrete example. Imagine the part of the typical Spring application .i.e. `Service` and `Dao`.

trait Dao
class ProductionDao extends Dao
case class Service(dao: Dao)

We want to wire these two guys into Spring application context. On the same time we want to take the advantage of the cake pattern in order to:
a) get global access to the application components
b) verify at the compile time that we have provided all necessary dependencies

For this purpose we create typical cake components, but instead of specifying dependencies as `T` we specify them as `() => T`.

trait DataAccessComponent extends CakeSupport {
val dao : () => Dao
}

trait ServiceComponent extends CakeSupport { this: DataAccessComponent =>
val service = singleton(new Service(dao()))
}

Then we wire the dependencies into the global application context.

object MyApp extends Cake extends ServiceComponent with DataAccessComponent {
val dao = singleton(new ProductionDao)
// val dao = singleton(mock[Dao]) // for tests
}

We can use the `CakeObject` as regular Scala cake:

val dao = MyApp.dao()
val service = MyApp.service()
dao == service.dao

Under the hood, our cake hides regular Spring (functional) application context:

val context = MyApp.context
context[Service] == MyApp.service()

The magic here is the `singleton` method from the `CakeSupport` trait which registers the function defined as Cake dependency in the application context.

The nice thing in cake for Spring Scala is that you don't have to cover all your Spring dependencies with "caked" components.

object CakeObject extends Cake with FunctionalConfigurationSupport
with ServiceComponent with DataAccessComponent {

// Beans from this configuration will be available only for the
// Spring application context and will not be a subject of the
// compile time type-safe checks.
def configurationClass = classOf[ComponentScanConfiguration]

val dao = singleton(new ProductionDao)

}

class ComponentScanConfiguration extends FunctionalConfiguration with ContextSupport {
componentScan("org.more.dynamic.components")
}

Using this approach you can combine the best of both worlds - type-safe cake dependencies and dynamic Spring configuration.

What do you think?

PS Scaladoc available on demand, as usually :) .