ANT MIGRATION TOOL
Prerequisite:
JDK 1.7 or above
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
ANT Installation:
Step 1:
Download ANT from apache official website. http://ant.apache.org/bindownload.cgi
Step 2:
Set Environment variable "ANT_HOME". The path should
be set till bin from the location where ANT is installed as shown above.
Set Environment variable "JAVA_HOME". The path should be set till bin from the location where JAVA is installed as shown below.
NOTE: Java must be there in Program Files(X86)
Download "Force.com Migration tool"
https://developer.salesforce.com/docs/atlas.en-us.daas.meta/daas/forcemigrationtool_install.htm
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.
Step 4:
Check whether ANT is installed or not properly by running command “ant -version“.
It might
be possible that you receive a message which says unable to find tools.jar.
You can
copy this jar from “JDK/lib/tools.jar” to “JRE/lib” folder.
Step 5:
If you still get error like
'ANT' is not recognized as an internal or external command, operable program or batch file.
You can Test the Path in this way:
Type the following in the Command Prompt:
Note: If ANT is properly working
this way, Restart the
System
In "sample" folder (of salesforce_ant_41.0) we can find
· build.properties
·
build.xml
· package.xml
To start with deployment using ANT, we will need “build.xml” and “build.properties” file.
As there is no need of “build.properties” however it’s 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.
Build.properties:
To retrieve or deploy metadata components, you need to edit build.properties to point to a Salesforce org.
1.
Go to the location
where you extracted the Force.com
Migration Tool files and open the sample subdirectory.
2. Open build.properties in a text editor and do either of the following.
• To use a username and password for login, substitute a valid Salesforce username and password.
If you’re using a security token, paste the 25-digit token value at the end of your password.
#
build.properties
# Specify
the login credentials for the desired
Salesforce organization sf.username = <User Name>
sf.password = <Password/Password+Security Token>
#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>
# 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://login.salesforce.com sf.maxPoll = 20
# If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
• To use an active
Salesforce session for login,
uncomment the sf.sessionId property and substitute
a valid session ID. Also, make sure to comment out the sf.username and sf.password properties.
# build.properties
# Specify the
login credentials for the desired Salesforce organization sf.username = <User Name>
sf.password = <Password/Password+Security Token>
#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>
# 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://login.salesforce.com sf.maxPoll = 20
# If your network
requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
Following is the structure of “build.properties” file.
# build.properties
# Specify the
login credentials for the desired Salesforce organization sf.username = <User Name>
sf.password = <Password/Password+Security Token>
#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>
# 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://login.salesforce.com sf.maxPoll = 20
# If your network
requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
Structure of Package.xml:
The package.xml file is a project manifest that lists all the components you want to retrieve or deploy in a single request. You can retrieve or deploy only a single package at a time.
Full Name :
The name
of the server-side package to deploy into. If the field is omitted, components will not be
assigned to a package when deployed, and will be in the unpackaged package.
This field is not used for
retrieve.
<?xml version="1.0"
encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>sample</fullName>
<types>
<members>*</members>
<name>ApexTriggers</name>
</types>
<version>41.0</version>
</Package>
Types:
<?xml version="1.0"
encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>sample</fullName>
<types>
<members>*</members>
<name>ApexTriggers</name>
</types>
<version>41.0</version>
</Package>
Members:
<?xml version="1.0"
encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>sample</fullName>
<types>
<members>*</members>
<name>ApexTriggers</name>
</types>
<version>41.0</version>
</Package>
Name:
Contains the type of the component, for example CustomObject or Profile. There is one name defined for each component type in the directory. This is a child element of <types>.
<?xml version="1.0"
encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>sample</fullName>
<types>
<members>*</members>
<name>ApexTriggers</name>
</types>
<version>41.0</version>
</Package>
Version:
The Metadata API version number
of the files being retrieved or deployed. When deploying, all the files must conform to the same version of the Metadata API.
<?xml version="1.0"
encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>sample</fullName>
<types>
<members>*</members>
<name>ApexTriggers</name>
</types>
<version>41.0</version>
</Package>
Some metadata components are sub-components of another component. This means you must dot-qualify the sub-component with the parent component name.
The following metadata components are defined as part of an
object:
• Picklist
• RecordType
• Weblink
• ValidationRule
build.xml:
<project name="Sample usage
of Salesforce Ant tasks" default="test" basedir="." xmlns:sf="antlib:com.salesforce">
<!--Points and loads build.properties-->
<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. -->
Refering your org credentials.
<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="../ant-salesforce.jar" />
</classpath>
</taskdef>
<!-- Test out deploy
and retrieve verbs
for package 'mypkg'
-->
<target name="test">
<!-- Upload the contents
of the "mypkg" package -->
<sf:deploy
username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="mypkg" rollbackOnError="true"/>
<mkdir dir="retrieveOutput"/>
<!-- Retrieve the contents into another directory -->
<sf:retrieve
username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveOutput" packageNames="MyPkg"/>
</target>
<!-- Retrieve an unpackaged set of
metadata from your org -->
<!-- The file unpackaged/package.xml lists what is to be retrieved -->
<target
name="retrieveUnpackaged">
<mkdir dir="retrieveUnpackaged"/>
<!-- Retrieve the contents into another directory -->
<sf:retrieve
username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" retrieveTarget="retrieveUnpackaged" unpackaged="unpackaged/package.xml"/>
</target>
<!-- Retrieve all the items
of a
particular metadata type -->
<target
name="bulkRetrieve">
<sf:bulkRetrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" metadataType="${sf.metadataType}" retrieveTarget="retrieveUnpackaged"/>
</target>
<!-- Retrieve metadata
for all the packages specified under packageNames -->
<target name="retrievePkg">
<sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" retrieveTarget="retrieveOutput" packageNames="${sf.pkgName}"/>
</target>
<!-- Deploy
the unpackaged set of metadata retrieved with retrieveUnpackaged and run tests
in this organization's namespace only-->
<target name="deployUnpackaged">
<sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="retrieveUnpackaged" rollbackOnError="true"/>
</target>
<!-- Deploy
a zip of metadata files to the org -->
<target name="deployZip">
<sf:deploy username="${sf.username}"
password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" zipFile="${sf.zipFile}" pollWaitMillis="1000" rollbackOnError="true"/>
</target>
<!-- Shows deploying code & running
tests for code in directory
-->
<target
name="deployCode">
<!-- Upload the contents of the "codepkg" directory, running the tests for just 1 class
-->
<sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" deployRoot="codepkg" testLevel="RunSpecifiedTests" rollbackOnError="true">
<runTest>SampleDeployClass</runTest>
</sf:deploy>
</target>
<target
name="deployCodeNoTestLevelSpecified">
<sf:deploy
username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" rollbackOnError="true"/>
</target>
<!-- Shows deploying code and running
tests only within
the org namespace -->
<target
name="deployCodeRunLocalTests">
<sf:deploy username="${sf.username}"
password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" deployRoot="codepkg"
rollbackOnError="true" testlevel="RunLocalTests"/>
</target>
<target name="undeployCode">
<sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="removecodepkg"/>
</target>
<!-- Shows retrieving code; only succeeds
if done after deployCode -->
<target name="retrieveCode">
<!-- Retrieve the contents listed in the file codepkg/package.xml into the codepkg
directory -->
<sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}"
serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" retrieveTarget="codepkg" unpackaged="codepkg/package.xml"/>
</target>
<!-- Shows deploying code,
running all tests, and running
tests (1 of which
fails), and logging.
-->
<target name="deployCodeFailingTest">
<!-- Upload the contents of the "codepkg" package, running all tests -->
<sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
maxPoll="${sf.maxPoll}" deployRoot="codepkg" testLevel="RunAllTestsInOrg"
rollbackOnError="true" logType="Debugonly"/>
</target>
<target name="deployCodeCheckOnly">
<sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" checkOnly="true"/>
</target>
<!-- Shows
quick deployment of recent validation. Set the property
sf.recentValidationId to your
recent check only deployment Id -->
<target name="quickDeploy">
<sf:deployRecentValidation username="${sf.username}"
password="${sf.password}" sessionId="${sf.sessionId}"
serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" recentValidationId="${sf.recentValidationId}"/>
</target>
<!-- Shows
cancel deployment of deploy request
either pending or in progress.
Set property sf.requestId to Id of pending or in progress
deploy request -->
<target name="cancelDeploy">
<sf:cancelDeploy username="${sf.username}"
password="${sf.password}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" requestId="${sf.requestId}"/>
</target>
<target name="listMetadata">
<sf:listMetadata username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" metadataType="${sf.metadataType}"/>
</target>
<target
name="describeMetadata">
<sf:describeMetadata username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"/>
</target>
</project>
Username:
Required if sessionId isn’t specified. The Salesforce username used for login. The username associated with this connection must have the “Modify All Data” permission. Typically, this permission is enabled only for System Administrator users.
Optional. The Salesforce server URL (if blank, defaults to login.salesforce.com). To connect to a sandbox instance, change this value to test.salesforce.com. serverurl retrieveTarget Required.
The root of the directory structure into which
the metadata files are retrieved.
apiVersion:
Optional. Defaults to 10000. The number of milliseconds to wait between attempts when polling for results of the retrieve request. The client continues to poll the server up to the limit defined by maxPoll.
maxPoll:
Optional. Defaults to 200. The number of times to poll the server for the results of the retrieve request. The wait time between successive poll attempts is defined by pollWaitMillis.
Trace:
Optional. Defaults to false. Prints
the SOAP requests and responses to the console. This option shows
the user’s password in plain
text during login.
Required if packageNames is not specified. The path and name of a file manifest that specifies the components to retrieve. Specify either unpackaged or packageNames, but not both.
unzip:
Optional. Defaults to true. If set to true, the retrieved components are unzipped. If set to false, the retrieved components are saved as a zip file in the retrieveTarget directory.
We can run the build.xml code using the command:
Example:
ant deployCode ant retrieveCode
Delete components from Salesforce Organization using “destructiveChanges.xml” :
<!-- Get all settings like Server Path, username and passwords from "build.properties" file -->
<property file="build.properties"/>
<property environment="env"/>
<target name="SFDCFetch"><!-- -->
<!-- Sequence
3 - Deploy to Target System,
Package.xml is present
in Src folder -->
<sf:deploy username="${sf1.username}" password="${sf1.password}" serverurl="${sf.serverurl}" deployroot="Src">
<sf:deploy username="${sf1.username}" password="${sf1.password}" serverurl="${sf.serverurl}" deployroot="Delete">
<target name="proxy">
<property name="proxy.host" value=" ProxyURL " />
<property name="proxy.port" value="1234" />
<property name="proxy.user" value="UserName" />
<property name="proxy.pwd" value="Password" />
</target>
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 -->
<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" />
s</target>
"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.
Common Migration Issues:
There are a number of common issues
you may run into when migrating metadata and deploying changes. These issues can be grouped into three categories:
• Metadata — Special
considerations for dealing
with certain metadata
components
• Connectivity — Problems connecting to an organization or polling for results
• Testing and Code Coverage
— Testing Apex before deployment
Common Metadata Issues :
The most common metadata issues are detailed below:
• Retrieving custom fields
on standard objects — When you use the wildcard
symbol in package.xml, to retrieve all objects,
you will not retrieve standard objects, or custom fields on standard
objects.
• Profiles or permission sets and field-level security — The contents of
a retrieved profile or permission set
depend on the other contents of the retrieve request. For example, field- level security for fields included in
custom objects are returned at the same time as profiles or permission sets.
• Understanding packages — Packages are used to bundle related components
so they can be shared with multiple
organizations, or distributed on Force.com AppExchange. Managed packages are packages that can be upgraded
in the installer's organization. They differ from unmanaged packages in that some components are locked, in order to permit upgrades. Metadata components
that are not in any package can be accessed with the unpackaged attribute of sf:retrieve and sf:deploy.
• Workflow — A .workflow file is a container for the
individual workflow components associated with an object, including WorkflowAlert,
WorkflowFieldUpdate, WorkflowOutboundMessage, WorkflowRule, and WorkflowTask.
•
Retrieving or deploying
components that depend on an object definition — The following metadata components are dependent on a particular
object for their definition: CustomField,
Picklist, RecordType, Weblink, and ValidationRule. This means you must dot- qualify
the component name with the object name in
package.xml, and may not use the wildcard symbol.
•
Personal folders — Users
personal folders, for both reports and documents, are not exposed
in the Metadata API. To migrate
reports or documents you must move them to a
public folder.
Connection Problems :
The most common connection problems are detailed below:
• Request timed out
When you retrieve
or deploy metadata, the request is sent
asynchronously, meaning that the
response is not returned immediately. Because these calls are asynchronous, the server will
process a deploy()
to completion even if
the Force.com Migration Tool times out. If the deploy succeeds, the changes will be committed
to the server. If the deploy fails after 26 timing out, there is no way to retrieve the error message from the server.
For this reason, it is important to tune
your pollWaitMillis and maxPoll parameters if you receive time-out errors:
pollWaitMillis : The number of milliseconds to wait between polls for retrieve/deploy results. The default value is 10000
milliseconds (ten seconds). For long-running processes, increase this number to reduce the total number of polling
requests, which count against your daily API limits.
maxPoll
: The number of polling attempts
to be performed before aborting. The default
value is 200. When combined with the default value of pollWaitMillis
(10000), this means the Force.com
Migration Tool will give the server process a total of 2,000 seconds (33
minutes) to complete before timing
out. The total time is computed as 200 poll attempts, waiting 10 seconds between
each.
·
Invalid username, password, security token; or
user locked out - This error
indicates a problem with the credentials in build.properties:
Username : Verify that your username is correct on
this account. When connecting to a sandbox instance
your sandbox name is appended to your username. For example, if your production username is foo@salesforce.com, and one of your
sandboxes is called bar, then your sandbox username is foo@salesforce.com.bar.
Password : Verify that your password is correct for this account. Note that you security token
is appended to the
end of your pasword.
Security token : The security token is
a 25-digit string appended to your
password. To reset your security
token, go to the Reset My
Security Token page in your
personal settings.
Locked out : If you
unsuccessfully attempt to log into an organization too many times, you may be temporarily locked out. The number of times you may fail to connect and the lockout duration depend
on your organization settings. Either contact your administrator to have the
lock removed, or wait until the lockout period expires.
Connection mismatch between sandbox
and production : If all of your connection credentials in
build.properties are correct, you may have a URL mismatch. The server URL is
different for sandbox and production
environments. In build.properties, the sf.serverurl value for production is https://login.salesforce.com.
For sandbox environments, the value is https://test.salesforce.com.
• Proxy settingsIf you connect through a proxy, you will need to follow
the Ant Proxy Configuration instructions.
Testing in Apex:
When you deploy
to a production organization and don’t specify the tests to
run, every unit test in your organization namespace is
executed. Before you deploy Apex, the following must be true:
·
At least 75% of your Apex code must be covered by unit tests,
and all of those tests must
complete successfully. Note the
following. 27 Common
Migration Issues
·
When deploying Apex to a
production organization, each unit test in your organization namespace is executed by default.
·
Calls to System.debug are not counted
as part of Apex
code coverage.
· Test methods and test classes are not counted as part of Apex code coverage.
·
While only 75% of your Apex
code must be covered by tests, your focus shouldn't be on the percentage of code that is covered.
Instead, you should make sure that every use case of your application is covered, including positive and
negative cases, as well as bulk and single records. This should lead to 75% or
more of your code being
covered by unit tests.
Every trigger must have some test coverage.
All classes and triggers must compile
successfully. Salesforce recommends that you write tests for the following:
Single action
Test to verify that a single
record produces the correct, expected result.
Bulk actions
Any Apex code, whether a trigger, a class or an extension, may be invoked for 1 to 200
records. You must test not only
the single record case, but the bulk cases as well.
Positive behavior
Test to verify
that the expected behavior occurs through every expected permutation, that
is, that the user filled out everything
correctly and did not go past the limits.
Negative behavior
There are likely limits to your
applications, such as not being able to add a future date, not being able to specify a negative
amount, and so on. You must test for the negative case and verify that
the error messages are correctly produced as well as for the positive, within the limits
cases.
Restricted
user
Test whether a user with restricted access
to the sObjects used in your code sees the expected behavior. That is, whether they can run
the code or receive
error messages.
0 Comments