Wednesday 19 August 2015

TOOLING API In Salesforce

What is  Tooling Api?
Tooling api is for Building custom development tools for Force.com applications.
Tooling API makes many development tasks easier.
When to use Tooling API?
When You want to add functionality to your existing development and integration tools or you want to build specialized development tools for a specific application or service.

• Manage working copies of Apex classes and triggers and Visualforce pages and         components using the ApexClassMember, ApexTriggerMember, ApexPageMember, ApexComponentMember and MetadataContainer objects.

• Manage working copies of static resource files using the StaticResource object.

• Check for updates and errors in working copies of Apex classes and triggers and Visualforce pages and components, and commit changes to your organization using the ContainerAsyncRequest object.
• Set heap dump markers using the ApexExecutionOverlayAction object.

• Overlay Apex code or SOQL statements on an Apex execution using the ApexExecutionOverlayAction object.

• Execute anonymous Apex. For sample code, see Using Tooling SOAP API and Using Tooling REST API.

• Set checkpoints to generate log files for yourself or for other users using the TraceFlag object.  

• Access debug log and heap dump files using the ApexLog and ApexExecutionOverlayResult objects.

• Manage custom fields on custom objects using the CustomField object.

• Access code coverage results using the ApexCodeCoverage,
ApexOrgWideCoverage and ApexCodeCoverageAggregate objects.

• Execute tests, and manage test results using the ApexTestQueueItem and ApexTestResult objects.

• Manage validation rules and workflow rules using the ValidationRule and WorkflowRule objects



Tooling API provides both SOAP and REST interfaces.

Use REST API if you’re using a language that isn’t strongly typed, like JavaScript. The Tooling REST API can be used just like the Force.com REST API.

Resources
The base URI for each Tooling REST API resource is http://domain/services/data/vXX.X/tooling/ where domain  is a Salesforce instance or a custom domain and vXX.X is the API version number.
Example:-http://na1.salesforce.com/services/data/v28.0/tooling/
Like the Force.com REST API, Tooling API uses the following resources.


URI
Supported Methods
Description
/completions?type=
GET
Retrieves available code completions of the referenced type.Currently only supports Apex system method symbols
(type=apex)
/executeAnonymous/?anonymousBody= <url encoded body>
GET
Executes Apex code anonymously.
/query/?q=
GET
Executes a query against a Tooling API object and returns data that
matches the specified criteria
/runTestsAsynchronous/?classids= <comma separated list of class
IDs> AND
/runTestsSynchronous/?classnames=<comma separated list of class
names>

GET
Executes the tests in the specified classes. Running tests
asynchronously allows methods to process in parallel, cutting down
your test run times.

/sobjects/
GET
Lists the available Tooling API objects and their metadata
/sobjects/SObjectName/
GET
Describes the individual metadata for the specified object or creates
a new record for a given object.use the GET method to retrieve the metadata for the ApexExecutionOverlayAction object.

/sobjects/SObjectName/
POST
Use the POST method to
create a new ApexExecutionOverlayAction object.

/sobjects/SObjectName/describe/
GET
Completely describes the individual metadata at all levels for the
specified object.
/sobjects/SObjectName/id/

GET
PATCH
DELETE
Accesses records based on the specified object ID.

Use the GET method to retrieve records or fields, the DELETE
method to delete records, and the PATCH method to update
records
/sobjects/ApexLog/id/Body/
GET
Retrieves a raw debug log by ID. Available from API version 28.0
or later.



EXAMPLES:
The following examples use Apex to execute REST requests
First, setup the connection to your org and the HTTP request type:
HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');

At the end of each request add the below code to send request and retrieve the body  of the response.
Http h = new Http();
HttpResponse res = h.send(req);
system.debug(res.getBody());

To get a description of all available objects in Tooling API:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/');
req.setMethod('GET');

To get a description of a specific Tooling API object, for example TraceFlag:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/
ApexClass/');
req.setMethod('GET');
To get a description of all the metadata for a specific Tooling API object, for example TraceFlag:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/
ApexClass/describe/');
req.setMethod('GET');

To create a new Tooling API object, for example MetadataContainer:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/
MetadataContainer/');
req.setBody('{"Name":"TestContainer"}');
req.setMethod('POST');

To retrieve a Tooling API object by ID, for example MetadataContainer:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/ MetadataContainer/ + containerID + '/');
req.setMethod('GET');

To update a Tooling API object by ID, for example MetadataContainer:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/ MetadataContainer/ + containerID + '/'); req.setBody('{"Name":"NewlyNamedContainer"}');
req.setMethod('PATCH');



To query a Tooling API object by ID, for example MetadataContainer:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/query/?q=
Select+id,Name+from+MetadataContainer+Where+ID=\'' + containerID + '\'');
req.setMethod('GET');



To check on the status of a deployment, using ContainerAsyncRequest:
req.setEndpoint('http://na1.salesforce.com/services/data/v28.0/tooling/sobjects/
ContainerAsyncRequest/' + requestID + '/');
req.setMethod('GET');

Apex Class :-

To create an Apex Class using Tooling Api :

String json ='{ "Name" : "Mydemoclass1", "Body" : "public class Mydemoclass1{ public Void sayHello(){ string name= \'HI NAGARAJU\'; system.debug(\'***Name\'+name);}   }" }';          
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/sobjects/ApexClass');
req.setMethod('POST');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setBody(json);
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());



clas1.png


To Update an Apex Class:
update an apex class involves some more steps than steps we required above. Apex class can be update by  ApexClassMember Object.
Steps to update are:
  • First we need to create Metadatacontainer object example:
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/MetadataContainer/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"Name":"TestMetadataContainer"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());
  • After this we need to create ApexClassMember object if we want to update ApexClass.ApexClassMember require 3 parameters, MetadatacontainerId, ApexClass id (which is created previously) as ContentEntityId and full body of class as string which is updated.
  • Here is example to create Apex Class so ApexClassMember will be created by:
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ApexClassMember/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId":"1dc90000000I6UwAAK","ContentEntityId" : "01p90000006Ll4tAAC","Body":"public class Mydemoclass1{ public Void sayHello(){ string name= \'HI NAGARAJU\';String Phone = \'9948839625\'; String Email = \'Nag@gmail.com\';system.debug(\'***Name\'+name);}   } "}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());




  • To update a class ContainerAsyncRequest object is used. It compile and deploy the code and provide status of code. Is code deployed or has some problem and what is the problem. ContainerAsyncRequest object can be created by:

req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId" : "1dc90000000I6UwAAK", "isCheckOnly": "false"}');

It returns the id by this, status of deployed code can be checked as:
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/'+'1dr90000001rMK3AAM');
tool.png

tool.png


To Delete an Apex Class :

HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() +'/services/data/v28.0/tooling/sobjects/ApexClass/'+01p90000006Ll4tAAC);
req.setMethod('DELETE');
Http h = new Http();
HttpResponse res = h.send(req);
system.debug(res.getBody());


Apex Trigger:
To create an Apex Trigger Using Tooling Api :

String json = '{ "Name" : "AccountTrigger", "TableEnumOrId" : "Account", "Body" : "trigger AccountTrigger1 on Account (before insert) { for(Account objacc : trigger.new){if(objacc.NManchala__Total_Amount__c > 1000){objacc.NManchala__Status__c = 'Clerk';} }}" }';
Httprequest req = new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v27.0/sobjects/ApexTrigger');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
req.setBody(json);
Http httpReq = new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());



tool.png

To Update  an Apex Trigger:
To update an apex trigger ,involves some more steps same as apex class.
  • First we need to create Metadatacontainer object example:

Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/MetadataContainer/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"Name":"TriggerMetadataContainer"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());
  • Next we have to create an apextriggerMember object if we want to update ApexTrigger.apextriggerMember  require 3 parameters, MetadatacontainerId, ApexTrigger id (which is created previously) as ContentEntityId and full body of trigger as string which is updated.
  • Here is example to create Apex Class so apextriggerMember will be created by:

Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ApexTriggerMember/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId":"1dc90000000I6VBAA0","ContentEntityId" : "01q90000000bbYRAAY","Body":"trigger AccountTrigger1 on Account (before insert) { for(Account objacc : trigger.new){if(objacc.NManchala__Total_Amount__c > 50000){objacc.NManchala__Status__c = \' Manager\';} }}"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());

  • To update a Trigger ContainerAsyncRequest object is used. It compile and deploy the code and provide status of code. Is code deployed or has some problem and what is the problem. ContainerAsyncRequest object can be created by:

Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId" : "1dc90000000I6VBAA0", "isCheckOnly": "false"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());

  • It returns the id by this, status of deployed code can be checked as:
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/'+1dr90000001rMQpAAM);
tool.png
tool.png




To delete an Apex Trigger:

HttpRequest req = new HttpRequest();
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() +'/services/data/v28.0/tooling/sobjects/ApexTrigger/'+01q90000000bbYRAAY);
req.setMethod('DELETE');
Http h = new Http();
HttpResponse res = h.send(req);
system.debug(res.getBody());

Apex Page:
To create a Apex Page using Tooling Api

String json ='{ "Name" : "TestPageFromRest","Markup" : "<apex:page>hello</apex:page>","ControllerType" : "0","MasterLabel":"TestPageFromRest","ApiVersion":"29.0"}';          
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/sobjects/ApexPage');
req.setMethod('POST');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setBody(json);
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());
//for controllerType = >0 -- no controller,
//for controllerType => 1 -- Standard controller + extensions
//for controllerType => 3 --custom Controller


tool.png

To update an Apex Page:
To update an apex Page,involves some more steps same as apexclass and trigger.

  • First we need to create Metadatacontainer object example:
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/MetadataContainer/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"Name":"pageMetadataContainer"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());
  • Next Create ApexPageMember .
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ApexPageMember/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId":"1dc90000000I6VGAA0","ContentEntityId" : "06690000005axNXAAY","Body":"<apex:page> <apex:form> <Apex:pageblock ></apex:pageblock></apex:form></apex:page>"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());

  • Next create ContainerAsyncRequest object.
Httprequest req =new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/');
req.setHeader('Content-Type','application/json');
req.setHeader('Authorization','OAuth ' + UserInfo.getSessionId());
req.setMethod('POST');
req.setBody('{"MetadataContainerId" : "1dc90000000I6VGAA0", "isCheckOnly": "false"}');
Http httpReq =new Http();
HttpResponse res = httpReq.send(req);
System.debug(res.getBody());

  • It returns the id by this, status of deployed code can be checked as:
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/'+'1dr90000001rMR9AAM');
tool.png
tool.png

To Create Static Resource using Tooling API:
string name = 'testjs';
string contentType = 'text/javascript';
string body = 'alert("Hello World");';
   // The static resource is expected to be base64 encoded.
string base64EncodedBody = EncodingUtil.base64Encode(Blob.valueof(body));
System.debug(base64EncodedBody);

HttpRequest req = new HttpRequest();
req.setEndpoint( URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v29.0/tooling/sobjects/StaticResource');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
// JSON formatted body
req.setBody(
   '{"Name":"'+name+'"'+
   ',"ContentType":"'+contentType+'"'+
   ',"Body":"'+base64EncodedBody+'"'+
   ',"CacheControl":"Public"}'
   );

Http http = new Http();
HttpResponse res = http.send(req);
System.debug(res);
System.debug(res.getBody());
System.debug(res.getHeaderKeys());

tool.png
tool.png





The Tooling Api consists of four types of objects.
1.Programming Objects.
2.Setup Objects.
3.Tooling Objects.
4.Operational Objects.

Programming Objects:
These Objects are used for interacting with programmatic artifacts for apex,visualforce and lightening.
The objects are:
Apexclass
ApexComponent
ApexPage
ApexTrigger
AuraDefinition
All the above objects Represents Saved Copy of their Respective.and

ApexClassMember
ApexComponentMember
ApexPageMember
ApexTriggerMember
AuraDefinitionBundle
Static Resource
Represents  working copy of their respective for Editing, saving and compiling.

Tooling Objects:
These objects are for building tools around test results, debugging, code coverage, and more.
ApexCodeCoverage:- Represents code coverage test results for an Apex class or trigger.
select ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered from ApexCodeCoverage ORDER BY ApexClassorTrigger.Name ASC.
tool.png

ApexCodeCoverageAggregate:-Represents aggregate code coverage test results for an Apex class or trigger.
select ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered from ApexCodeCoverageAggregate

ApexExecuteOverlayAction:- Specifies an Apex code snippet or SOQL query to execute at a specific line of code in an Apex class or trigger and optionally generate a heap dump.

ApexExecuteOverlayResult:-Represents the result from the Apex code snippet or SOQL query defined in the associated ApexExecutionOverlayAction, and the resulting heap dump if one was returned.

ApexLog :- Represents a debug log.

ApexOrgWideCoverage :- Represents code coverage test results for an entire organization.
SELECT PercentCovered FROM ApexOrgWideCoverage

ApexResult :- A complex type that represents the result of Apex code executed as part of anApexExecutionOverlayAction, returned in an ApexExecutionOverlayResult.

ApexTestQueueItem :- Represents a single Apex class in the Apex job queue.

HeapDump :- A complex type that represents a heap dump in an Apex Execution Overlay  Result.

SOQLResult :- A complex type that represents the result of a SOQL query in an Apex ExecutionOverlayResult.

SymbolTable:A complex type that represents all user-defined tokens in the Body of an ApexClass,ApexClassMember, or ApexTriggerMember and their associated line and column locations within the Body.
select Id, ApiVersion, Name, NamespacePrefix, SymbolTable, Body from ApexClass where NamespacePrefix = 'Nmanchala'

TraceFlag :- Represents a trace flag that triggers an Apex debug log at the specified logging level.

Operational Objects:-
These objects are for Tooling API operations.
ContainerAsyncRequest :- Allows you to compile and asynchronously deploy a MetadataContainer object to your organization.

DeployDetails:-A complex type that contains detailed XML for any compile errors reported in the asynchronous request defined by a ContainerAsyncRequest object.

MetadataContainer :- Manages working copies of ApexClassMember, ApexTriggerMember, ApexPageMember and ApexComponentMember objects, including collections of objects that should be deployed together.


Setup Objects:- These objects are primarily used for interacting with metadata for declarative development.
All these Objects are Queryable  objects by enabling the (Use Tooling API )Checkbox in developer console.

Object
Description
BusinessProcess
Represents a business process.
CompactLayout
Represents the values that define a compact page layout.
CustomField
Represents a custom field on a custom object that stores data unique to your organization.
CustomFieldMember
Represents the working copy of a field for editing or saving in a Metadata Container.
CustomObject
Represents a custom object that stores data unique to your organization. Includes access to the associated CustomObject object and related fields in Salesforce Metadata API.
CustomTab
Represents a custom tab.
EmailTemplate
Represents an email template.
EntityDefinition
Provides row based access to metadata about standard and custom objects.
FieldDefinition
Provides row based access to metadata about standard and custom fields of standard and custom objects.
FieldSet
Represents the metadata for a group of fields.
FlexiPage
Represents a Lightning Page. A Lightning Page is the home page for an app that appears as a menu item in the Salesforce1 navigation menu. Includes access to the associated FlexiPage object in the Salesforce Metadata API.
Layout
Represents a page layout. For more information, see “Managing Page Layouts” in the Salesforce online help.
MenuItem
Represents a menu item.
Profile
Represents a user profile. A profile defines a user's permission to perform different functions within Salesforce.
ProfileLayout
Represents a profile layout.
QuickActionDefinition
Represents the definition of a quick action.
QuickActionList
Represents a list of quick actions.
QuickActionListItem
Represents an item in a quick action list.
RecentlyViewed
Represents metadata entities typically found in Setup such as page layout definitions, workflow rule definitions, and email templates that the current user has recently viewed.
RecordType
Represents a custom record type.
User
Represents a user.
ValidationRule
Represents a formula that is used for specifying when a criteria is met. This includes both validation rules and workflow rules. Includes access to the associated ValidationRule object in the Salesforce Metadata API.
WorkflowAlert
Represents a workflow alert. A workflow alert is an email generated by a workflow rule or approval process and sent to designated recipients.
WorkflowFieldUpdate
Represents a workflow field update.
WorkflowOutboundMessage
Represents an outbound message. An outbound message is a workflow, approval, or milestone action that sends the information you specify to an endpoint you designate, such as an external service. Outbound messaging is configured in the Salesforce setup menu. Then you must configure the external endpoint. You can create a listener for the messages using the SOAP API.
WorkflowRule
Represents a workflow rule that is used to fire off a specific workflow action when the specified criteria is met. Includes access to the associated WorkflowRule object in Salesforce Metadata API.
WorkflowTask
Represents a workflow task that is used to fire off a specific workflow action when the specified criteria is met. Includes access to the associated WorkflowRule object in Salesforce Metadata API.
















5 comments:

  1. Thanks...best information about tooling api

    ReplyDelete
  2. What are the permissions needed for using it from a static method on a static apex class?

    ReplyDelete
  3. How to right test classes for tooling api ,in case of updating workflow .

    ReplyDelete
  4. Useful Document.Can we deactivate multiple trigger at one rest call?

    ReplyDelete