8

I am looking to execute anonymous apex code thru ANT scripts.

But couldn't get started..

Appreciate if somebody can outline the process of doing this.

Thanks for your help.

1

1 Answer 1

11
  1. download the salesforce ant tool and extract it to /lib/salesforce_ant_34.0/

  2. then download the missing link http library and extract it to /lib/ml-ant-http-1.1.3/

  3. scaffold out your build.xml as follows, and look at the deploy target for example usage

     <project default="usage" basedir="." xmlns:sf="antlib:com.salesforce" xmlns:ml="org.missinglink.ant.task.http.HttpClientTask">
    
         <!-- Download from https://login.salesforce.com/dwnld/SfdcAnt/salesforce_ant_32.0.zip -->
         <taskdef uri="antlib:com.salesforce" classpath="lib/salesforce_ant_32.0/ant-salesforce.jar" />
    
         <!-- Download from https://code.google.com/p/missing-link/ -->
         <taskdef name="http" uri="org.missinglink.ant.task.http.HttpClientTask" classname="org.missinglink.ant.task.http.HttpClientTask" classpath="lib/ml-ant-http-1.1.3/ml-ant-http-1.1.3.jar"/>
    
         <property file="build.properties"/>
         <property environment="env"/>
    
         <target name="deploy" description="Deploys all package components to dev org">
             <!-- stop scheduled job -->
             <executeAnonymous username="${de.username}" password="${de.password}" serverurl="${de.serverurl}"><![CDATA[
                 for (SObject j : [SELECT Id FROM CronTrigger]) System.abortJob(j.Id);
             ]]></executeAnonymous>
    
             <!-- upload code -->
             <sf:deploy
                 username="${de.username}"
                 password="${de.password}"
                 serverurl="https://login.salesforce.com"
                 deployRoot="src"
             />
    
             <!-- restart scheduled job -->
             <executeAnonymous username="${de.username}" password="${de.password}" serverurl="${de.serverurl}"><![CDATA[
                 System.schedule('New Job', '0 0 * * * ?', new Job());
             ]]></executeAnonymous>
         </target>
    
         <macrodef name="executeAnonymous" description="Invoke ExecuteAnonymous using Salesforce Tooling API">
             <attribute name="username" description="Salesforce user name."/>
             <attribute name="password" description="Salesforce password."/>
             <attribute name="serverurl" description="Salesforce endpoint."/>
             <text name="apexcode"/>
             <sequential>
                 <!-- Login to populate serverUrl / sessionId / instance -->
                 <login username="@{username}" password="@{password}" serverurl="@{serverurl}" />
    
                 <!-- Execute using HTTP GET -->
                 <ml:http url="${instance}/services/data/v34.0/tooling/executeAnonymous" method="GET" outfile="lib/executeAnonymousResult.json"  statusProperty="loginResponseStatus">
                     <headers>
                         <header name="Authorization" value="Bearer ${sessionId}"/>
                     </headers>
                     <query>
                         <parameter name="anonymousBody" value="@{apexcode}"/>
                     </query>
                 </ml:http>
    
                 <!-- Fail on error -->
                 <loadfile property="executeAnonymousResult" srcFile="lib/executeAnonymousResult.json" />
                 <fail message="Execute Anonymous failed: ${executeAnonymousResult}">
                     <condition>
                         <resourcecontains resource="lib/executeAnonymousResult.json" substring="&quot;success&quot;:false" />
                     </condition>
                 </fail>
    
                 <!-- Show output -->
                 <echo message="${executeAnonymousResult}" />
             </sequential>
         </macrodef>
    
         <macrodef name="login" description="Login to salesforce and populate serverUrl / sessionId / instance">
             <attribute name="username" description="Salesforce user name."/>
             <attribute name="password" description="Salesforce password."/>    
             <attribute name="serverurl" description="Salesforce endpoint."/>    
             <sequential>
                 <!-- Obtain Session Id via Login SOAP service -->
                 <ml:http url="@{serverurl}/services/Soap/c/34.0" method="POST" failonunexpected="false" outfile="lib/loginResult.xml" statusProperty="loginResponseStatus">
                     <headers>
                         <header name="Content-Type" value="text/xml"/>
                         <header name="SOAPAction" value="login"/>
                     </headers>
                     <entity><![CDATA[
                         <env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
                             <env:Body>
                                 <sf:login xmlns:sf='urn:enterprise.soap.sforce.com'>
                                     <sf:username>@{username}</sf:username>
                                     <sf:password>@{password}</sf:password>
                                 </sf:login>
                             </env:Body>
                         </env:Envelope>]]>
                     </entity>
                 </ml:http>
    
                 <!-- Fail on error -->
                 <loadfile property="loginResult" srcFile="lib/loginResult.xml" />
                 <fail message="Login failed: ${loginResult}">
                     <condition>
                         <resourcecontains resource="lib/loginResult.xml" substring="faultcode" />
                     </condition>
                 </fail>
    
                 <!-- Parse response into properties -->
                 <xmlproperty file="lib/loginResult.xml" />
                 <echo file="lib/serverUrl.txt" message="${soapenv:Envelope.soapenv:Body.loginResponse.result.serverUrl}" />
                 <echo file="lib/sessionId.txt" message="${soapenv:Envelope.soapenv:Body.loginResponse.result.sessionId}" />
                 <echo file="lib/instance.txt" message="${soapenv:Envelope.soapenv:Body.loginResponse.result.serverUrl}" />
                 <replaceregexp file="lib/instance.txt" match="(https://[^/]+)/.*" replace="\1" />
                 <loadfile property="sessionId" srcFile="lib/sessionId.txt" />
                 <loadfile property="instance" srcFile="lib/instance.txt" />
             </sequential>
         </macrodef>
    
     </project>
    
5
  • Hi bigassforce, this is definitely a piece of cake to me, but still i am not able to understand. Can you tell me where to place the code?
    – Khyber
    Sep 5, 2015 at 0:47
  • Ok sure, i am new to using ANT for deployment, have been retrieving/deploying components but didn't deploy apex. Everytime i try, it throws this error BUILD FAILED The following error occurred while executing this line: C:\apache-ant-1.9.6-bin\apache-ant-1.9.6\lib\ant-salesforce.xml:20: taskdef class org.missinglink.ant.task.http.HttpClientTask cannot be found using the classloader AntClassLoader[]
    – Khyber
    Sep 5, 2015 at 11:08
  • i haven't changed anything, i just used as you gave me, they are as : xmlns:sf="antlib:com.salesforce" xmlns:ml="org.missinglink.ant.task.http.HttpClientTask
    – Khyber
    Sep 5, 2015 at 11:16
  • Let us continue this discussion in chat.
    – Khyber
    Sep 5, 2015 at 17:31
  • 3
    Its easy to post an answer, but not that easy to spend time to make someone understand the answer. Bigassforce is good at it. Kudos Sir. Really appreciate all your time into this.
    – Khyber
    Sep 5, 2015 at 23:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .