Running Apex Code through ExecuteAnonymous API

Running Apex Code through ExecuteAnonymous API

Hi Friends,

I was working on a POC wherein I need to run apex code through ExecuteAnonymous API like Workbench does. I got stuck on this one as it was not a straight forward task and I spend some time on research so wanna share my research with you guys.

First of all, ExecuteAnonymous call is available through Apex API & Tooling API.

  1. Apex API is available through SOAP protocol.
  2. Tooling API is available through SOAP as well as REST.

Note: For SOAP, You can generate WSDLs from API section of Salesforce.

WSDLs

Problem:

Catch over here is whenever you run these requests either through SOAP or REST, We won't get body/raw log for apex code executed. We only get following result:

{
  "line" : -1,
  "column" : -1,
  "compiled" : true,
  "success" : true,
  "compileProblem" : null,
  "exceptionStackTrace" : null,
  "exceptionMessage" : null
}

There is no straight forward way in REST API to get the body. For SOAP, We need to add a debugging header in request to get raw log in response.

<apex:DebuggingHeader>
    <apex:categories>
    <apex:category>Apex_code</apex:category>
    <apex:level>FINEST</apex:level>
    </apex:categories>
    <apex:debugLevel>DETAIL</apex:debugLevel>
  </apex:DebuggingHeader>

Full Request

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:apex="http://soap.sforce.com/2006/08/apex">
    <soapenv:Header>
      <apex:DebuggingHeader>
        <apex:categories>
        <apex:category>Apex_code</apex:category>
        <apex:level>FINEST</apex:level>
        </apex:categories>
        <apex:debugLevel>DETAIL</apex:debugLevel>
      </apex:DebuggingHeader>
      <apex:SessionHeader>                   
          <apex:sessionId>sessionId</apex:sessionId>
      </apex:SessionHeader>
    </soapenv:Header>
    <soapenv:Body>
      <apex:executeAnonymous>
          <apex:String>System.debug('Hello');</apex:String>
      </apex:executeAnonymous>
    </soapenv:Body>
</soapenv:Envelope>

Full Response

  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/08/apex" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
  <DebuggingInfo>
  <debugLog>34.0 APEX_CODE,FINEST
  Execute Anonymous: System.debug('Hello');
  01:53:57.042 (42323953)|EXECUTION_STARTED
  01:53:57.042 (42336750)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex
  01:53:57.042 (42750478)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:1
  01:53:57.042 (42867541)|STATEMENT_EXECUTE|[1]
  01:53:57.042 (42874614)|STATEMENT_EXECUTE|[1]
  01:53:57.042 (42882147)|HEAP_ALLOCATE|[1]|Bytes:5
  01:53:57.043 (43033648)|ENTERING_MANAGED_PKG|
  01:53:57.043 (43067036)|USER_DEBUG|[1]|DEBUG|Hello
  01:53:57.043 (43116911)|CODE_UNIT_FINISHED|execute_anonymous_apex
  01:53:57.044 (44702729)|EXECUTION_FINISHED</debugLog>
  </DebuggingInfo>
</soapenv:Header>
<soapenv:Body>
<executeAnonymousResponse>
  <result>
    <column>-1</column>
    <compileProblem xsi:nil="true"/>
    <compiled>true</compiled>
    <exceptionMessage xsi:nil="true"/>
    <exceptionStackTrace xsi:nil="true"/>
    <line>-1</line>
    <success>true</success>
  </result>
</executeAnonymousResponse>
</soapenv:Body>
</soapenv:Envelope>

As I mentioned above, there is no straight forward way to do this in REST API. This can be done in 4 Steps:

  1. Set Trace Flag : To log logs against your user

    Endpoint : /services/data/v34.0/tooling/sobjects/traceFlag
    Method : POST
    Post:
     {
      "ApexCode": "Finest",
      "ApexProfiling": "Error",
      "Callout": "Error",
      "Database": "Error",
      "ExpirationDate": "2015-09-11",
      "TracedEntityId": "00590000000tQBwAAM",
      "Validation": "Error",
      "Visualforce": "Error",
      "Workflow": "Error",
      "ScopeId": null,
      "System": "Error"
      }
    

    To know more about Trace Flag, go through this documentatation.

  2. Run your executeAnonymous call through API.

  3. Then, We need to make a query to get Id of raw log from ApexLog table. Run below query to get last log from user.

    SELECT Id FROM ApexLog WHERE Request = 'API' AND Location = 'Monitoring' AND Operation like '%executeAnonymous%' AND LogUserId='00590000000tQBwAAM' ORDER BY StartTime DESC, Id DESC LIMIT 1
    
  4. After getting Id, We need to make an another call for raw logs.

    Endpoint: /services/data/v29.0/sobjects/ApexLog/07L9000004qMsoiEAC/Body
    Method: GET
    
  5. (Optional) Remove trace flags from visibility.

If anyone has any questions about it, I would be glad to help!

Lakshay Katney Avatar

Lakshay Katney

Saleforce developer by profession but I like to work with various technologies.I blog about Force.com, Hybrid Apps, PhoneGap, AngularJS, BackboneJS, JavaScript in general. I am Angular & NodeJS fan.

Read More
Share this page
Top 15 Posts

    100%