macwire icon indicating copy to clipboard operation
macwire copied to clipboard

Accessing wired instances within modules defined as classes

Open blacktooth opened this issue 7 years ago • 5 comments

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.
}

blacktooth avatar Sep 18 '18 05:09 blacktooth

Well, if you have an instance of UserModule, simply userModule.userFinder?

adamw avatar Sep 18 '18 13:09 adamw

Well, if you have an instance of UserModule, simply userModule.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()))))

blacktooth avatar Sep 18 '18 13:09 blacktooth

Yes, well, that might need a second level of wiring :) But you need to create those instances at some point ...

adamw avatar Sep 18 '18 13:09 adamw

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?

blacktooth avatar Sep 19 '18 07:09 blacktooth

I think you can do the same using a module which uses wire to wire other modules, with compile-time safety.

adamw avatar Sep 19 '18 14:09 adamw