Getting Started With ANT: Retrieving Metadata via ANT Migration Tool for Salesforce


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 file

build.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:

descriptions of sf.username, sf.password, sf.serverurl, and sf.sessionId from the Salesforce documentation

By 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 file

build.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

  1. login
  2. specify which URL we are logging into (in this example, we use sf.testurl to log in using test.salesforce.com)
  3. define the maxPoll as defined in the build.properties file
  4. tell the script where to place the retrieve results
    and
  5. 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 file

Running 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 results

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

Profiles have been retrieved!

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”

Leave a Reply

%d bloggers like this: