Reading Ant variables from multiple properties files - java

I have an Ant buildfile that imports the following at the top of the file:
<project name="..." ...>
<property file="build.properties"/>
...
In the project root I have two properties files: build.properties and special-config.properties. I am defining a target that needs to read the following property out of special-config.properties:
always.ask=true
So the target needs to be something like this (just keep in mind that build.properties was already set as the property file long before this target ever executes):
<target name="exec-special-logic">
<!-- Somehow read special-config.properties#always.ask and set it to a local variable... -->
</target>
But I am ansure of how to load this 2nd property file and make its properties (such as always.ask) available to Ant. Thanks in advance.

You can read properties from as many different files as you like, so you could have
<property file="build.properties"/>
<property file="build.properties.part2"/>
And so on. In Ant the first value set for a property sticks - properties are quietly immutable. Hence if you have:
<property name="my.prop" value="one" />
somewhere in the first file and
<property name="my.prop" value="two" />
later - perhaps in the second file, the property will have the value "one" for the duration of the build.
A feature of recent versions is that properties can be localised to an execution block - this lets you "get around" the immutability. Here's an example lifted straight from the docs for the Ant local task:
<property name="foo" value="foo"/>
<target name="step1">
<echo>Before local: foo is ${foo}</echo>
<local name="foo"/>
<property name="foo" value="bar"/>
<echo>After local: foo is ${foo}</echo>
</target>
<target name="step2" depends="step1">
<echo>In step2: foo is ${foo}</echo>
</target>
outputs
step1:
[echo] Before local: foo is foo
[echo] After local: foo is bar
step2:
[echo] In step2: foo is foo

Related

Read property from file and assign to a different name in ant?

I am trying to read a property from properties file and assign to a different name but it is not working. I am new to ant so I guess I am missing something basic.
build.properties:
USERNAME=deter_dangler
build.xml:
<project name="Simple Ant example" default="test" basedir=".">
<property file="build.properties"/>
<property environment="env"/>
<property name="uname" value="${env.USERNAME}"/>
<target name="test">
<echo message="uname property value is ${uname}"/>
<echo message="env.USERNAME property value is ${env.USERNAME}"/>
</target>
</project>
The output when I run the build command:
javanoob#DELL:~/Desktop$ ant
Buildfile: /Desktop/build.xml
test:
[echo] uname property value is ${env.USERNAME}
[echo] env.USERNAME property value is ${env.USERNAME}
BUILD SUCCESSFUL
Total time: 0 seconds
Trying setting the environment variable as follows:
USERNAME=deter_dangler ant
Alternatively, if you want to use a properties file then simplify your ANT file as follows:
<project name="Simple Ant example" default="test" basedir=".">
<property file="build.properties"/>
<target name="test">
<echo message="uname property value is ${USERNAME}"/>
</target>
</project>
I believe that it could be simple incorrect environment variable being used i.e., by default USER is available on the linux machine without requiring to be explicitly defined by user and you are using USERNAME. I assume this is what user is expecting as he is trying to print value from property and another one from system defined default.
So, just replacing the above mentioned changes in the build.properties and build.xml files.
build.properties
USER=deter_dangler
build.xml
<project name="Simple Ant example" default="test" basedir=".">
<property file="build.properties"/>
<property environment="env"/>
<property name="uname" value="${USER}"/>
<target name="test">
<echo message="uname property value is ${uname}"/>
<echo message="env.USER property value is ${env.USER}"/>
</target>
</project>
Output
Buildfile: /home/apps/Documents/so/34553709/build.xml
test:
[echo] uname property value is deter_dangler
[echo] env.USER property value is apps
BUILD SUCCESSFUL
Total time: 1 second
In the above, if you notice, ${USER} is taken from property file and ${env.USER} from system logged in user.

Ant/Build a JAR : Build failed, Reference task.path not found

I'm working on a project with a build.xml to generate a JAR file.
When I try to build it I get this error:
Buildfile: D:\xxxxx\trunk\project-java\build.xml
BUILD FAILED D:\xxxxxtrunk\project-java\build.xml:25: Reference
task.path not found.
Total time: 140 milliseconds
Build.xml with the line where it crashes.
<?xml version="1.0"?>
<project name="xxxxx" default="prepare-release" basedir=".">
<property name="project.dir" value="."/>
<property file="${project.dir}/build.properties"/>
<property file="${project.dir}/svn.properties"/>
<property name="dist.dir" value="${project.dir}/dist"/>
<property name="build.dir" value="${project.dir}/build"/>
<property name="src.dir" value="${dist.dir}/${dist.type}/src"/>
<property name="release.dir" value="${project.dir}/release"/>
<!-- load svn tasks -->
// Pb on this line
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml"
classpathref="task.path" />
What can it be? Thanks for your help.
BUILD FAILED D:\xxxxxtrunk\project-java\build.xml:25: Reference task.path not found.
Well, where is the classpath task.path defined in your build.xml file?
When you define a task via <taskdef>, you need to do several things:
You need to specify the jar file where the task exists.
You need to specify the class that contains the task, and how to find it in the jar. This can be done in one of two ways:
You say the class is in com.foo.bar.mytask, and then give it a name.
You can specify a resource in the jar (either a properties file or an XML file) which pretty much says what class is associated with each name (which is what resource="org/tigris/subversion/svnant/svnantlib.xml" is doing.
Finally, you need to specify how to find that jar file.
That last one you're missing. You specified a reference to a classpath called task.path, but didn't actually define that classpath.
There are several things you can do:
You can put the jar into the $ANT_HOME/lib directory. When you define a task via <taskdef/>, Ant automatically looks there. I'm not fond of this because it means that you build doesn't work on other users' machines because they may not have that jar installed.
You can define a classpath to find it.
This is my preference, and here's how I usually do it.
<taskdef resource="org/tigris/subversion/svnant/svnantlib.xml">
<classpath>
<fileset dir="${basedir}/antlib/svnant}"/>
</classpath>
</taskpath>
In your project, create a directory called ${basedir}/antlib/svnant and put all five jars that came with this SVNAnt task in that directory. This way, all of the jars you need for your optional build tasks are now inside your project. If someone checks out your project from the version control system, they automatically get the needed task jars.
I put all of my optional ant task jars in that ${basedir}/antlib directory, and put each in their own directory in that directory.
Remember I said one of the things you need is to specify the class that contains the task?.
Here's what that org/tigris/subversion/svnant/svnantlib.xml file you specified looks like in svnant.jar:
<?xml version="1.0"?>
<antlib>
<!-- Tasks -->
<taskdef name="svn"
classname="org.tigris.subversion.svnant.SvnTask" />
<!-- Types -->
<typedef name="svnFileSet"
classname="org.tigris.subversion.svnant.types.SvnFileSet" />
<!-- Selectors -->
<typedef name="svnNormal"
classname="org.tigris.subversion.svnant.selectors.Normal" />
<typedef name="svnAdded"
classname="org.tigris.subversion.svnant.selectors.Added" />
<typedef name="svnReplaced"
classname="org.tigris.subversion.svnant.selectors.Replaced" />
<typedef name="svnModified"
classname="org.tigris.subversion.svnant.selectors.Modified" />
<typedef name="svnConflicted"
classname="org.tigris.subversion.svnant.selectors.Conflicted" />
<typedef name="svnIgnored"
classname="org.tigris.subversion.svnant.selectors.Ignored" />
<typedef name="svnUnversioned"
classname="org.tigris.subversion.svnant.selectors.Unversioned" />
<typedef name="svnLocked"
classname="org.tigris.subversion.svnant.selectors.Locked" />
<typedef name="svnMissing"
classname="org.tigris.subversion.svnant.selectors.Missing" />
<typedef name="svnDeleted"
classname="org.tigris.subversion.svnant.selectors.Deleted" />
<!-- Conditions -->
<typedef name="svnExists"
classname="org.tigris.subversion.svnant.conditions.Exists" />
</antlib>
It's just a map of task names to classes inside the jar.
Search your entire build.xml, the transitive closure of
included files, and all super projects for the string "task.path".
If missing or not of the following form, add or correct the form. Be sure you're not trying to identify it in some manner other than an #id attribute setting.
<path id="task.path">
...
</path>
If found but in a super project (which calls the current project via ant or antcall tasks), set the inheritrefs attribute to true to pass along the definition.
If found but in a parallel task that also defines the same #id
value, the last task to finish will override the other's reference. Consider cleaning things up to avoid ambiguity.
See also: Ant objects and references: what is the scope of a reference's ID?

Pass environment variables to Ant build.xml from Jenkins?

I am using Jenkins as CI. I have an build.xml. Build.xml has code like below.
<property name="environment" value="$environment}" />
How can i pass value to build.xml from Jenkins ? Can i pass it through environment variables?
Your environment variables are available via the environment property.
In the example below, the environment variable VIEW is printed from the simple hello world ant script via ${env.VIEW}. Change VIEW to the name of the environment variable of interest.
<?xml version="1.0" encoding="UTF-8"?>
<project name="Hello World" default="Hello" basedir=".">
<property environment="env"/>
<property name="HelloText" value="Hello"/>
<target name="Hello">
<echo>VIEW=${env.VIEW}</echo>
</target>
</project>
IMPORTANT! Note that this line is needed in order for env.VIEW to be understood by ant:
<property environment="env"/>
If your ant build dependeds on the property environment:
<property
name="environment"
value="a_value_I_edit_just_before_run_ant_default_target_mannually" />
you could configure your Jenkins' job to build with parameter:
so Jenkins will log (i.e. on Windows) something like:
cmd.exe /C '"ant.bat ant -file build.xml -Djenkins_environment=myValue && exit %%ERRORLEVEL%%"'
Then you could modify your ant build to check for system property:
<property
name="manually_edited_environment"
value="a_value_I_edit_just_before_run_ant_default_target_manually" />
<condition property="environment"
value="${jenkins_environment}"
else="${manually_edited_environment}">
<isset property="jenkins_environment" />
</condition>
if the jenkins_environment property is set then environment gets its value, else environment gets manually_edited_environment's value; the remaining part of your build still depend on the property environment.
If you have trouble in correctly matching the -DpropertyName use the echoproperties ant task to make ant logging all system properties.
your ant script should look like this:-
<target name="test" >
<property environment="env" />
<echo>BUILD_NUMBER: ${env.BUILD_NUMBER}</echo>
</target>
You can set properties with build parameters (ie: myParameter) and get them in an ant script with ${myParameter}.
Just make sure you don't use dots in parameters names in jenkins because there might be problems getting them in the ant script.
As for environment variables, i don't know, sorry.
Considering parametrized build as in the case above e.g you must have set variable called environment in the job and getting its value from user.Now you can refer to its value in build.xml using property name="environment" value="$environment}

ANT <propertyfile> task changes are committed after the execution

I am using a property file in ANT build script. Now, I am modifying some properties in the file based on the user input. The problem is that the changes are not effective during the execution but once the execution completes.
Here is the ANT script:
<project name="testProject" default="test" basedir=".">
<property file="my.properties"/>
<target name="test" depends="input">
<echo>${user}</echo>
</target>
<target name="input">
<echo>Taking user input</echo>
<input message="Please enter db-username:" addproperty="db.user"/>
<propertyfile file="my.properties">
<entry key="user" value="${db.user}"/>
</propertyfile>
</target>
</project>
Here is my.properties file:
#Fri, 23 May 2014 21:23:43 +0530
#My properties
#Thu, 22 May 2014 19:01:12 +0530
test=1
user=test
Here is the output after running:
D:\tmp>ant
Buildfile: D:\tmp\build.xml
input:
[echo] Taking user input
[input] Please enter db-username:
me
[propertyfile] Updating property file: D:\tmp\my.properties
test:
[echo] test
BUILD SUCCESSFUL
Total time: 4 seconds
But the file my.properties is update with user=me. Please tell me if this is the correct way of doing or any other alternative.
Interesting scenario, you can do the way how you are doing now. There will no problem but unnecessary complex for maintenance.
if you have different db user names you should pre define in property file instead of overwriting during execution.
dev.username="dev1234"(..${db.user})
qa.username="q1234"
prod.username="prodxxx"
First, once an Ant property is set, its value is immutable. It cannot change.
Second, once a property is set with <property file="my.properties"/>, the property's value cannot change. Even if my.properties has changed, further calls to <property file="my.properties"/> will not overwrite any existing properties.
Third, the <echo> in the test target doesn't echo the user's input.
This...
<target name="test" depends="input">
<echo>${user}</echo>
</target>
...should be...
<target name="test" depends="input">
<echo>${db.user}</echo>
</target>
Finally, the <propertyfile> task appears to create a new property in my.properties:
<propertyfile file="my.properties">
<entry key="username" value="${db.user}"/>
</propertyfile>
The above creates a property named username in my.properties. However, the rest of the script refers to the plain user property.

Some clarification about this section of ant script?

I am studying how ant work and I have some doubts related to it. I have an ant xml script definition file that begin in this way:
<?xml version="1.0"?>
<project name="Peacock Engine" default="default"> <!-- "default" is the default target -->
<tstamp />
<!-- ============================================ -->
<!-- Load build properties -->
<!-- ============================================ -->
<property name="project.buildfile" value="build.num" />
<property file="${project.buildfile}" />
<property file="info.properties" />
<!-- ============================================ -->
<!-- Specify the classpath -->
<!-- ============================================ -->
<path id="project.classpath">
<fileset dir="${project.libdir}">
<include name="${project.libs}" />
</fileset>
</path>
<!-- ============================================ -->
<!-- The default target -->
<!-- ============================================ -->
<target name="default" depends="jar"/>
Now help me to analyze this:
1) project tag is the root target and I use it to specify the project attributes.
2) : what exactly do this line?
3) Then I have these lines:
<property name="project.buildfile" value="build.num" />
<property file="${project.buildfile}" />
<property file="info.properties" />
What exactly do? I think that the first line create something like a variable named project.buildfile and load into it the content of a file named build.num
REgarding the following 2 lines I have few idea about what they do...can you help me?
4) Then in the ant script I find these lines:
<!-- ============================================ -->
<!-- Specify the classpath -->
<!-- ============================================ -->
<path id="project.classpath">
<fileset dir="${project.libdir}">
<include name="${project.libs}" />
</fileset>
</path>
I tryed to search on the web but I have totaly no idea about this section
5) Finnslly I have this section that is the definition of the default target that is the default action that is executed when I launch the ant script withous specify a specific task (a specific target):
<!-- ============================================ -->
<!-- The default target -->
<!-- ============================================ -->
<target name="default" depends="jar"/>
I am not totally sure about it but I think that by this line I am sayng that the default behavior of the ant script is to compile the program and that the compiled program is put it inside a Jar file.
Someone can help me to understand better this script code?
Tnx
Andrea
1) and 2) This sets the name of the project to "Peacock Engine" and sets the default task to the task named "default" (see 5)). The default task will be executed if you invoke Ant without providing a specific task:
<project name="Peacock Engine" default="default">
3) <property name="project.buildfile" value="build.num" /> creates a property which you can access anywhere in your Ant file with ${project.buildfile}. The value of the property will be build.num
<property file="${project.buildfile}" /> makes use of the above defined property. It basically loads the file "build.num" and makes all properties that are defined in this file available for further use. How does a property file work ? Have a look at the ant documentation of the property file task.
<property file="info.properties" /> loads another property file called "info.properties" and also makes all the properties in this file available to Ant.
4)
<path id="project.classpath">
<fileset dir="${project.libdir}">
<include name="${project.libs}" />
</fileset>
</path>
This tag defines a classpath. The path tag encloses a fileset. The fileset includes all libraries in ${project.libdir} that include the name ${project.libs}. Both are variables that might have been defined by including the property files above.
Effectively this tag gives you a set of libraries that can be included anywhere in the build file by referencing it's id (project.classpath).
5) <target name="default" depends="jar"/> see 1). The project tag references this target as default target when no target is supplied. This target has another target which it depends on. The target named in "depends" will be executed before "default". Again, if "jar" has another target that it depends on, this target will be executed first, and so on. It is a "call-graph". See the documentation on targets for more information on this.
You may want to have a look at the Ant documentation for writing a simple build file as a starting point to get more familiar with Ant.
1) project tag is the root target and I use it to specify the project attributes.
The project tag simply names the project, you also have the default target defined. The project tag is not, itself, a target.
<property name="project.buildfile" value="build.num" />
Creates a property named project.buildfile and sets the value to 'build.num'
<property file="${project.buildfile}" />
reads a set of properties from a file, the name of which is stored in the property project.buildfile, the value of which, in this case, is 'build.num'.
<property file="info.properties" />
reads a set of properties from a file named 'info.properties'
<path id="project.classpath">
<fileset dir="${project.libdir}">
<include name="${project.libs}" />
</fileset>
</path>
Creates a path named 'project.classpath'. The path will have the root defined in the projectlib.dir property and contains all files defined in the project.libs property
<target name="default" depends="jar"/>
means that the target default is dependent on the target jar successfully completing first. Ant will run the jar target automatically to satisfy this requirement.
Apache maintains a manual for Ant here
You should go to Ant Manual and read through it. It'll help you understand many of your questions.
Project Line
Ant files are XML files, and XML files have a root entity that encloses all the other entities. This is what the <project> entity is. Here's a simple Ant build.xml file:
<project>
<echo message="Hello, World!"/>
</project>
The sole task in this file (<echo>) is enclosed in the <project> XML entity.
The <project> entity can take some attributes:
name: The name of the Ant project. This is available in the ${ant.project.name} property.
default: The default target you want to execute. Ant basically has a two-level hierarchy. There are targets and there are tasks. A target is what you want to execute (compile, package, execute, clean, etc.), and targets contain tasks to accomplish what you want to do.
basedir: The base directory used when you specify a directory. The default is the current directory.
XML Namespaces: Don't worry about this one for now. You won't be using this until you get more comfortable with Ant.
Property Lines:
Then I have these lines:
<property name="project.buildfile" value="build.num" />
<property file="${project.buildfile}" />
<property file="info.properties" />
Ant uses something called properties which you can think of as variables. However, once a property is set, it can't be changed. For example:
<property name="foo" value="This is the initial value of foo"/>
<property name="foo" value="This is my new value"/>
The first line sets ${foo} to This is the initial value of foo. The second line does nothing. In fact, it doesn't fail or anything. It simply doesn't reset the value.
You can use this to adjust your build system by creating property files that Ant will read in first before the build takes place. The first line sets a property called ${project.buildfile} to the file build.num. This is the build number. The second line reads in all the properties in this file and sets their values. The third line reads in another property file that may setup other properties. Here's a quick example:
<project>
<property file="build.num"/>
<property name="build.number" value="Not Set"/>
<echo message="The build number is ${build.number}"/>
</project>
Let's say there's no file called build.num. In this case, ${build.number} is set to Not Set, and the build file will print out:
The build number is Not Set
Now, let's make a file called build.num, and it is this:
build.number = 1234
Now, when I run the build, it will read in the property build.number from the build.num file. The <property name="build.number" value="Not Set"/> won't change the build number since it was already set. The build will now print out:
The build number is 1234
Now, let's say I run my build like this:
$ ant -Dbuild.number=9876
I am setting ${build.number} on my command line. The build will still read in the file build.num, but won't set ${build.number} from it since I've already set it. The line <property name="build.number" value="Not Set"/> will also be ignored since ${build.number} is already set.
Path
Then in the ant script I find these lines:
<!-- ============================================ -->
<!-- Specify the classpath -->
<!-- ============================================ -->
<path id="project.classpath">
<fileset dir="${project.libdir}">
<include name="${project.libs}" />
</fileset>
</path>
There are two types of data in Ant. One is the properties which I mentioned above. The other are Paths. A Path is a series of files or directories. You see this in Unix and Windows with the PATH environment variable:
$ echo $PATH
$ /bin:/usr/bin:/usr/local/bin:/home/david/bin
If I type in a command, the operating system will search each of my directories in the PATH to find that command. In Java, you have the CLASS_PATH which are the jars you need to compile your project.
This is setting a path called project.classpath. It basically takes all of the jars that matches the <fileset> criteria and puts them in a path that can be used later, maybe for the compilation.
Targets:
<target name="default" depends="jar"/>
As I mentioned earlier, Ant has a two level hierarchy: Targets are the things you want to accomplish. Think of them as a program. A compile target is a program to compile your code. Targets contain tasks that need to be done to run the target.
Some tasks depend upon other tasks. For example, a target to test my code will be dependent upon the target to compile the code. I can't test my code without it first compiling:
<target name="test" depends="compile">
....
</target>
Some targets simply specify other targets. For example, I have a target called all. This runs the target to clean up my directory structure and get rid of any previously built files, compile my code, run tests, and then to package up my code:
<target name="all" depends="clean,compile,test,package"/>
The all target doesn't do anything itself. It's just a way to combine all of the other targets into one easy to use target. I run all, and everything I need to do a complete build is done.
In this case, the developer is defining a target called default that runs the jar target. You can see in their <project> entity that the default target for this project is called default, so if I run Ant without specifying a target, it will run the default target.
This is a bit convoluted. The developer could have left this out, and simply set default="jar" in the <project> entity.
As I mentioned before, go to the Ant Manual and it will help you learn Ant. Plus, give you a reference you can use to learn more about these various tasks.
Dude Maven is the new kid on the block. Try it and you won't need ANT. I have been using it for a month now and no more going back to ANT. There are a lot of tutorials online on how to used it with your projects. Maven Website

Categories

Resources