Reputation: 1461
I am from Java background and new to functional paradigm as such, so please forgive and correct me I smell like OOP.
I have a trait names PaymentHandler
trait PaymentHandler {
def handleInit(paymentInfo: PaymentInfo, paymentConfig: PaymentConfig): Either[Future[WSResponse], Exception]
def handleComplete(paymentinfo: PaymentInfo, paymentConfig: PaymentConfig, clientToken: String): Future[Map[String, String]]
}
and
@Singleton
class PayPal extends PaymentHandler{....}
@Singleton
class BrainTree extends PaymentHandler{....}
Till here everything is Ok. but the problem comes when I want to have multiple PaymentGateways based on Payment method. Initially I wrote a PaymentHandlerFactory like
class PaymentHandlerFactory @Inject()(
paypal:PayPal,
braintree:BrainTree) {
def get(name:String): PaymentHandler = {
name match {
case "paypal" => paypal
case "bt" => braintree
case _ => null
}
}
}
and then use this PaymentHandlerFactory to get the PayPal object injected by guice. But somehow I felt this is not right way to do and I got onto companion objects. so this is the code I wrote then
object PaymentHandler {
@Inject
val paypal:PayPal = null
def apply(name:String): PaymentHandler = {
name match {
case "paypal" => paypal
case _ => null
}
}
}
Ofcourse this fails as it cannot Inject PayPal object. Now I have two questions in my mind.
Upvotes: 1
Views: 3786
Reputation: 2113
If you land up on this question about DI on companion objects, please check the below workaround
The benefit of DI is that it will be propagated to this companion object.
If you have a companion object on class Paypal
and class BrainTree
as below:
@Singleton
class PayPal extends PaymentHandler{....}
object PayPal extends PayPal
@Singleton
class BrainTree extends PaymentHandler{....}
object BrainTree extends BrainTree
Now, I can use these objects in the PaymentHandler companion object as below:
// get the correct handler from factory
class PaymentHandler extends PaymentHandlerFactory(PayPal, BrainTree){...}
object PaymentHandler extends PaymentHandler
Now in any class, we can use PaymentHandler.get()
Upvotes: 0
Reputation: 8443
The reason you cannot inject in companion object is because they are objects rather than classes. This means only a single instance exists and that is created by scala itself. If you want to do dependency injection, then the thing that requires the dependency must be created by the dependency injection framework. Therefore, you need to model your fatory using a class if you want to use guice.
I think what you did with your class PaymentHandlerFactory
is the pragmatic way and probably works in most cases. I would refrain from prematurely making this too generic.
If you want to make it a bit more guice-y, you could use their AssistedInject.
Upvotes: 2