Jam is an incredibly simple DI Scala library.
Essential differences from macwire:
- injects a whole object tree, not only constructor arguments
- can be easily migrated on Scala 3, since doesn't use context scans
- incredibly simple: 1 exposed method, ~50 lines of code
Add jam dependency:
"com.github.yakivy" %% "jam-core" % "0.0.1"
Usage example:
class DatabaseAccess()
class SecurityFilter(databaseAccess: DatabaseAccess)
class UserFinder(databaseAccess: DatabaseAccess, securityFilter: SecurityFilter)
class UserStatusReader(userFinder: UserFinder)
trait UserModule {
val singletonDatabaseAccess = jam.brew[DatabaseAccess]
val userStatusReader = jam.brew[UserStatusReader]
}
will generate:
trait UserModule {
val singletonDatabaseAccess = new DatabaseAccess()
val userStatusReader = new UserStatusReader(
new UserFinder(
singletonDatabaseAccess,
new SecurityFilter(singletonDatabaseAccess)
)
)
}
- injection candidates is being searched in
this
instance, so to provide an instance for future injection you need to make it a member ofthis
. Examples:
trait A {
val a = new A
...brewing //val a will be used
}
val container = new {
val a = new A
...brewing //val a will be used
}
trait A {
def b(): String = {
val a = new A
...brewing //new A instance will be created
}
}
trait A {
val a1 = new A
{
val a2 = new A
...brewing //val a1 will be used
}
}
- library injects only non implicit constructor arguments, implicits will be resolved by scalac
- jam is intended to be minimal, features like scopes, object lifecycles or factory methods should be implemented manually, for example:
//to release resources use cats.effect.Resource
dbClientResource.use { dbClient =>
val container = new {
//to create an object with custom constructor define val or def member
val config = Config.fromFile("config.conf")
//to create singleton define val member
val userStorage = new UserStorage(dbClient)
//to create custom factory method define def member
def userService = new UserService(
userStorage,
config.withFallback(new Config())
)
...brewing //provided members will be used here
}
...logic that utilizes container
} // client will be closed