Actually yes. DbClientUtil initializes twice: first by DbHelper and then by Runner. If this is a problem, there are a lot of ways to solve this:
1) make DbClientUtil
stateless and rewrite it as def dbClient
. It is actually a good solution, because your state should be stored in a database without any depends on how many clients you have instantiated
2) create singleton. Just one. Not two:
object DbClientUtil extends DbClientUtil
object DbHelper extends DbClientUtil{
def sendDbPayload(dbModel:DbModel):Unit = {
DbClientUtil.sendData(dbModel)
}
}
object Runner {
List(DbModel("model1"),DbModel("model2"),DbModel("model3")).foreach{
model => DbHelper.sendDbPayload(model)
}
DbHelper.shutdown //Use just one client, not two
}
But actually I don't like this. Strict dependencies gives you more coupling
3) Use dependency injection. I guess this is the one of best solution for large projects. For example, you can use Google Guice:
trait DbClientService {
def sendData(data: Any): Unit //No implementation
}
class DbClientServiceImpl extends DbClientService
def sendData(data: Any): Unit {
//write you implementation code
}
}
Bind it: https://github.com/codingwell/scala-guice/
class ServiceModule extends AbstractModule {
protected def configure() {
bind[DbClientService].to[DbClientServiceImpl].in[Singleton]
}
}
And then inject it:
class DbHelper @Inject()(dbClient:DbClientService) extends DbClientUtil{
def sendDbPayload(dbModel:DbModel):Unit = {
dbClient.sendData(dbModel)
}
}
class Runner @Inject()(dbClient:DbClientService) extends DbClientUtil{
List(DbModel("model1"),DbModel("model2"),DbModel("model3")).foreach{
model => dbClient.sendDbPayload(model)
}
dbClient.shutdown
//still, don't know if it is good solution
//to control client state from outer scope
//better make this logic private
}