Saturday, March 16, 2013

Ant Deploy to permanently remove custom objects

Ant and Force.com Migration tool (ant-salesforce.jar) are very powerful command line tools to manage deployments in salesforce.

I have been using this for a long time and it has proved very productive for deployment tasks. Recently I was trying to remove custom objects from one of my developer org using migration tool when I faced a problem. When we delete a object from salesforce user interface it is not deleted permanently. It remain there in list of "Deleted objects" and you can undelete it. I wanted to delete my objects permanently as those were not needed. Salesforce Ant Deploy task has an attribute "purgeOnDelete" which is expected to delete custom objects permanently. But when I tried to use this I got following error:

sf:deploy doesn't support the "purgeOnDelete" attribute.

As per salesforce documentation if we set purgeOnDelete to true, the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin. Instead, they become immediately eligible for deletion.

But this feature doesn't work as documented. So Let's see how we are going to overcome this. If you are new to Force.com Migration tool refer salesforce documentation for getting started with this fantastic tool. I am expecting that you have prior knowledge of Salesforce Migration tool.


Step 1. First step it to make purgeOnDelete available for use. For this we have to extend DeployTask class from com.salesforce.ant package that comes in ant-salesforce.jar. Here are detailed steps to do this and create a new "DeployPurge.jar"

  1. Start Eclipse and select File | New | Java Project. In New Java Project dialog box enter name of your project and optionally Location. Click "Next".

  2. Click "Libraries" tab on next screen.
  3. Click "Add External JARs..." button and locate ant.jar and ant-salesforce.jar. You can find ant.jar and ant-salesforce.jar in lib directory under Ant installation folder. If you don't find ant-salesforce.jar in lib folder you need to follow instruction in Force.com Migration Tool Guide to install Ant and Salesforce migration tool on your machine.
  4. Click "Open", on next screen click "Finish"
  5. Right Click src folder in eclipse package explorer and select New | Class
  6. Enter "com.salesforce.ant" in package field and "DeployPurge" in name field.
  7. Replace your class code with following code.
    package com.salesforce.ant;
    import com.salesforce.ant.DeployTask;
    public class DeployPurge extends DeployTask
    {
        public DeployPurge()
        {
            this.deployOptions.setPurgeOnDelete(false);
        }
    
        public void setPurgeOnDelete(boolean purgeOnDelete) 
        {
            this.deployOptions.setPurgeOnDelete(purgeOnDelete);
        }
    }
    
  8. We have simply created a new class by extending DeployTask class and created a new method in this to set purgeOnDelete.
  9. Now we need to export our project as a jar file. Right click on your project in package explorer and select "Export"
  10. Expend Java and select "JAR file", click next. Make selection as per below screenshot.

  11. Click Finish. Our customized jar file is ready. Place this jar in ant\lib directory where you already have ant-salesforce.jar file.
Step 2. Next step is to use our jar file and purgeOnDelete option. We need following files in a folder.
build.xml
build.properties
removecode\package.xml
removecode\destructiveChanges.xml

build.xml
<project basedir="." default="undeploy" name="Sample usage of DeployPurge" xmlns:sf="antlib:com.salesforce">
    <property file="build.properties" />
    <property environment="env" />
    <taskdef classname="com.salesforce.ant.DeployPurge" name="deploypurge"/>
    <target name="undeploy">
     <deploypurge username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployroot="removecode"  purgeondelete="true" />
     </target>
  </project>
build.properties
# build.properties
# Specify the login credentials for the desired Salesforce organization
sf.username = username@mydomain.com
sf.password = passwordtoken
# 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
package.xml
<package xmlns="http://soap.sforce.com/2006/04/metadata">
    <version>25.0</version>
</package>
destructiveChanges.xml
<package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>testobj__c</members>
        <name>CustomObject</name>
    </types>
    <version>25.0</version>
</package>

In build.properties file enter your salesforce username, password and security token.

In destructiveChanges.xml repalce testobj__c with your object name. You can repeat this <members> tag multiple time to delete multiple objects in one go.


Step 3. Next step is to fire the ant task from command line. Use this step carefully as this will delete object and all its data and you will not be able to recover it. 

  1. Start command prompt and move to folder where you have created above files.
  2. Run following command : ant undeploy
  3. Login to salesforce and check that your objects are delete permanently.
You can find source code for all this on github.

3 comments:

  1. where is the DeployTask class in here? can you please send me a note on how to write DeployTask class at mdreshmi@gmail.com

    ReplyDelete
    Replies
    1. https://github.com/forcemantis/purgeOnDelete

      Delete
  2. The Deploytask class is not mentioned in the link and also the error for the DeployPurge class is

    The field DeployTask.deployOptions is not visible--------------------this.deployOptions.setPurgeOnDelete(false);
    The nested type DeployPurge cannot hide an enclosing type-----------------public class DeployPurge


    package com.saleforce.ant;
    import com.salesforce.ant.DeployTask;
    public class DeployPurge extends DeployTask{
    public DeployPurge()
    {
    this.deployOptions.setPurgeOnDelete(false);
    }
    public class DeployPurge
    {
    public void setPurgeOnDelete(boolean purgeOnDelete)
    {
    this.deployOptions.setPurgeOnDelete(purgeOnDelete);
    }
    }
    }

    Please explain deploytask class. Appreciate your timely help!

    ReplyDelete