
Hello, and welcome to Another Salesforce Blog! Here I will be posting solutions to problems that I couldn’t find an answer to in hopes of helping those who find themselves stuck when using the Salesforce platform.
User Story
We want to automate parts of our deployments using Salesforce’s Metadata API.
Background
Per Salesforce, the ANT Migration Tool is a “command-line utility for moving metadata between a local directory and a Salesforce org.” Using ANT, repetitive deployment tasks can be automated using Salesforce’s Metadata API.
This tutorial assumes that you have the most recent version of Apache ANT installed, instructions for which can be found here. I have my ANT folder installed under my C:\
directory for ease of access.
Although there are many resources available for ANT on the web, I had a hard time getting started. Let’s dig in.
Solution
The three necessary files for an ANT deployment are a build.properties
file, a build.xml
file, and a directory containing a package.xml
file, which I have named retrievepkg
. For this project, I have these files located in a folder under my ANT folder named C:\ant\RetrieveProfiles
.

package.xml
First, we will build our easiest component. The package.xml
file, or Project Manifest, specifies what changes will be made in our specified environment. Documentation is located here. Our package.xml
file will be located inside of the retrievepkg
folder as specified.
We want to select all profiles, so our code will be as follows:
<?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>*</members> <name>Profile</name> </types> <version>36.0</version> </Package>
We specify the version of XML we are using, the Salesforce metadata package being used, and the types of data we are extracting. The type name is “Profile”, and we are inserting the wildcard operator (“*”) to specify that we want to select all of them.

package.xml
filebuild.properties
The build.properties
file will contain information such as your username, password, package name, and login URLs.
Per the Salesforce documentation, it is advisable to use the following parameters:

sf.username
, sf.password
, sf.serverurl
, and sf.sessionId
from the Salesforce documentationBy naming and specifying different usernames and passwords, such as sf.usernameTest
in the build.properties
file, we are able to easily switch between a testing or staging environment and a production environment.
Today, we will just be specifying one username and password. If you are using a developer org, specify it here. You must append your security token to your password.
# build.properties # # Specify the login credentials for the desired Salesforce organization sf.username = USERNAME sf.password = PASSWORD #sf.sessionId = <Insert your Salesforce session id here. Use this or username/password above. Cannot use both> #sf.pkgName = <Insert comma separated package names to be retrieved> #sf.zipFile = <Insert path of the zipfile to be retrieved> #sf.metadataType = <Insert metadata type name for which listMetadata or bulkRetrieve operations are to be performed> sf.pkgName = retrievepkg # Use 'https://login.salesforce.com' for production or developer edition (the default if not specified). # Use 'https://test.salesforce.com for sandbox. #sf.serverurl = https://test.salesforce.com sf.testurl = https://test.salesforce.com sf.loginurl = https://login.salesforce.com sf.maxPoll = 20 # If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration. #
In this example, we have named a package for retrieval retrievepkg
, which is where our package.xml
file is located. MaxPoll indicates the maximum number of times the script will poll the server, and is an optional field that defaults to 200. Here we have set it to 20.

build.properties
filebuild.xml
Lastly, we will build our build.xml
file, which will contain a series of commands to be executed by ANT. Documentation is contained here. For this example, we will write a command to retrieve information. In another tutorial, we will write a command to deploy information.
First, we name our project and specify the base directory and our build.properties
file:
<project name="Another Salesforce Blog" default="test" basedir="." xmlns:sf="antlib:com.salesforce"> <property file="build.properties"/> <property environment="env"/> ...
The next step is to blank out the default values for username, password, and session id properties.
... <!-- Setting default value for username, password and session id properties to empty string so unset values are treated as empty. Without this, ant expressions such as ${sf.username} will be treated literally. --> <condition property="sf.username" value=""> <not> <isset property="sf.username"/> </not> </condition> <condition property="sf.password" value=""> <not> <isset property="sf.password"/> </not> </condition> <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition> ...
After blanking out the values, we specify the resources we are using, and the path to the ANT-salesforce.jar
file. Mine is located in C:\ant\ant-salesforce.jar
for ease of access.
... <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce"> <classpath> <pathelement location="C:\ant\ant-salesforce.jar" /> </classpath> </taskdef> ...
Now that we’ve specified the files that our script will be using, we will define the actions that our script will take. For now, we will just be retrieving the profiles in our org.
First, we name our function, retrieveProfiles
. We also need to make a directory to store our profiles in, which we will also name retrieveProfiles
.
... <!-- Retrieve Profiles --> <target name="retrieveProfiles"> <mkdir dir="retrieveProfiles"/> ...
Next, we define our action and close out the code. Line by line, we
- login
- specify which URL we are logging into (in this example, we use
sf.testurl
to log in usingtest.salesforce.com
) - define the maxPoll as defined in the
build.properties
file - tell the script where to place the retrieve results
and - let the script know where our
package.xml
file is located.
... <!-- Retrieve the contents into another directory --> <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.testurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveProfiles" unpackaged="retrievepkg/package.xml"/> </target> </project>
In all, our build.xml
code will look like this:
<project name="Another Salesforce Blog" default="test" basedir="." xmlns:sf="antlib:com.salesforce"> <property file="build.properties"/> <property environment="env"/> <!-- Setting default value for username, password and session id properties to empty string so unset values are treated as empty. Without this, ant expressions such as ${sf.username} will be treated literally. --> <condition property="sf.username" value=""> <not> <isset property="sf.username"/> </not> </condition> <condition property="sf.password" value=""> <not> <isset property="sf.password"/> </not> </condition> <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition> <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce"> <classpath> <pathelement location="C:\ant\ant-salesforce.jar" /> </classpath> </taskdef> <!-- Retrieve Profiles --> <target name="retrieveProfiles"> <mkdir dir="retrieveProfiles"/> <!-- Retrieve the contents into another directory --> <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.loginurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveProfiles" unpackaged="retrievepkg/package.xml"/> </target> </project>

build.xml
fileRunning the Script
In order to run your ANT script, open a command terminal and navigate to the folder your build.xml
file is located in. This can be achieved using the cd [FILEPATH]
command.
Once you have navigated to the appropriate folder, you can see what your named targets are using the ant -p
command. We only have one, retrieveProfiles
.
In order to run our target, use the command ant [TARGET NAME]
, in this case, we use ant retrieveProfiles
.

retrieveProfiles
resultsThis will insert a folder titled “profiles” into our retrieveProfiles
folder, with metadata for each profile in the organization.

In my next tutorial, I will explain how to update object permissions for profiles using the metadata we extracted.
Thanks for reading, let me know if you have any comments or questions!

Evelyn Grizzle
Another Salesforce Blog

One response to “Getting Started With ANT: Retrieving Metadata via ANT Migration Tool for Salesforce”
[…] our changes. For a step by step walkthrough of each line of code, please see my previous tutorial here. Note that we are specifying the login parameters as sf.usernameStage and sf.passwordStage so that […]