Complete Salesforce Deployment Guide using Ant Migration Tool

Following are the many tools available for Salesforce deployment like

  1. Change sets (From Salesforce site)
  2. Eclipse (Using “Deploy to server” option in Eclipse)
  3. ANT (Java based tool)

We are going to discuss the ANT based migration, step by step:

JDK 1.5 or above

Step 1:
Download ANT distribution from – “

Step 2:
Set Environment variable “ANT_HOME“. The path should be of parent folder of “bin”. Also add the “bin” folder to your path.

Step 3:
Check whether ANT is installed or not properly by running command “ant -version“. It might be possible that you receive message something like unable to find tools.jar. You can copy this jar from “JDK_HOME/lib/tools.jar” to “JRE/lib” folder.

Salesforce Get ANT version
Salesforce Get ANT version

In above screen you can see that before copying tools.jar I was getting warning.

Step 4:

Login to salesforce and navigate to “Your Name |Setup | Develop | Tools” and download “ Migration tool”.

Unzip the downloaded file to the directory of your choice. Copy the “ant-salesforce.jar” file from the unzipped file into the ant lib directory.

To start with deployment using ANT, we will need “build.xml” and “” file. As there is no need of “” however its good to have it so that the configuration related settings are in different file. You can copy both files from “sample” folder of unzipped content from salesforce. Following is the structure of “” file.

# Specify the login credentials for the desired Salesforce organization
sf.username = <SFDCUserName>
sf.password = <SFDCPasswrd>
#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>
# Use '' for production or developer edition (the default if not specified).
# Use ' for sandbox.
sf.serverurl =

Step 5:
Copy all folders with source code from source organization using eclipse. Lets say the root folder name is “test1”.
Create “” from above code snippet or copy it from unzipped folder. Now create “build.xml” needed by ANT. Following is the example of build.xml file:

<project name="Shivasoft ANT Tutorial" default="deployCode" basedir="." xmlns:sf="antlib:com.salesforce">
    <property file=""/>
    <property environment="env"/>
    <!-- Shows deploying code &amp;amp;amp;amp; running tests for code in directory -->
    <target name="deployCode" depends="proxy">
      <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="test1">
    <!-- Shows removing code; only succeeds if done after deployCode -->
    <target name="undeployCode">
      <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="removecodepkg"/>
	<target name="proxy">
		<property name="" value=" ProxyURL " />
		<property name="proxy.port" value="1234" />
		<property name="proxy.user" value="UserName" />
		<property name="proxy.pwd" value="Password" />
		<setproxy proxyhost="${}" proxyport="${proxy.port}" proxyuser="${proxy.user}" proxypassword="${proxy.pwd}" />

Attribute “deployRoot” means the root folder from which the code should be copied and tag  means the testclasses which should run after the deployment. At last, go to the folder “test1” from command line and run command “ant deployCode”.


Salesforce Migration using-ANT
Salesforce Migration using-ANT

Checking the status of the task:
To know the status of task you can run command:
Ant targetName -Dsf.asyncRequestId=requestID

Using Proxy in ANT migration tool:
If your organization uses the proxy then add below target in “build.xml” and specify this target as dependent.

<target name="proxy">
		<property name="" value=" ProxyURL " />
		<property name="proxy.port" value="1234" />
		<property name="proxy.user" value="UserName" />
		<property name="proxy.pwd" value="Password" />
		<setproxy proxyhost="${}" proxyport="${proxy.port}" proxyuser="${proxy.user}" proxypassword="${proxy.pwd}" />

Retrieve content from Salesforce Organization:
create “package.xml” for the list of component to be retrieved and add following task in “build.xml”.

<!-- Retrieve an unpackaged set of metadata from your org -->
<!-- The file unpackaged/package.xml lists what is to be retrieved -->
<target name="test" depends="proxy">
  <mkdir dir="retrieveUnpackaged"/>
  <!-- Retrieve the contents into another directory -->
  <sf:retrieve username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" retrieveTarget="retrieveUnpackaged" unpackaged="unpackaged/package.xml" unzip="false" />

“Unzip” attribute specifies that the code retrieved should be in Zip format or not. By default the value is true means it will not in zip format.

Delete components from Salesforce Organization using “destructiveChanges.xml” :
In some cases, we may want to delete some components like Object or fields from Salesforce Organization. In this case, Only “package.xml” will not work. We need to create “destructiveChanges.xml” file also. Syntax for this file is exactly same as of “package.xml”, except that here we cannot define wildcards. So, to undeploy anything from Salesforce org, we need two xml files – “package.xml” and “destructiveChanges.xml“.

Below is complete code of build.xml, which includes retrieve, Undeploy and Deploy commands.

<project name="Shivasoft Demo Org" default="deployCode" basedir="." xmlns:sf="antlib:com.salesforce">
	<!-- Get all settings like Server Path, username and passwords from "" file -->
    <property file=""/>
    <property environment="env"/>
	<!-- Sequence 1 - Get All information from Source, Retrieve the contents into Src directory -->
	<target name="SFDCFetch">
	  <!-- -->
	  <sf:retrieve username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" retrieveTarget="src" unpackaged="package.xml"/>

	<!-- Sequence 3 - Deploy to Target System, Package.xml is present in Src folder -->
	<target name="deploy">
      <sf:deploy username="${sf1.username}" password="${sf1.password}" serverurl="${sf.serverurl}" deployroot="Src">

	<!-- Sequence 2 - If you want to remove some components, destructiveChanges.xml and Package.xml present in Delete Folder -->
	<target name="unDeploy">
      <sf:deploy username="${sf1.username}" password="${sf1.password}" serverurl="${sf.serverurl}" deployroot="Delete">

You may also be interested to check how to automate daily Salesforce backup.

How to Create Change set from Package.xml

Step 1 : Create Empty Changeset, lets say its name is changeset2
Step 2 : add fullname tag in package.xml. Fullname needs to be the name of changeset created in Step 1

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="">

Step 3 : src folder name which contains package.xml needs to have changeset name, in our case changeset2

How to Create Package.xml from Change set

Use below ANT script

<target name="retrieveChangeset">  
packageNames="changesetname" /> 


Update [03-Apr-2017]

Question : Why Salesforce ANT Migration tool is giving wrong Username, Security token or password error, even when everything is correct ?
Ans : If your password contains “$”, then ANT tool ignores this characters. So, to correct this, we need to add one more “$”.

Question : I am getting unable to find tools.jar files error. I don’t have access to server so cannot place tools.jar manually. Can I fix this error using build.xml by placing jar files in relative folder?

Ans : You can include any jar file to be in class path. Add below lines in build.xml. All jar files are placed in lib folder.

<path id="class.path">
<pathelement location="${build}"/>
<fileset dir="./lib">
<include name="**/*.jar" />

<taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce" classpathref="class.path"/>

Question : Why I am getting error like java.lang.OutOfMemoryError: Java heap space while retrieving metadata from Salesforce. 

Ans : It is possible that you are retrieving metadata of some big organization with lots of changes. In this case, Java JVM running on system needs more memory (RAM) in order to process it. It can be done in two ways

1. Before running ANT command, run below command which will set the RAM allocated for JVM to 1GB. If you are not a Windows user, then use export instead of set in below command.

set ANT_OPTS=-Xmx1g

2. Problem in above solution is that, you would need to execute set command every time before using ANT. For permanent solution, open ant.bat file in bin folder of ANT installation (Same installation folder referred in ANT_HOME). And, at very first line, write below command and save it.

set ANT_OPTS=-Xmx1g

I hope this article will help newbie to learn ant migration tool.

Related Posts


33 responses to “Complete Salesforce Deployment Guide using Ant Migration Tool”

  1. Sunu Avatar

    Thank you very much for the post

  2. Vinay Avatar

    Thanks a lot, very informative.

  3. sra Avatar

    Very good thanks shiva

  4. Nitish Mishra Avatar

    How can I deploy a folder using ant tool:

    when I used the below codes to deploy the folder :


    It gives the error:
    Retrive Commands ::

    F:AntDemosample>ant retrieveUnpackaged
    Buildfile: F:AntDemosamplebuild.xml
    [sf:retrieve] Request for a retrieve submitted successfully.
    [sf:retrieve] Request Id for the current retrieve task: 04s900000025E2EAAU
    [sf:retrieve] Waiting for server to finish processing the request…
    [sf:retrieve] Request Status: Completed
    [sf:retrieve] Retrieve warnings (1):
    [sf:retrieve] package.xml – Entity type: ‘Folder’ is unknown
    [sf:retrieve] Finished request 04s900000025E2EAAU successfully.

    Deploy command::

    F:AntDemosample>ant deployUnpackaged
    Buildfile: F:AntDemosamplebuild.xml
    [sf:deploy] Request for a deploy submitted successfully.
    [sf:deploy] Request Id for the current deploy task: 04s90000002BZDxAAO
    [sf:deploy] Waiting for server to finish processing the request…
    [sf:deploy] Request Status: Completed
    F:AntDemosamplebuild.xml:37: FAILURES:
    Error: package.xml():Unknown type name ‘Folder’ specified in package.xml
    Total time: 16 seconds

    Any help will be appreciated..:)

  5. Dedo Avatar

    Nice tutorial 🙂 can I run ANT to retrieve and deploy from/to salesforce from Eclipse?

    1. JitendraZaa Avatar

      Eclipse already have inbuilt Migration tool.

  6. planecrash Avatar

    How do I do a site to site copy? I get errors if I select every object in the eclipse dialog. For instance case assignments object for users in one site and not another?

    1. planecrash Avatar

      Eventually figured it all out, was a pain in the butt!

      1. JitendraZaa Avatar

        I just checked ur comment.. What was wrong at ur side ? If u can suggest i will update this article. Your feedback is appreciated

        1. planecrash Avatar

          Well basically I was given access to a development instance a consultant had coded. My level of experience was low, and it was difficult determining which metadata components to select, without any input from the people who wrote it, to completely move the custom app from one instance of salesforce to another. I have since identified the list of metadata components required in the migration and have continuous integration up and running with ant, the migration tool, Git, and JetBrains’ TeamCity.

  7. Salesforce user Avatar
    Salesforce user

    Thanks, it helped me in setting up proxy in build.xml

  8. Ta Avatar

    Hi I want to read a xml file form my local machine and update the account object with the xml data using ANT…please suggest me how should I achieve it.

  9. saravanan Avatar


    I have tried to retrieve the metadata from my
    developer org for practicing. But I am always getting – Invalid Api
    version specified on URL. I have posted this in developer forum but I
    didn’t get any reply .Could u pls help me on this. For more details
    about the error click the below link


  10. Hardik Chavda Avatar
    Hardik Chavda

    Hi Sir, I read your post. I have to say excellent job. I have one doubt though. If we can migrate everything using eclipse then why do we need ANT migration tool, In short my question is, What is it in ANT that makes it different from eclipse migration process? And what are the components that we can migrate using ANT but not using Eclipse.

    1. Jitendra Zaa Avatar

      Hi Hardik, There are many differences but most importany for me is ability to schedule migration in ANT which is not possible in Eclipse. Both supports almost same feature but Eclipse is more use friendly. If you are talking about Continiuse integration then go for ANT. There is very good article written by “James Loghry” at

  11. Skender Kollcaku Avatar
    Skender Kollcaku


    First of all thanks for this guide.
    I get the following error and sincerely do not fully understand what is the deployRoot:

    ./ant deployPlivoCheckOnly
    Buildfile: C:Antapache-ant-1.9.6-binapache-ant-1.9.6binbuild.xml

    [echo] Run ‘ant deployPlivo’ to deploy this library to your organization.
    [echo] Testing deployment of Plivo Helper Library for Salesforce without saving changes…
    C:Antapache-ant-1.9.6-binapache-ant-1.9.6binbuild.xml:22: Should provide a valid directory ‘deployRoot’ or a zip file ‘zipFile’.

    Any suggestion?


    1. Jitendra Zaa Avatar

      Not very sure but seems you have created build.xml in bin folder of ANT itself. I would suggest, remove ANT and fresh install. Set Class path for ANT bin folder and set ANT_HOME environment variable. create isolated folder for your project and run ANT from there.

      1. Skender Kollcaku Avatar
        Skender Kollcaku

        Hi, You are right.

        I did it from the start and now it should be all fine:

        C:Plivoplivo-salesforce-masterinstall>ant deployPlivo

        Buildfile: C:Plivoplivo-salesforce-masterinstallbuild.xml


        [echo] Deploying Plivo Helper Library for Salesforce…
        [sf:deploy] Request for a deploy submitted successfully.
        [sf:deploy] Request ID for the current deploy task: 0Af58000002UomDCAS
        [sf:deploy] Waiting for server to finish processing the request…
        [sf:deploy] Request Status: InProgress
        [sf:deploy] Request Status: Succeeded
        [sf:deploy] *********** DEPLOYMENT SUCCEEDED ***********
        [sf:deploy] Finished request 0Af58000002UomDCAS successfully.


        Total time: 15 seconds

        Now my question is: what is the next step in the integration process?
        How do I see a sample Demo Plivo app in my Salesforce instance?

        Thanks again,

  12. Sivanathan Palanivel Avatar
    Sivanathan Palanivel

    Hello Jitendra,

    I am facing an issue which I think you might help me with. I am receiving the below error with my TFS – Salesforce migration tool continuous build integration process. It was working fine until I upgraded the JRE version to 1.8. The JDK is 1.6. I have verified the ANT_HOME and JAVA_HOME parameters, its all looks fine to me. This issue only happens when I queue a new build from TFS. The whole setup is in one of the file servers and the local build(on the server) runs fine with no errors. What do you think I am missing in this case?

    Ant failed. Error output:
    Ant failed. Error output: BUILD FAILED
    Ant failed. Error output: java.lang.UnsupportedClassVersionError: com/sforce/ws/ConnectionException : Unsupported major.minor version 51.0
    Ant failed. Error output: ○at java.lang.ClassLoader.defineClass1(Native Method)
    Ant failed. Error output: ○at java.lang.ClassLoader.defineClassCond(
    Ant failed. Error output: ○at java.lang.ClassLoader.defineClass(


    1. Jitendra Zaa Avatar

      You need JRE 7 installed on system. Class version 51 from error needs updated JRE. check this for more info –

  13. Kamal Sharma Avatar
    Kamal Sharma

    When i execute command > ant retrieveCode. I got an error message

    Buildfile: C:UsersBispDesktopTest1build.xml

    [mkdir] Created dir: C:UsersBispDesktopTest1retrieveUnpackaged
    [sf:retrieve] Note: use ant -verbose to get more information on the failure

    C:UsersBispDesktopTest1build.xml:7: Failed to login: Failed to send request to https://${sf.serverurl}/services/Soap/u/38.0

    I am not using any proxy network still i build failed.

    Can you help me with this?

    1. Jitendra Zaa Avatar

      IN file, make sure sf.serverurl is defined.

      1. Kamal Sharma Avatar
        Kamal Sharma

        Hi Jitendra Thanks for response. I already defined in Sharing code to you .


        # Specify the login credentials for the desired Salesforce organization
        sf.username =
        sf.password =
        sf.serverurl =
        sf.maxPoll =20

        1. James24 Avatar

          I am also getting the same error. I check the URL it’s good. I gave the proxy setting as mentioned in this blog. is this something do with the firewall?

      2. Manoj Behera Avatar
        Manoj Behera

        Hi Jitendra,

        Can you please share with me your email Id please…I need a help from you please.

        my email Id:

  14. Manoj Behera Avatar
    Manoj Behera

    Hi Jitendra,

    Your help is much appreciated…I have gone through some of the blogs including your one, I could not be able to resolve this issue. My code is as:

    public static void execute(Set invoiceIds, String sid) {
    JSONGenerator gen = JSON.createGenerator(true);
    gen.writeObjectField(‘invoiceIds’, invoiceIds);
    String requestBody = gen.getAsString();
    HttpRequest req = new HttpRequest();
    String remoteSite = System.URL.getSalesforceBaseURL().getHost();
    req.setEndpoint(‘https://’ + remoteSite.toLowerCase()+’/services/apexrest/QUAN/Invoice/XmlWriter’);
    String authorizationHeader = ‘Bearer ‘ + sid;
    req.setHeader(‘Authorization’, authorizationHeader);
    req.setHeader(‘Content-Type’, ‘application/json’);
    Http http = new Http();
    HTTPResponse res;
    try {
    res = http.send(req);
    } catch (Exception e) {
    String msg = ‘Invoice submitted but XML data was not created successfully. Invoice records affected: ‘+invoiceIds;
    Strategy_Settings_QUAN__c settings = Strategy_Settings_QUAN__c.getInstance();
    String emailAddress = (String)settings.get(‘SAP_Support_Email_QUAN__c’);
    if(String.isBlank(emailAddress)) {
    emailAddress = ‘’;
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    List toAddresses = new List{emailAddress};
    mail.setSubject(‘SAP Invoice error’);
    mail.setHtmlBody(msg+ ‘Errors:’+e);
    mail.setPlainTextBody(msg+ ‘nnErrors:nn’+e);
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    //log exception in error log

    public static void writeXml(List invoiceIds) {
    // RestRequest req = RestContext.request;
    // RestResponse res = RestContext.response;
    String filePrefix = ”;
    Strategy_Settings_QUAN__c settings = Strategy_Settings_QUAN__c.getOrgDefaults();
    if (settings.Id != null && settings.Invoice_File_Prefix_QUAN__c != null) filePrefix = settings.Invoice_File_Prefix_QUAN__c;
    Id recordTypeId = [SELECT Id FROM RecordType WHERE DeveloperName = ‘Invoice_QUAN’ And SobjectType = ‘ContentVersion’].Id;
    Id workspaceId = [SELECT Id FROM ContentWorkspace WHERE Name = ‘Strategy’ Limit 1].Id;
    List existingPDFs = [SELECT Id, FirstPublishLocationId, Invoice_QUAN__c FROM ContentVersion WHERE FileType = ‘PDF’
    AND Invoice_QUAN__c IN :invoiceIds];
    Map invoiceIDToContentWorkspaceIDMap = new Map();
    for(ContentVersion existingPDF : existingPDFs){
    if(existingPDF.Invoice_QUAN__c != null && existingPDF.FirstPublishLocationId != null){
    invoiceIDToContentWorkspaceIDMap.put(existingPDF.Invoice_QUAN__c, existingPDF.FirstPublishLocationId);
    List xmlFiles = new List();
    for (String invoiceId : invoiceIds) {
    PageReference xmlFile = Page.QUAN_InvoiceAFIXML;
    xmlFile.getParameters().put(‘id’, invoiceId);

    ////Exception throws from the below line.
    Blob b = (!Test.isRunningTest()) ? xmlFile.getContent() : Blob.valueOf(‘MyText’);
    //Blob b = xmlFile.getContent();

    ContentVersion invoiceXml = new ContentVersion();
    invoiceXml.Title = filePrefix+invoiceId+’.xml’;
    invoiceXml.PathOnClient = filePrefix+invoiceId+’.xml’;
    invoiceXml.FirstPublishLocationId = invoiceIDToContentWorkspaceIDMap.get(invoiceId);
    } else {
    invoiceXml.FirstPublishLocationId = workspaceId;
    invoiceXml.Document_Type_QUAN__c = settings.QUAN_Invoice_XML_Writer_Document_Type__c;
    invoiceXml.RecordTypeId = recordTypeId;
    invoiceXml.Invoice_QUAN__c = invoiceId;
    invoiceXml.VersionData = b;
    insert xmlFiles;

    //delete any other xml-related documents on this invoice
    Set contentDocumentIds = new Set();
    for (ContentVersion cv : [SELECT ContentDocumentId From ContentVersion WHERE Invoice_QUAN__c in :invoiceIds AND Title like ‘%.xml%’ AND Id not in :xmlFiles])
    try {
    delete [SELECT ID FROM ContentDocument WHERE Id in :contentDocumentIds];
    } catch (Exception e) {
    System.debug(‘nnnMERC_InvoiceXmlWriter – ‘+e.getMessage()+’nnnn’);
    //log exception in error log

    I am getting “14:05:48.0 (85235474)|EXCEPTION_THROWN|[126]|System.CalloutException: Callout loop not allowed” exception. I have mentioned the line number in the second method written by “////Exception throws from the below line.”.

  15. Aneesh Avatar

    Hey Jitendra,
    I went through the post and it’s very informative. However, I had a unique requirement or rather interesting requirement with regard to the sales force deployment using ANT+ IntelliJ IDEA. I would want to discuss about it with you. How can I get in touch with you?
    since this post is quite old, I am. It sure if it’s still active. I hope you see my comment.

  16. Vidya Ramachandran Avatar
    Vidya Ramachandran

    I am unable to install ANT sucessfully. It prompts ANT is not recognized as internal or external command. How do I fix it. Please help.

  17. GK Avatar

    Hi Jitendra,
    I am using TFS for CI and CD. How can I get the recent validation id from the previous task. I want to pick it and use in next task using PS script
    My first step in TFS is deploy: checkonly=true
    after above task I want to use deployRecentValidation:. So in this I need to mention recentvalidationid manually in properties file. But I am trying to get the value in TFS variable after the first step. So that I can use it in 2 step.
    Any answer for this?

  18. shubhamgupta2621 Avatar

    Hi Shiva, i am not able to understand how you we can create dynamix package.xml? so we need to create package.xml for each deployment . or let say we have created a new template, and checked in. will this above solution automatic deploy that too?

  19. Sandeep Bala Avatar


    Can you please help me to how to run specific test class in Salesforce. Can you please provide the another way not like below mentioned way.


    Sandeep Bala

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Jitendra Zaa

Subscribe now to keep reading and get access to the full archive.

Continue Reading