Chai Nadig Chai Nadig - 1 month ago 6
Java Question

Inject dependency based on parameter in Play Framework

I keep track of a list of service providers in the database for a

consumerId
.

I have a
SchedulerActor
that creates
TaskActor
for each service provider enabled for the
consumerId
.

I want to inject an implementation of
ServiceProvider
to
TaskActor
s for each service provider in the list. There can be different implementations of
ServiceProvider
.

interface ServiceProvider {
void processRequest(Request request);
}

class SchedulerActor {
@Override
public void onReceive(Object consumerId) throws Exception {
List<String> serviceProvidersList = getFromDatabase((String) consumerId);
for (String serviceProviderStr : serviceProvidersList) {

//serviceProviderStr could be "ServiceProvider1" or "ServiceProvider2"
ServiceProvider serviceProvider = getServiceProviderFromStr(serviceProviderStr);

ActorRef r = getContext().actorOf(Props.create(TaskActor.class, serviceProvider));
getContext().watch(r);
routees.add(new ActorRefRoutee(r));

}
router = new Router(new BroadcastRoutingLogic(), routees);
router.route(message, getSelf());
}
}

class TaskActor {
private final ServiceProvider serviceProvider;
public TaskActor(ServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}

@Override
public void onReceive(Object message) {
if (message instanceof Request) {
serviceProvider.processRequest((Request)message);
}
}
}



  1. What goes inside
    getServiceProviderFromStr(String)
    to achieve this?

  2. I don't want to add
    switch
    or
    if else
    statements to return the required implementation.

  3. Can I supply Provider Bindings at runtime, passing the string to the provider object?


Answer

another way to use same named binding instead of proposed @Assisted

@Inject 
public Injector injector;
...
ServiceProvider s = injector.getInstance(Key.get(Parent.class, Names.named(serviceName)));

where classes bound in configure():

bind(ServiceProvider.class).annotatedWith(Names.named("Name1")).to(Child1.class);
bind(ServiceProvider.class).annotatedWith(Names.named("Name2")).to(Child2.class);
Comments