Newer Version Available
SOAP Calls
To access the Tooling API WSDL, from Setup, enter API in the Quick Find box, then select API and click Generate Tooling WSDL.
Like the Salesforce SOAP API, Tooling API uses the following calls.
- create()
- Adds one or more records to your organization’s data.
- delete()
- Deletes one or more records from your organization’s data.
- describeLayout()
- Retrieve metadata about page layouts for a specified SOjbect.
- describeGlobal()
- Lists the available Tooling API objects and their metadata.
- describeSObjects()
- Describes the metadata (field list and object properties) for the specified
object or array of objects.
Call describeGlobal() to retrieve a list of all Tooling API objects for your organization, then iterate through the list and use describeSObjects() to obtain metadata about individual objects.
- describeValueType()
- Describes the metadata for a specified namespace and value type.
- describeWorkitemActions()
- Describes which actions are available for a specified work item.
- executeanonymous(string apexcode)
- Executes the specified block of Apex anonymously and returns the result.
- query()
- Executes a query against a Tooling API object and returns data that matches the specified criteria.
- queryMore()
- Retrieves the next batch of objects from a query().
- retrieve()
- Retrieves one or more records based on the specified IDs.
- runTests() and runTestsAsynchronous()
- Executes test methods in the specified classes. Running tests asynchronously allows methods to process in parallel, cutting down your test run times. For example code, see ApexTestQueueItem.
- search()
- Search for records that match a specified text string.
- update()
- Updates one or more existing records in your organization’s data.
- upsert()
- Creates records and updates existing records; uses a custom field to determine the presence of existing records.
SOAP Headers
The SOAP headers available in the Tooling API WSDL are described in SOAP Headers for Tooling API.
Examples
These examples use Java, but you can use any language that supports Web services.
1String classBody = "public class Messages {\n"
2 + "public string SayHello() {\n"
3 + " return 'Hello';\n" + "}\n"
4 + "}";
5
6 // create an ApexClass object and set the body
7 ApexClass apexClass = new ApexClass();
8 apexClass.Body = classBody;
9 ApexClass[] classes = { apexClass };
10
11 // call create() to add the class
12 SaveResult[] saveResults = sforce.create(classes);
13 for (int i = 0; i < saveResults.Length; i++)
14 {
15 if (saveResults[i].success)
16 {
17 Console.WriteLine("Successfully created Class: " +
18 saveResults[i].id);
19 }
20 else
21 {
22 Console.WriteLine("Error: could not create Class ");
23 Console.WriteLine(" The error reported was: " +
24 saveResults[i].errors[0].message + "\n");
25 }
26 }The IsCheckOnly parameter on ContainerAsyncRequest indicates whether an asynchronous request compiles code but doesn’t execute or save it (true), or compiles and save the code (false).
1String updatedClassBody = "public class Messages {\n"
2 + "public string SayHello(string fName, string lName) {\n"
3 + " return 'Hello ' + fName + ' ' + lName;\n" + "}\n"
4 + "}";
5
6 //create the metadata container object
7 MetadataContainer Container = new MetadataContainer();
8 Container.Name = "SampleContainer";
9
10 MetadataContainer[] Containers = { Container };
11 SaveResult[] containerResults = sforce.create(Containers);
12 if (containerResults[0].success)
13 {
14 String containerId = containerResults[0].id;
15
16 //create the ApexClassMember object
17 ApexClassMember classMember = new ApexClassMember();
18 //pass in the class ID from the first example
19 classMember.ContentEntityId = classId;
20 classMember.Body = updatedClassBody;
21 //pass the ID of the container created in the first step
22 classMember.MetadataContainerId = containerId;
23 ApexClassMember[] classMembers = { classMember };
24
25 SaveResult[] MembersResults = sforce.create(classMembers);
26 if (MembersResults[0].success)
27 {
28 //create the ContainerAsyncRequest object
29 ContainerAsyncRequest request = new ContainerAsyncRequest();
30 //if the code compiled successfully, save the updated class to the server
31 //change to IsCheckOnly = true to compile without saving
32 request.IsCheckOnly = false;
33 request.MetadataContainerId = containerId;
34 ContainerAsyncRequest[] requests = { request };
35 SaveResult[] RequestResults = sforce.create(requests);
36 if (RequestResults[0].success)
37 {
38 string requestId = RequestResults[0].id;
39
40 //poll the server until the process completes
41 QueryResult queryResult = null;
42 String soql = "SELECT Id, State, ErrorMsg FROM ContainerAsyncRequest where id = '" + requestId + "'";
43 queryResult = sforce.query(soql);
44 if (queryResult.size > 0)
45 {
46 ContainerAsyncRequest _request = (ContainerAsyncRequest)queryResult.records[0];
47 while (_request.State.ToLower() == "queued")
48 {
49 //pause the process for 2 seconds
50 Thread.Sleep(2000);
51
52 //poll the server again for completion
53 queryResult = sforce.query(soql);
54 _request = (ContainerAsyncRequest)queryResult.records[0];
55 }
56
57 //now process the result
58 switch (_request.State)
59 {
60 case "Invalidated":
61 break;
62
63 case "Completed":
64 //class compiled successfully
65 //see the next example on how to process the SymbolTable
66 break;
67
68 case "Failed":
69 . . break;
70
71 case "Error":
72 break;
73
74 case "Aborted":
75 break;
76
77 }
78 }
79 else
80 {
81 //no rows returned
82 }
83 }
84 else
85 {
86 Console.WriteLine("Error: could not create ContainerAsyncRequest object");
87 Console.WriteLine(" The error reported was: " +
88 RequestResults[0].errors[0].message + "\n");
89 }
90 }
91 else
92 {
93 Console.WriteLine("Error: could not create Class Member ");
94 Console.WriteLine(" The error reported was: " +
95 MembersResults[0].errors[0].message + "\n");
96 }
97 }
98 else
99 {
100 .. Console.WriteLine("Error: could not create MetadataContainer ");
101 Console.WriteLine(" The error reported was: " +
102 containerResults[0].errors[0].message + "\n");
103 }
104 }To access Apex class and trigger data in a structured format, use a SymbolTable.
1//use the ID of the class from the previous step
2 string classId = "01pA00000036itIIAQ";
3 QueryResult queryResult = null;
4 String soql = "SELECT ContentEntityId, SymbolTable FROM ApexClassMember where ContentEntityId = '" + classId + "'";
5
6 queryResult = sforce.query(soql);
7 if (queryResult.size > 0)
8 {
9 ApexClassMember apexClass = (ApexClassMember)queryResult.records[0];
10 SymbolTable symbolTable = apexClass.SymbolTable;
11
12 foreach (Method _method in symbolTable.methods)
13 {
14 //here's the SayHello method
15 String _methodName = _method.name;
16
17 //is the method Global, Public or Private?
18 String _methodVisibility = _method.visibility.ToString();
19
20 //get the method's return type
21 string _methodReturnType = _method.returnType;
22
23 //get the fName & lName parameters
24 foreach (Parameter _parameter in _method.parameters)
25 {
26 string _paramName = _parameter.name;
27 string _parmType = _parameter.type;
28 }
29 }
30 }
31 else
32 {
33 //unable to locate class
34 }To add checkpoints to your code for debugging, use ApexExecutionOverlayAction.
1//use the ID of the class from the first sample.
2 string classId = "01pA00000036itIIAQ";
3
4 ApexExecutionOverlayAction action = new ApexExecutionOverlayAction();
5 action.ExecutableEntityId = classId;
6 action.Line = 3;
7 action.LineSpecified = true;
8 action.Iteration = 1;
9 action.IterationSpecified = true;
10 ApexExecutionOverlayAction[] actions = { action };
11
12 SaveResult[] actionResults = sforce.create(actions);
13 if (actionResults[0].success)
14 {
15 // checkpoint created successfully
16 }
17 else
18 {
19 Console.WriteLine("Error: could not create Checkpoint ");
20 Console.WriteLine(" The error reported was: " +
21 actionResults[0].errors[0].message + "\n");
22 }