jack miao
jack miao

Reputation: 1488

How to provide scala object's with classes that have dependancy injection?

I have a different car object's, one for example:

object Porsche extends Car with CarsUtilities {
   override def start() {...}
   override def canStart(fuelInLitr: Int) = fuelInLitr > 5

   override val fuelInLitr = 45
   override val carId = 1234567
}

this is how Car and CarsUtilities looks like:

trait Car {
  def start(): Unit
  val canStart(fuel: Double): Boolean
  val fuelInLitr: Int
  val carId: Int
}

trait CarsUtilities {
  // method to prepare start() result
  def prepareResult() = {...}
}

I have two api services:

class CarApiService (wsClient: WSClient, configuration: Configuration) {

  def getCarkey(carId: String): Future[Option[CarKey]] = {
    // here im performing api call using wsclient
  }

}

and

class CarSupplierApiService @Inject()(configuration: Configuration) {

  def getSupplierInfo(carId: String): Future[Option[SupplierInfo]] = // here im performing elastic search api call

}

Now, In some of the car object's, lets say 50% of them im gonna use those api services, sometime both and other times just one of them. What would be a best practice of providing those car objects those services instances?

I dont really want to use new to create an instance of them for each object that need to use them...so I thought maybe add them lazily to the CarsUtilities so all the car objects will have access to those api services when they need them...would that be a good solution?

also, if I do that how do I give then the Configuration and WSClient injections?

trait CarsUtilities {
  lazy val carApiService = new CarApiService(???)
  lazy val carSupplierApiService = new CarSupplierApiService(???)
  // method to prepare start() result
  def prepareResult() = {...}
}

thanks!!

using playframework 2.6, scala 2.11.8 :)

Upvotes: 0

Views: 759

Answers (1)

rethab
rethab

Reputation: 8413

Generally, dependency injection and objects doesn't work together. Please see here for work-arounds, but in the long term you wan to get rid of objects that depend on injected classes.

What you probably need is some sort of business service that is a class an may be injected in controllers, like so:

class CarsUtilities @Inject() (carApiService: CarApiService, carSupplierApiService: CarSupplierApiService) {

  // this class implements all the business logic and can use the services
  def prepareResult() = {}

}

In the controllers, you may inject this CarsUtilities as well, because dependency injection "propagates".

Upvotes: 1

Related Questions