I've been doing some work on communication between our company's learning management system and salesforce so that we can tie a client's training into their customer and partner management systems. I had done a little work with salesforce in the past, mostly on accessing data via their REST API, but this integration involved creating a new schema in the client's salesforce database as well as creating some Apex functions (salesforce's platform language) to run periodically on their system.
Background
Salesforce's force.com platform is an interesting system. It centers around a multitenant architecture which focuses on applications with web-based front ends and a relational database back end. It can create fairly complex permissions hierarchies, which can be useful for enterprise clients, and is fairly well documented. They encourage the idea that one can create applications on force.com without writing code (or at least very little code) and therefore focus on visual application design tools, including a visual schema editor for the relational database.
Anyone can get a free developer account to play around with the force.com platform.
The Problem
Deployment can be tricky depending on the client. Our client had an Enterprise Edition account, which meant that we could develop a solution within their sandbox and use a change set for deployment to production. That was the model the client typically used, and we thought it would be prudent to adapt to their deployment strategy. It also allowed the client to perform whatever testing a validation their business processes required.
However, it is often better for us to do work in our own developer edition instance prior to deploying to the client sandbox. This allows us to run experiments, we don't have to worry about permissions, and we don't have to worry about losing access to our work. It is possible to create a managed package of our application, but a developer edition can only have one managed package.
Another aspect of the development which I found troubling was the visual programming aspect. I wanted to be able to save our deployment as a script which we could easily tweak and put into our revision control system. The alternative for our visually programmed system was to place screen shots in a wiki so that we could reproduce the work later. This was not a good solution.
The Metadata API
Of course force.com has a way of representing this visual data internally, and they expose it programmatically using the metadata API. This seemed to be exactly what we needed to record and recreate the changes we were making, but it's a fairly complex API and it would have required us to write a tool to exploit the API. It turns out, however, that someone has already written that tool! It's the Force.com Migration Tool.
Using the Force.com Migration Tool
The Force.com migration tool integrates into Apache
Ant through the installation of a salesforce specific
ant jar. All I had to do under OS X was copy this jar into
/usr/share/ant/lib
and I was ready to go.
You need a build.properties
file, which specifies your username, password,
and the login url. An example is shown below:
# build.properties
#
# Specify the login credentials for the desired Salesforce organization
sf.username = USERNAME GOES HERE
sf.password = PASSWORD GOES HERE
# 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
You also need to setup a build.xml
file which is in the typical style of an
ant build file. Be sure to include your build.properties
file. I include a
retrieve
target to retrieve the data from my environment, and a deploy
target to deploy the data. My build.xml
file looks like this:
<project name="Backup salesforce changes" default="retrieve" basedir="." xmlns:sf="antlib:com.salesforce">
<property file="build.properties"/>
<property environment="env"/>
<target name="retrieve">
<mkdir dir="retrieveMetadata"/>
<sf:retrieve username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" retrieveTarget="retrieveMetadata" unpackaged="package.xml"/>
</target>
<target name="deploy">
<sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="deployMetadata"/>
</target>
</project>
Another file, the package.xml
file tells the migration tool what data to
retrieve. This XML document contains a list of metadata types and the members
to be retrieved from each type. In some cases you can use the *
wildcard to
retrieve all the metadata objects of that type. In the case of this
application, my package.xml
file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>User_Certificate__c</members>
<name>CustomObject</name>
</types>
<types>
<members>Contact</members>
<name>CustomObject</name>
</types>
<types>
<members>User</members>
<name>CustomObject</name>
</types>
<types>
<members>Contact-Contact Layout</members>
<members>Contact-Partner Contact Layout</members>
<name>Layout</name>
</types>
<types>
<members>REST_Moodle_BatchScheduler</members>
<name>ApexClass</name>
</types>
<version>29.0</version>
</Package>
Note that you can check the list of metadata types to see what they are named and if they accept wildcards.
Running the
ant retrieve
command put the relevant metadata into the retrieveMetadata
directory. I
could then copy it to the deployMetadata
directory for deployment. I could
also edit the metadata if need be. I could also put the entire thing under
revision control so that we could track changes and make bug reports against
the repository.
When we were ready to deploy to the sandbox, I just put the credentials and
login of the sandbox into my build.properties
file and ran the
ant deploy
command.
More information
For more information, please visit the following sites: