Music, software, life… and stuff.
[ Twitter ] [ GitHub ] [ Linked In ]
The “Property Override Configuration” feature is an extremely useful technique for Grails applications. It allows you to specify the values for bean properties in your application configuration, which can be done externally and/or in an environment sensitive manner.
For example, we could easily control the number of simultaneous connections a particular service is allowed to make to a particular thing.
Here is our fictitious service…
class ThingService {
def maxConnections
}
In our Config.groovy we might have…
beans {
thingService {
maxConnections = 10
}
}
environments {
test {
beans {
thingService {
// only use 1 connection when testing
maxConnections = 1
}
}
}
production {
// Load extra config from external location in production
grails.config.locations = ["classpath:thing-config.groovy"]
}
}
On the production classpath we might have a file called “thing-config.groovy” that has…
beans.thingService.maxConnections = 100
So we no have a default value of 10 for our maxConnections property, but overridden in test with a value of 1 and overridden in production with a value of 100. We can also change this value without a recompile in production (though you will need a restart).
That’s all well and good and pretty handy, but you can take it slightly further once you realise how this feature works.
Property Override Configuration works at the bean definition level in Spring. This means that the value you specify is not directly assigned to the corresponding property on the bean in question, but rather is added to the bean definition before Spring goes to work creating your beans (which is effectively the same as changing the original bean definition). This means that you can take advantage of Spring’s rich type conversion features to do some rather cool things.
For example, we can make dealing with the filesystem easier by combining Spring’s resource support with the Property Override Configuration mechanism. Let’s assume we have a service that wants to read a text file that is on the classpath.
Here is our service…
class TextFileReadingService {
File textFile
}
To populate that property you could either write the code yourself to create the instance, define a bean named textFile in resources.groovy and let autowiring set things up, or use Property Override Configuration. If we want to use Property Override Configuration, you might first try…
beans {
textFileReadingService {
textFile = new File(this.class.classLoader.getResource("theTextFile.txt").toURI())
}
}
While that will work, there is an easier way…
beans {
textFileReadingService {
textFile = "classpath:theTextFile.txt"
}
}
This works because Spring implicitly converts the String value we have given to a File object for us, and in doing this treats values with certain prefixes specially. This is part of Spring’s resource abstractions. Another useful prefix is “context:”, which resolves a file path relative to the root of the web app…
beans {
textFileReadingService {
textFile = "context:js/jquery.js"
}
}
Note that Property Override Configuration is particularly useful when working with beans that we don’t define ourselves, such as services, taglibs, controllers etc. If we were defining our own beans and did not need environment sensitivity or externalisation of the value, we could use the same type conversion facilities when definining our beans directly.
If we had a class in src/groovy that looked like…
class TextFileReader {
File textFile
}
We could create a Spring bean for it like so in resources.groovy…
beans = {
textFileReader(TextFileReader) {
textFile = "context:js/jquery.js"
}
}
The point of this example being to illustrate that type conversion is not unique to Property Override Configuration.
Property Override Configuration is a surprisingly useful feature that is generally under publicised. It’s worth adding to your arsenal of techniques, especially combined with the type conversion that Spring offers.
Posted: Oct 6th, 2010 @ 3:41 pm