I’m building my first application based on Guice, and I must say I’m thoroughly enjoying it. The application is a webapp that uses Jackrabbit as content repository, JCROM for object mapping, Struts2 for actions, and Tiles2 + FreeMarker for the views. There isn’t too much documentation around for Guice yet, so I thought it might be a good idea to share some of my findings. I’m going to start by showing you how I inject configuration parameters from a properties file into Java classes using Guice. If you don’t know Guice, it might be a good idea to read the Guice User Guide first.
One of the things that all applications have to deal with is loading configuration parameters. Guice provides us with a really elegant way of injecting the configuration parameters once we’ve loaded them. This is what we need to do:
- Annotate our Java class with configuration parameters it needs
- Create a properties file for the configuration parameters
- Modify our Guice module to load the configuration parameters and inject them
So let’s start with the annotations. For this example, let’s say we have an application that needs one configuration parameter: theme (this could be a theme for the look and feel of a web application). We have a Java class called ThemeManager, which needs to be configured with the theme name. It looks like this:
1 2 3 4 5 6 7 8 9 10 | public class ThemeManager { private final String themeName; public ThemeManager( String themeName ) { this.themeName = themeName; } //... do stuff using the theme name } |
We need to add Guice annotations to the class, to show Guice that we want this parameter to be injected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import com.google.inject.Inject; import com.google.inject.name.Named; public class ThemeManager { private final String themeName; @Inject public ThemeManager( @Named("themeName") String themeName ) { this.themeName = themeName; } //... do stuff using the theme name } |
Firstly, I’ve added an @Inject annotation to the constructor (line
to tell Guice that it needs to inject values here. Secondly, I’ve added a @Named annotation to the themeName parameter (line 9), to tell Guice that it should inject a String with the name “themeName” here. Let’s create a properties file, called myapp.properties, and add the themeName property:
themeName = default
The final thing I need to do, is to read the properties file in my Guice module, and inject the parameter. This is how I accomplish that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import com.google.inject.AbstractModule; import com.google.inject.name.Names; import java.net.URL; import java.util.Iterator; import java.util.Properties; public class MyModule extends AbstractModule { @Override protected void configure() { // bind the properties try { Properties properties = loadProperties(); bindConstant() .annotatedWith(Names.named("themeName")) .to(properties.getProperty("themeName")); } catch ( Exception e ) { // handle the exception } } private static Properties loadProperties() throws Exception { Properties properties = new Properties(); String name = "myapp.properties"; ClassLoader loader = MyModule.class.getClassLoader(); URL url = loader.getResource(name); if ( url == null ) { url = loader.getResource("/"+name); } properties.load(url.openStream()); return properties; } } |
No black magic here. After I load the properties, I bind the property value as a constant to everything that has been annotated with the name “themeName” (lines 14-16). Guice will therefore take this property and inject it into the ThemeManager class. The properties file is loaded from the classpath (I store my properties file in WEB-INF/classes), but you can load it from anywhere.
But it gets better! We can tweak the module code a bit to load all properties, whatever they’re named, from the properties file and inject. Guice supports this out of the box via the Names.bindProperties() method. This is how it would look:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import com.google.inject.AbstractModule; import com.google.inject.name.Names; import java.net.URL; import java.util.Iterator; import java.util.Properties; public class MyModule extends AbstractModule { @Override protected void configure() { // bind the properties try { Properties properties = loadProperties(); Names.bindProperties(binder(), properties); } catch ( Exception e ) { // handle the exception } } private static Properties loadProperties() throws Exception { // ... this remains unchanged } } |
Now we can add more properties to the property file, and annotate more classes that need configuration parameters, and those parameters will then be injected automatically without you having to change a single line of code in your module class!
For example, let’s say we have another class, RepositoryManager, that needs to be configured with a “repository path” parameter. We just need to annotate the class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import com.google.inject.Inject; import com.google.inject.name.Named; public class RepositoryManager { private final String repositoryPath; @Inject public RepositoryManager( @Named("repositoryPath") String repositoryPath ) { this.repositoryPath = repositoryPath; } //... do stuff using the repository path } |
…and then we add the parameter to the properties file:
themeName = default repositoryPath = /my/repository/path
And that’s it. No need to change the module. Guice will now inject both configuration parameters.






