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.

11

May I humbly recommend this bigass macro:

https://gist.github.com/bigassforce/af56ebda0354b273ab76

  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>
    <!--
     ! The MIT License (MIT)
     ! 
     ! Copyright (c) 2015 bigass.force.com
     ! 
     ! Permission is hereby granted, free of charge, to any person obtaining a copy
     ! of this software and associated documentation files (the "Software"), to deal
     ! in the Software without restriction, including without limitation the rights
     ! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     ! copies of the Software, and to permit persons to whom the Software is
     ! furnished to do so, subject to the following conditions:
     ! 
     ! The above copyright notice and this permission notice shall be included in
     ! all copies or substantial portions of the Software.
     ! 
     ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     ! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     ! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     ! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     ! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     ! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     ! THE SOFTWARE.
     !-->
    
  • 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 '15 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 '15 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 '15 at 11:16
  • Let us continue this discussion in chat. – Khyber Sep 5 '15 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 '15 at 23:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.