Newer Version Available
Use Tooling API with SOAP
Use SOAP API if you’re using a strongly typed language like Java that generates Web service client code. Tooling SOAP API is used just like the Salesforce SOAP API. For details on usage, syntax, and authentication, see the SOAP API Developer's Guide.
To access the Tooling API WSDL, from Setup, click and click Generate Tooling WSDL.
Like the Salesforce SOAP API, Tooling API uses the following calls.
| Call | Description |
|---|---|
| create() | Adds one or more records to your organization’s data. |
| delete() | Deletes one or more records from your organization’s data. |
| describeGlobal() | Lists the available Tooling API objects and their metadata. |
| describeSObjects() | Describes 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. |
| 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. |
| 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. |
Starting in API version 34.0, the following calls support the AllOrNoneHeader header: create(), update(), upsert(), and delete().
By default, if AllOrNoneHeader isn’t used, those calls can save a partial set of records for records with no errors (equivalent to AllOrNoneHeader=false). If AllOrNoneHeader is set to true, records are saved only when there are no failures in any record in the call.
Examples
These examples use Java, but you can use Tooling SOAP API in any language that supports Web services.
1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 String classBody = "public class Messages {\n"
18 + "public string SayHello() {\n"
19 + " return 'Hello';\n" + "}\n"
20 + "}";
21
22 // create an ApexClass object and set the body
23 ApexClass apexClass = new ApexClass();
24 apexClass.Body = classBody;
25 ApexClass[] classes = { apexClass };
26
27 // call create() to add the class
28 SaveResult[] saveResults = sforce.create(classes);
29 for (int i = 0; i < saveResults.Length; i++)
30 {
31 if (saveResults[i].success)
32 {
33 Console.WriteLine("Successfully created Class: " +
34 saveResults[i].id);
35 }
36 else
37 {
38 Console.WriteLine("Error: could not create Class ");
39 Console.WriteLine(" The error reported was: " +
40 saveResults[i].errors[0].message + "\n");
41 }
42 }
43The 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).
1swfobject.registerObject("clippy.codeblock-1", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 String updatedClassBody = "public class Messages {\n"
18 + "public string SayHello(string fName, string lName) {\n"
19 + " return 'Hello ' + fName + ' ' + lName;\n" + "}\n"
20 + "}";
21
22 //create the metadata container object
23 MetadataContainer Container = new MetadataContainer();
24 Container.Name = "SampleContainer";
25
26 MetadataContainer[] Containers = { Container };
27 SaveResult[] containerResults = sforce.create(Containers);
28 if (containerResults[0].success)
29 {
30 String containerId = containerResults[0].id;
31
32 //create the ApexClassMember object
33 ApexClassMember classMember = new ApexClassMember();
34 //pass in the class ID from the first example
35 classMember.ContentEntityId = classId;
36 classMember.Body = updatedClassBody;
37 //pass the ID of the container created in the first step
38 classMember.MetadataContainerId = containerId;
39 ApexClassMember[] classMembers = { classMember };
40
41 SaveResult[] MembersResults = sforce.create(classMembers);
42 if (MembersResults[0].success)
43 {
44 //create the ContainerAsyncRequest object
45 ContainerAsyncRequest request = new ContainerAsyncRequest();
46 //if the code compiled successfully, save the updated class to the server
47 //change to IsCheckOnly = true to compile without saving
48 request.IsCheckOnly = false;
49 request.MetadataContainerId = containerId;
50 ContainerAsyncRequest[] requests = { request };
51 SaveResult[] RequestResults = sforce.create(requests);
52 if (RequestResults[0].success)
53 {
54 string requestId = RequestResults[0].id;
55
56 //poll the server until the process completes
57 QueryResult queryResult = null;
58 String soql = "SELECT Id, State, ErrorMsg FROM ContainerAsyncRequest where id = '" + requestId + "'";
59 queryResult = sforce.query(soql);
60 if (queryResult.size > 0)
61 {
62 ContainerAsyncRequest _request = (ContainerAsyncRequest)queryResult.records[0];
63 while (_request.State.ToLower() == "queued")
64 {
65 //pause the process for 2 seconds
66 Thread.Sleep(2000);
67
68 //poll the server again for completion
69 queryResult = sforce.query(soql);
70 _request = (ContainerAsyncRequest)queryResult.records[0];
71 }
72
73 //now process the result
74 switch (_request.State)
75 {
76 case "Invalidated":
77 break;
78
79 case "Completed":
80 //class compiled successfully
81 //see the next example on how to process the SymbolTable
82 break;
83
84 case "Failed":
85 . . break;
86
87 case "Error":
88 break;
89
90 case "Aborted":
91 break;
92
93 }
94 }
95 else
96 {
97 //no rows returned
98 }
99 }
100 else
101 {
102 Console.WriteLine("Error: could not create ContainerAsyncRequest object");
103 Console.WriteLine(" The error reported was: " +
104 RequestResults[0].errors[0].message + "\n");
105 }
106 }
107 else
108 {
109 Console.WriteLine("Error: could not create Class Member ");
110 Console.WriteLine(" The error reported was: " +
111 MembersResults[0].errors[0].message + "\n");
112 }
113 }
114 else
115 {
116 .. Console.WriteLine("Error: could not create MetadataContainer ");
117 Console.WriteLine(" The error reported was: " +
118 containerResults[0].errors[0].message + "\n");
119 }
120 }
121To access Apex class and trigger data in a structured format, use a SymbolTable.
1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 //use the ID of the class from the previous step
18 string classId = "01pA00000036itIIAQ";
19 QueryResult queryResult = null;
20 String soql = "SELECT ContentEntityId, SymbolTable FROM ApexClassMember where ContentEntityId = '" + classId + "'";
21
22 queryResult = sforce.query(soql);
23 if (queryResult.size > 0)
24 {
25 ApexClassMember apexClass = (ApexClassMember)queryResult.records[0];
26 SymbolTable symbolTable = apexClass.SymbolTable;
27
28 foreach (Method _method in symbolTable.methods)
29 {
30 //here's the SayHello method
31 String _methodName = _method.name;
32
33 //is the method Global, Public or Private?
34 String _methodVisibility = _method.visibility.ToString();
35
36 //get the method's return type
37 string _methodReturnType = _method.returnType;
38
39 //get the fName & lName parameters
40 foreach (Parameter _parameter in _method.parameters)
41 {
42 string _paramName = _parameter.name;
43 string _parmType = _parameter.type;
44 }
45 }
46 }
47 else
48 {
49 //unable to locate class
50 }
51To add checkpoints to your code for debugging, use ApexExecutionOverlayAction.
1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 //use the ID of the class from the first sample.
18 string classId = "01pA00000036itIIAQ";
19
20 ApexExecutionOverlayAction action = new ApexExecutionOverlayAction();
21 action.ExecutableEntityId = classId;
22 action.Line = 3;
23 action.LineSpecified = true;
24 action.Iteration = 1;
25 action.IterationSpecified = true;
26 ApexExecutionOverlayAction[] actions = { action };
27
28 SaveResult[] actionResults = sforce.create(actions);
29 if (actionResults[0].success)
30 {
31 // checkpoint created successfully
32 }
33 else
34 {
35 Console.WriteLine("Error: could not create Checkpoint ");
36 Console.WriteLine(" The error reported was: " +
37 actionResults[0].errors[0].message + "\n");
38 }
39