Skip to content
October 2, 2014 / BrianOFlan

Ant Property Setting Order

Everyone knows that Ant properties are immutable [1]:  Once set, they retain their first-set value forever.  Further attempts to set a property of the same name are ignored by Ant (unless, using ant-contrib [2], the property is unset like this: <var name="x" value="" unset="true"/> [3]).
 
You may wonder if there is any way to change (or “mute”?) the otherwise immutable sacredness of properties. In fact, “user” properties (or “command line” properties, set with -D on the command line) are the only properties that are truly immutable and immune to all the following attempts at overriding (but not immune to the ant-contrib “var” task).
 
The important implication there is that these two lines will set a property to the value “abc”:
<property name="xmlFileProperty1" value="abc" />
<property name="xmlFileProperty1" value="def" />
 
The first attempt to set the property wins:  The property setting order is first-set.  This pattern is reinforced if you try to set the same property name from the command line:  Ant sees the command line before it finds its build.xml (or -f file) and keeps the command line value for that property.  The pattern also holds if you had already set the property indirectly by loading a property file (with <property file="someFile.properties" />) and that file included that same property name.  Ant keeps the property file’s value if the file is loaded first (as long as no “user”/command line properties have already set it).
 
You can kind-of get around some property immutability by calling a target using the “antcall” task [4].  That task takes nested “param” elements with the same kinds of attributes as the “property” task and can override properties of the same name (except for “user” properties).
 
But!  When you have more than one param with the same name, something unexpected happens:  The property setting order is last-set.  That is to say that these lines set a property to the value “def” (but only until the antcall-ed target returns or concludes):
 

<antcall target="someTarget">
<param name="antcallProp1" value="abc" />
<param name="antcallProp1" value="def" />
</antcall>

 

Similar seemingly out-of-order property setting shows up with the “ant” task [5], the task that invokes another Ant build file:

<ant antfile="someOtherXmlFile">
<property name="antTaskProp1" value="abc" />
<property name="antTaskProp1" value="def" />
</ant>

 

 
Property files themselves behave this way (last-set).  A property file like this will end up setting the property to “def” (unless something else has already set the imilar seemingly out-of-order property setting shows up with the “ant” task, the task that invokes another Ant build file:
propertyFileProp1=abc
propertyFileProp1=def
 
What’s interesting is that this is not documented for Ant or for java.util.Properties (which Ant uses for loading properties files) [6][7][8].  (If you expected java.util.Properties to do something cool like create an array out of any key with too many definitions, there’s Apache Commons’s PropertiesConfiguration class[9][10][11].)
 
There is one more undocumented situation where Ant defies its property setting order:  With command line argument properties (“user” properties).  If you set the same property more than once on the command line, the property setting order is last-set.  A command like this will end up setting the property to “def”:
ant -DcmdLineProp1=abc -DcmdLineProp1=def
 
Knowing that can be very important in case you need to override some setting.  I have seen long Ant commands with many command line variables.  Without thoroughly researching all the possible values each variable could end up being, there is no way to know whether or not you are accidentally overriding a property.  (And without knowing the property setting order, you may not know that the last command line property wins.)
 
If you had a variable called ANT_ARGS_NORMAL set to “-v -Djavac.debug=off -lib ../some/path” setting and used javac.debug to control the “debug” attribute of the “javac” task [12][13] — if that, then these two commands would produce opposite results (only the second command produces class files with debug metadata:

ant -Djavac.debug=true ${ANT_ARGS_NORMAL}
ant ${ANT_ARGS_NORMAL} -Djavac.debug=true

 

 

 

And that’s what bit me today.

And that’s what inspired this investigation into the true nature of Ant property setting order.

 

 

References:
1. http://ant.apache.org/manual/properties.html
2. http://ant-contrib.sourceforge.net/tasks/tasks/
3. http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html
4. http://ant.apache.org/manual/Tasks/antcall.html (“When more than one nested <param> element would set a property of the same name, the one declared last will win. This is for backwards compatibility reasons even so it is different from the way <property> tasks in build files behave.”)
5. http://ant.apache.org/manual/Tasks/ant.html (“When more than one nested <property> element would set a property of the same name, the one declared last will win. This is for backwards compatibility reasons even so it is different from the way <property> tasks in build files behave.”)
6. Not documented: http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29
7. Not documented but deduced: http://stackoverflow.com/a/15570024/969789
8. Not documented but deduced: http://stackoverflow.com/a/12558454/969789
9. http://commons.apache.org/proper/commons-configuration/userguide/howto_properties.html#Lists_and_arrays
10. http://commons.apache.org/proper/commons-configuration/userguide/howto_properties.html
11. http://stackoverflow.com/questions/20511865/how-to-read-the-property-file-when-duplicate-key-value-pair-exist-in-the-file
12. javac debug attrib in Ant: http://ant.apache.org/manual/Tasks/javac.html
13. javac debug (-g flag): http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: