iCodeLikeImDrunk
iCodeLikeImDrunk

Reputation: 17866

How do I correctly bind multiple implementations of the same service?

I have service class: Service and its impls: RedisServiceImpl, DBServiceImpl.

In my application, almost every class must use the these two impls to update fields. I want to use Guice to inject these services.

class ServiceModule extends AbstractModule with ScalaModule {

    override def configure(): Unit = {
        bind[Service].annotatedWith(Names.named("Redis")).toInstance(new RedisServiceImpl("localhost"))
        bind[Service].annotatedWith(Names.named("DB")).toInstance(new DBServiceImpl("some external host"))
    }
}

The problem with this is, if ever we move away redis/db, I'd have to scour through all the classes and replace "Redis"/"DB" with the new names. Is there an easier way to do this?

I tried to create constants inside of ServiceModule, but I got the following error when I tried to inject the service into a class:

Error:(18, 34) annotation argument needs to be a constant; found: modules.ServiceModule.x
          , @Named(ServiceModule.x) redisService: Service
                             ^

Here are the classes I'm injecting into:

class Poller @Inject()(
        @Named("PollService") pollService: PollService[List[ChannelSftp#LsEntry]]
      , @Named("Redis") redisStatusService: StatusService
      , @Named("DB") dynamoDbStatusService: StatusService
) {
  ... methods ...
}

If I tried:

class Poller @Inject()(
        @Named(ServiceModule.x) pollService: PollService[List[ChannelSftp#LsEntry]]
      , @Named("Redis") redisStatusService: StatusService
      , @Named("DB") dynamoDbStatusService: StatusService
) {
  ... methods ...
}

I get the error I mentioned above.

Upvotes: 3

Views: 790

Answers (2)

Jacek Cz
Jacek Cz

Reputation: 1906

If I can suggest: rethink what pattern do You realize: Chain Of Responsibility, maybe Visitor or Decorator. They differ how many implementations are fired (ChoR stop at first successful etc, order unrestricted or concrete). I saw different Guice ways to realize different patters.

PS. I'm not religious phanatic of design patters, no holy wars because of method name 'next()' or other etc. I have maybe simmilar problem: 2/3 source of data: JAR resource, filesystem, database configured by Guice by the local decision

Upvotes: 1

durron597
durron597

Reputation: 32343

This is the problem, in Poller not your Guice module:

     @Named(ServiceModule.x) pollService: PollService[List[ChannelSftp#LsEntry]]

The annotation argument must be a constant, as it says in the error message:

Error:(18, 34) annotation argument needs to be a constant; found: modules.ServiceModule.x
      , @Named(ServiceModule.x) redisService: Service

It seems as though you are having the same issue as in this question: Best practice for use constants in scala annotations; try making ServiceModule.x final.

Upvotes: 4

Related Questions