It’s easy for build.properties files to get out of hand when multiple projects, developers, hosts and environments are involved.
It’s pretty common to use a hierarchy of build.properties files to try and minimise duplication and keep things tidy, as described by Gene Goitmer in his blog post.
In short, this takes advantage of the fact that Ant properties cannot be overridden once set. By importing more specific (e.g. per user) properties files first, their values will remain even if the same property exists in more general (e.g. per environment) properties files.
I find that if our product involves multiple modules/projects, duplication can be avoided by having two such hierarchies – one common one, and another for each project. The common one is imported first, and contains properties such as the location of your local Apache Ivy cache.
Gene has a useful addition to my usual process, which is to have a file called “local.build.properties” for setting properties such as passwords that we want to avoid checking in. Adding it to svn:ignore ensures that it won’t be checked in accidentally.
I think that care needs to be taken with the use of overrides, particularly when using property values to detokenize configuration files. In those cases, I’ve seen setups in the past where the main properties file (“build.properties”, which is imported last) contains many properties that aren’t common for all environments, and require them to be overridden for all other environments.
I don’t think that this is a good idea, as it in effect will default any properties that you’ve forgotten to set correctly for a particular other environment. Worst case example, you could end up using the prod database with your dev build.
By not doing this, you’ll notice immediately if you’ve forgotten to set a property as your build will fail. Or if you’re using them for detokenizing some configuration files, you’ll also notice immediately when your post-detokenizing checks finds tokens in your detokenized files.