Reputation: 329
Like we do the following in Spring
@Value("${varName:0}")
int varName;
Is there a way to do this using Google Guice?
Upvotes: 2
Views: 6410
Reputation: 6456
In Guice you would annotate the method and make it optional. You then just assign the default value. If no property is there to be injected, it will be the default value.
For example:
public class TestModule3 extends AbstractModule {
@Override
protected void configure() {
// Properties p = new Properties();
// p.setProperty("myValue", "12");
// Names.bindProperties(binder(), p); // this binds the properties that usually come for a file
bind(Manager.class).to(ManagerImpl.class).in(Singleton.class);
}
public static interface Manager {
public void talk();
}
public static class ManagerImpl implements Manager {
@Inject(optional = true)
@Named("myValue")
int test = 0;
@Override
public void talk() {
System.out.println(test);
}
}
public static void main(String[] args) {
Manager instance = Guice.createInjector(new TestModule3()).getInstance(Manager.class);
instance.talk();
}
}
This will print "0" for you, because I commented out the property binding. If you remove the comments, it will bind the value 12 to the String myValue. The inject annotation takes care of the rest.
Hope that helps,
EDIT:
As @TavianBarnes pointed out, Guice 4+ has an OptionalBinder. I tried this for your usecase and could not make it work out of the box.
It appears that OptionalBinding is very useful for classes (actual instances), not for properties. Here is why:
You have to know all the properties in advance and bind them to their defaults. It is easy to forget them. The example shown by OP also shows that he does not know if he has the property available (based on the name).
Default implementation of property bindings don't work in combo with the OptionalBinding.
So the way you can make that work is like this:
OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named("myValue"))).setDefault()
.toInstance("777");
Properties p = new Properties();
p.setProperty("myValue", "12");
// use enumeration to include the default properties
for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements();) {
String propertyName = (String) e.nextElement();
String value = p.getProperty(propertyName);
OptionalBinder.newOptionalBinder(binder(), Key.get(String.class, Names.named(propertyName))).setBinding()
.toInstance(value);
}
I had to copy the Named binding code and change it to support optional bindings.
In summary:
I would prefer to use the optional=true flag + default value in code for properties.
Use the OptionalBinding for actual classes that can be optional.
Finally, there is one more thing you could do - this is my solution in my code. I have a similar requirement (not the optional, but default values).
I want:
Apache offers a handy library for this already which I reuse. This is how my properties look like:
myProperty=${ENV_VAR_NAME:-600}
This is the default annotation of how to define a default value. The above property says:
Then I bind it as follows:
InputStream resourceAsStream = getClass().getResourceAsStream(path);
if(resourceAsStream == null) {
throw new IllegalArgumentException("No property file found for path: " + path);
}
try {
p.load(resourceAsStream);
EnvironmentVariableSubstitutor envSubstitutor = new EnvironmentVariableSubstitutor(false);
Set<Object> keys = p.keySet();
for(Object k : keys) {
String property = p.getProperty(k.toString());
property = envSubstitutor.replace(property);
p.put(k, property);
}
} catch (IOException e) {
throw new IllegalStateException("Could not load properties", e);
} finally {
try {
resourceAsStream.close();
} catch (IOException e) {
log.error("Could not close stream for resource " + path);
}
}
Names.bindProperties(binder(), p);
What this code does is:
These are all the solutions I can come up with at short notice :) let me know if something's unclear
Edit 2:
there is some info on OptionalBindings and properties + how to handle default values in this google thread as well: https://groups.google.com/forum/#!topic/google-guice/7Ga79iU_sb0
Artur
Upvotes: 3