Reputation: 1470
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
Reputation: 35437
You don't need anything extra: Guice can do it out-of-the-box. But... you'll have to use Provider
s 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