macwire
macwire copied to clipboard
Accessing wired instances within modules defined as classes
I am new to Scala and Macwire and trying to figure out how to access instances that are wired using modules organized as classes. If modules are defined as traits, one can extend them and access the wired instances in them as below,
trait UserModule {
lazy val userFinder: UserFinder = wire[UserFinder]
}
class UserFinderSpec extends FlatSpec with UserModule {
assert userFinder.find(...) should ...
}
If my modules are organized as classes with composition, how do I access the instances?
class UserFinder(databaseConnection: databaseConnection) {
}
@Module
class DatabaseConnectionModule {
lazy val databaseConnection: DatabaseConnection = ...
}
@Module
class UserModule(databaseConnectionModule: DatabaseConnectionModule) {
lazy val userFinder:UserFinder = wire[UserFinder]
}
class UserFinderSpec extends FlatSpec {
//How to access UserFinder here?
//val wired = wiredInModule(new UserModule(new DatabaseConnectionModule))
//val userFinder = wired.lookup(classOf[UserFinder]
//Above way to access the instances seems complicated
//as I need to instantiate the modules with it's dependency chain which can be very long in my use-case.
}
Well, if you have an instance of UserModule, simply userModule.userFinder?
Well, if you have an instance of
UserModule, simplyuserModule.userFinder?
Getting an instance of UserModule might involve instantiating multiple other modules which can become very long. Something like,
new UserModule(new DataBaseConnectionModule(new HttpConnectionModule(new URLModule(), new ThrottlingLimitsModule(), new TimeoutsModule()))))
Yes, well, that might need a second level of wiring :) But you need to create those instances at some point ...
Have you considered how Guice solves this problem using the install method? One can define a module that combines everything,
class DatabaseConnectionModule {
install(new URLModule())
install(new TimeoutsModule())
install(new ThrottlingModule())
val databaseConnection = ...
}
class UserModule {
install(new DataBaseConnectionModule())
val userFinder: UserFinder = ...
}
class AppModule {
install(new UserModule())
install(new BillingModule())
}
val wired = wiredInModule(new AppModule())
val userFinder: UserFinder = wired.lookup(classOf[UserFinder])
What is your opinion on this?
I think you can do the same using a module which uses wire to wire other modules, with compile-time safety.