Walter
Walter

Reputation: 1470

guice - select different providers while running

I want to change a provider I'm using at runtime without having to stop the JVM. For example, this isn't exactly what I'm trying to do, but the idea is the same: Say, I want to switch from Amazon S3 to Google Cloud storage in the middle of a running application.

Is that something I can do within guice?

I would have to have all jars available at runtime and configure all modules at startup. Then, later once the application is started, I'd have to use a provider that can determine which instance to inject @ startup and later on when it changes.

Or, would it be better just to restart the application after updating a configuration and the system would then proceed with that configuration and if it needs to change, the application would again need to be restarted.

Would OSGI help here?

Upvotes: 0

Views: 149

Answers (1)

Olivier Grégoire
Olivier Grégoire

Reputation: 35437

You don't need anything extra: Guice can do it out-of-the-box. But... you'll have to use Providers instead of the direct instance.

In your module

bind(Cloud.class)
  .annotatedWith(Names.named("google"))
  .to(GoogleCloud.class);
bind(Cloud.class)
  .annotatedWith(Names.named("amazon"))
  .to(AmazonCloud.class);
bind(Cloud.class)
  .toProvider(SwitchingCloudProvider.class);

Somewhere

class SwitchingCloudProvider implements Provider<Cloud> {
  @Inject @Named("google") Provider<Cloud> googleCloudProvider;
  @Inject @Named("amazon") Provider<Cloud> amazonCloudProvider;
  @Inject Configuration configuration;        // used as your switch "commander"
  public Cloud get() {
    switch(configuration.getCloudName()) {
      case "google": return googleCloudProvider.get();
      case "amazon": return amazonCloudProvider.get();
      default: 
        // Whatever you want, usually an exception.
    }
  }
}

Or in a provider method in your module

@Provides
Cloud provideCloud(
    @Named("google") Provider<Cloud> googleCloudProvider,
    @Named("amazon") Provider<Cloud> amazonCloudProvider,
    Configuration configuration) {
  switch(configuration.getCloudName()) {
    case "google": return googleCloudProvider.get();
    case "amazon": return amazonCloudProvider.get();
    default: 
      // Whatever you want, usually an exception.
  }
}

Usage

class Foo {
  @Inject Provider<Cloud> cloudProvider; // Do NOT inject Cloud directly or you won't get the changes as they come up.
  public void bar() {
    Cloud cloud = cloudProvider.get();
    // use cloud
  }
}

Upvotes: 2

Related Questions