What is the point of dependency injection if you still need to pass an argument?

I have problems understanding the basic idea of ​​dependency injection. (I am using Play 2.5 with the play-slick module). I have a Users class that needs to connect to a database.

 package models @Singleton class Users @Inject() (dbConfigProvider: DatabaseConfigProvider) { private val db = dbConfigProvider.get[JdbcProfile].db private val users = TableQuery[UserTable] private val setupAction = DBIO.seq(users.schema.create) private val setupFuture: Future[Unit] = db.run(setupAction) def getAll(): Future[Seq[User]] = setupFuture.flatMap(_ => db.run(users.result) ) // More methods like the previous } 

When I have a view that should access these methods, I expect the dependency injection system to fill in a dbConfigProvider dependency for me like this.

 package views class UserSearch { def index(implicit ec: ExecutionContext): Future[String] = Future( (new Users).getAll().map(seq => seq.map(user => user.name).mkString(" ")) ) } 

However, this gives me a compilation error, and I am forced to make the dbConfigProvider dependency of my view and pass it explicitly. In this case, I finally get dbConfigProvider from the controller calling the view.

 package views class UserSearch @Inject (dbConfigProvider: DatabaseConfigProvider) { def index(implicit ec: ExecutionContext): Future[String] = Future( (new Users(dbConfigProvider)).getAll().map(seq => seq.map(user => user.name).mkString(" ")) ) } 

I guess I misunderstood how dependency injection should work.

So my questions are these:

  • What is the use of the @Inject() keyword in my Users model, then?

  • Is my project a failure? I would like the Users and UserSearch objects to be objects, but then I cannot use dependency injection on them.

  • In case anyone is familiar with Slick, is my getAll() method used to work with slick? Is this even the right way to write asynchronous code?

0
scala dependency-injection playframework slick
source share
2 answers

Thanks to the comments of @MichaelZajac, I changed UserSearch to an ad as such:

 class UserSearch @Inject (users: Users) 

And now I have my controller installed as follows:

 class UsersController @Inject()(userSearch: UserSearch) extends Controller { def index = Action.async { implicit request => userSearch.index().map(Ok(_)) } } 

This directly answers my first question, and, seeing it in action, also answers my second question. I am getting SQL errors, but at least my project is compiling. Later, I clarified my third question: it turns out that there is no reason to create a table schema, because in my case it happens using playback files, so I deleted the setupFuture.flatMap part, although it works fine with it and does nothing stupid, like creating a table twice, or something else that you might need when creating / starting a table.

0
source share

one of the advantages of DI is the ease of use of other implementations, especially useful in tests where you can pass the layout of the arguments.

For example, if you get an instance of a class ( MyExternalClass ) that will call external APIs, you can instead send a subclass ( MyExternalSubClass extends MyExternalClass ) that will override the method that calls the API and simply return the preconfigured json

There are also several advantages (and disadvantages) listed here (many other interesting articles on the Internet):

0
source share

All Articles