;

The build process in Netbeans changed significantly between the 3.x releases (the last one of which was 3.6) and the 4.x releases. In the 3.x releases you typically hand crafted an ant script and executed defined tasks using a pop up menu. It worked pretty well and I liked it. When 4.0 we released it was very quickly apparent that things had changed significantly. Gone was the hand crafted ant script, in its place was a machine written script and predefined tasks. Along with that was a sort of code management structure which forces you to place certain types of files in certain places (that's not 100% true you still have the option of DIYing it but it's more work). I didn't like the 4.0 release much. It was buggy and slow and the features weren't very well polished. The 4.1 release however is sweet as a nut. I now hope they continue this path as some of the new features are great. Anyway, this article is about the new build process which seemed to me to have one big problem: it was a total PITA to build for more than one environment (e.g. you could do a development build but you couldn't then do a production build without a lot of manual intervention). This tip will show you how to do a build for two environments but it could easily be any number of different environments with any number of different configuration files. As I work mostly on web applications I will present this tip using a web application but the method will work just as well for other types of application.

Switch to the files view and expand the first level of your project. Create a folder called configuration or some such but make sure it doesn't conflict with any folder names Netbeans creates (it will just cause confusion later). Under this create a folder for each build environment you want to use. In my case I will create production and development.

In the folders created in the step above place all the configuration files that are need to be changed depending on the build type (for instance you might add web.xml), include a properties file with string replacements or a combination of the two depending on your needs.

Open the build.xml file that resides in the root directory of the project you are working on. Add to that a -pre-comiple task that will ask what build type you are currently doing. The clever bit here is getting Netbeans to pop up a dialog that will ask you what type of build you are doing. This magic can be achieved with the following bit of code:

<target name="-pre-compile">
	<input message="Choose a build type:"
		validargs="development,production"
		addproperty="build.type"
		defaultvalue="development"
	/>
	<property file="configuration/${build.type}/build.properties"/>
</target>

Notice that I have got it to load a properties file. This is because I have found that generally I don't actually want to replace the whole of a given file, I only want to replace some strings in it. There are some advantages to this approach. The first is that you don't have to maintain numerous copies of the web.xml file - you just maintain one copy with a few cryptic strings in it that get replaced at build time. The second is that this approach integrates nicely with Netbeans. The cryptic strings I mentioned are just strings so you can continue to use the nice Netbeans view of the web.xml file and the correct file will still show up under the configuration files section. The downside of this is that the string replacement has to be performed after the compile stage because the strings are replaced in the copied files not the originals. This is only a minor draw back as there shouldn't be anything in the compile stage relying on runtime settings. If it is a problem then you could copy the file across manually in the -pre-compile strange and run a filter on it while you do so. In my case I prefer the -post-compile replace strategy which looks like this:

<target name="-post-compile">
	<replace file="${build.web.dir}/WEB-INF/web.xml" 
		token="@developer.details@" value="${developer.details}"/>
</target>

As you can probably tell the strings to be replaced are surrounded by @ characters which means that it is very unlikely they would normally show up in a web.xml file. The replacement string is pulled from the properties file that was chosen in the -pre-compile target. I could combine these into one target that would do everything but I want the flexibility to replace files before compile as well as change settings afterwards.