SOQL Query Analysis using Query Plan tool and Optimization using filters & Custom Indexes.

Why SOQL Optimization is Needed ?

SOQL is a tool that lets you access records in your Salesforce database. When you don’t write good SOQL queries you’re going to hit the governor limit of non selective query. There is a very common issue that most of us have came across when there are more than 100k records in a given table. For e.g.  If we cross the threshold of 100k records, we might start to see some “non-selective query” type errors mentioned below:

Error Non Selective

 

SOQL query should always be selective meaning it must contain at least one query filter on an indexed field and that filter in turn reduces the resulting number of rows below a Salesforce-determined threshold*.

Analyze SOQL queries using Query Plan tool 

When it comes to optimize the SOQL, we first need to analyze the SOQL to identfiy the weak areas of SOQL and it’s running performance. The Query Plan tool shows the cost of Salesforce executing a given SOQL query given the database statistics known at that time.

Enabling Query Plan

Salesforce doesn’t have the Query Plan feature enabled by default. To enable it, open the Developer Console –> Help –> Preferences and then check “Enable Query Plan”.

Using Query Plan

After the Query Plan is enabled, open the Query Editor tab at the bottom, enter a SOQL query, and click the Query Plan button. This will open a modal showing the cost of the SOQL query along with helpful tips.

QueryPlan

  • Cardinality – The estimated number of records that will be returned by the query.
  • Fields – The indexed field(s) used by the Query Optimizer. If the leading operation type is Index, the fields value is Index. Otherwise, the fields value is null.
  • Leading Operation Type – The primary operation type that Salesforce will use to optimize the query.
    • Index – The query will use an index on the queried object.
    • Sharing – The query will use an index based on the sharing rules associated with the user who is executing the query. If there are sharing rules that limit which records that user can access, Salesforce can use those rules to optimize the query.
    • TableScan – The query will scan all records for the queried object.
    • Other – The query will use optimizations internal to Salesforce.
  • Cost – The cost of the query compared to the Force.com Query Optimizer’s selectivity threshold. Values above 1 mean that the query won’t be selective.

In above example, we query all Accounts with non-selective filter which is “Is Deleted”, the cost is high.

  • SObject Cardinality – The approximate record count for the queried object.
Salesforce Query Plan How To
Optimize SOQL using Filters and Custom Index : 
  • We must only select the fields which are needed but not all fields.
  • We should try to use the limit operator to reduce how many records are returned.
  • We must use indexed fields- selective filters

Here are the three examples which shows how the initial non-selective query is being optimized with adding more filters to it.

// Non- Selective Query- This will return everything from the table 

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact ];

// Better Query than above one, we’ve got a filter but it is not on an indexed field

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact Where Status = ‘Active’];

// Even better since Owner is one of the standard indexed fields. The performance of the SOQL //query improves when two or more filters used in the WHERE clause meet the mentioned //conditions.

List<Contact> = [SELECT Id, Name, Email, OwnerId from Contact Where Status = ‘Active’ and OwnerId IN (‘005d0000001acWo’,’005d0000001mnTo’) ];

Developer must use Indexed fields to improve the performance of SOQL query.

Custom Index and Considerations 

Salesforce leverages indexes heavily to optimize query performance whenever possible. An index is a separate data structure that stores field values in such a way that it’s fast to search on them to identify the rows we’d like returned. The general concept is the same as a book’s index.

What fields are pre- indexed?

  • Object Ids
  • Object Name – Auto Number or Text Field.
  • Custom Relationsips – Master Details and Lookups.
  • External Ids
  • Unique Fields
  • Owner Field

Use an index in the where clause whenever possible. However, this doesn’t guarantee that it will be used. Salesforce has various rules around when an index will be used or not based on its selectivity.

  • An indexed field will not be used under the following conditions:
    • Not In (…)

e.g. Status__c Not IN (‘Active’) – Even if Status__c is indexed field, it won’t be considered as indexed field and might occur non-selective error. 

    • Like with wildcards “%Field%”
    • !=
    • Excludes for picklist values
    • Not Like
    • Comparison Operators Paired With Text Fields. Text_Field <, >, <=, >

Not sure if a field is indexed or not ? Open an object’s definition page and notice that there’s an “Indexed” column. If it’s checked, it’s indexed.

Indexed

How to get field Indexed which is not indexed ?

Please submit a case with Salesforce Support.

For more information custom index:-

 

Salesforce Apex Code Repository

Salesforce provides couple of developer related objects which are very useful when a developer wants to fetch the metadata information of apex class, components, pages, triggers, code coverage using apex code. There are lot of scenarios where we can utilize these objects :-

  1. To search any referenced fields and objects inside apex classes,pages & triggers.
  2. To Create an Apex Class, Apex Triggers, Apex Pages via API.
  3. To find out the package related classes or triggers.
  4. To check the number of test classes and running test results.
  5. To check the coverage of classes and triggers.

We have the following objects which represent Apex Code Repository:-

  1. ApexClass
  2. ApexComponent
  3. ApexPage
  4. ApexTrigger
  5. ApexTestResult
  6. ApexCodeCoverage
  7. ApexCodeCoverageAggregate

ApexClass

This object represents apex class.

For e.g. A Developer wants to show the list of classes related to a package called “APTTUS” , we can use a field NameSpacePrefix to filter out the classes related to package using below SOQL:

Select Name From ApexClass Where NameSpacePrefix = 'APTTUS'         

For more information about ApexClass object.

ApexTrigger

This object represents Apex Triggers.

For e.g. A Developer wants to show the list of Apex Triggers on the Account object. We can use a field called TableEnumOrId with passing the Object Name and below SOQL will return all the triggers written on Account object.

Select Name From ApexTrigger Where TableEnumOrId = 'Account'         

For more information about ApexTrigger object.

ApexPage

This object represents a Visualforce Page.

For e.g. A Developer wants to show the list of Visualforce Pages defined with the standardController attribute on the <apex:page> tag

Select Name From ApexPage Where ControllerType = 'Standard'   

For more information about ApexPage object.

ApexTestResult

This object represents the Test Results produced by apex tests. Each test method execution is represented by a single ApexTestResult record.

For e.g. A Developer wants to show the list of apex test results ran for an apex class “XYZ”. Here XYZ is the ID of Apex Class. Below SOQL will return the test results for the same:

Select Name From ApexTestResult Where ApexClassId = 'XYZ'   

For more information about ApexTestResult object.

ApexCodeCoverage

This object represents code coverage test results for an Apex class or trigger. This object is accessible via Tooling API only. This object is specifically used to design a statistic report for any apex class or trigger.

This object needs a REST Call to access the data stored into this object. Below is the sample code to get the data using REST call:


HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint(wrapObj.instance_url+'/services/data/v39.0/tooling/query/?q='+SELECT+id,ApexTestClass.Name,TestMethodName,NumLinesCovered,NumLinesUncovered,ApexClassorTrigger.Name,ApexClassorTrigger.Type,Coverage+from+ApexCodeCoverage+where+ApexClassorTriggerId);
req.setHeader('Authorization', 'OAuth '+wrapObj.access_token);
req.setTimeout(120000);
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug('***Response Body****'+ res.getBody());
return res.getBody();

For more information about ApexCodeCoverage object.

ApexCodeCoverageAggregate

This object represents aggregate code coverage for a  Class or Trigger. For E.g. :-  We want to see the coverage for a specific class covered by all test methods, so we can use this object in our REST call. 

In Summary, Salesforce provides the flexibility to play around with the metadata of developer objects in Apex Code.

Salesforce Tweaks using Chrome Plugins

Admin/Developers spend lot of time in opening, searching, navigating, analyzing, assigning permissions on setup or non setup items using Salesforce standard functionality.

There are couple of plugins for developers-

Salesforce advanced Code searcher

1. Search for any code inside Apex Class, Visualforce page, Triggers etc.

2. Find and open any Class, Visualforce, Triggers, Components, Templates.

3. Extract Code Coverage. 

To speed up the above mentioned activities, there is a plugin called:

By using the advanced quick find you can get your code few clicks shorter. Also, you can search any string your code Also, you can search any string your code

In addition to the above you can use this extension to jump to classes / pages / triggers from the advanced quick find section on the left hand side.

SF Quick Metadata Lookup

Find any metadata in your org. 

To download the above plugin:

 

Salesforce API FieldNames

Shows the API field names on detail pages.

To download the above plugin:

SOQL Extractor and Analyzer for Salesforce

Extract SOQL queries with their execution counts from Debug Logs of Salesforce. Helps Developer to analyze the ‘Too Many SOQLs’ error.

To download the above plugin:

Salesforce – Deployment Tools, Best Practices & Faster Deployment

When you are ready to deploy your changes to Production, a developer can use various tools to move metadata from one organization to another:

Change Sets:

The most frequently used tool for deployment when you want to send customizations from your Sandbox to Production org. This requires a deployment connection to be established between Sandbox and Production org. Change sets are the simplest way of doing deployments which uses point and click tool to migrate metadata instead of using xml files or scripts. It works between Sandbox and Production only.

Please follow the below doc to setup and use Change Sets:

https://help.salesforce.com/articleView?id=code_tools_changesets.htm&type=0&language=en_US&release=206.13

Force.com Migration Tool

The Force.com Migration Tool is most preferred tool a Java/Ant-based command-line utility for moving metadata between a local directory and a Salesforce org. There is no deployment connection required which means you can deploy the components from one org to any Salesforce org.

Please follow the below doc to setup and use Force.com Migration tool:

https://developer.salesforce.com/docs/atlas.en-us.daas.meta/daas/meta_development.htm

Force.com IDE / Eclipse

The Force.com IDE is a plugin for Eclipse which is very powerful tool for creating , modifying and deploying  the apex code. This tool can synchronize changes between any Salesforce Orgs. The main feature of Eclipse is that you can easily delete classes from Production org by changing the related metadata .xml file.

Please follow the below doc to setup and use Force.com Migration tool:

https://developer.salesforce.com/page/Force.com_IDE

Which tool we should use for Deployment?

Please follow the below chart below to decide which tool you may use for deployment.

Environment What we can do ? Developer Console Workbench Eclipse ANT
Production Create/Modify Code
Delete Code
Rename Class
Run/Debug Code

Run SOQL query
Deploy Code

No

No

No

Yes

Yes

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

No

Yes

Yes

Yes

Yes

No

No

Yes
Sandbox Create/Modify Code
Delete Code
Rename Class
Run/Debug Code

Run SOQL query
Deploy Code

Yes

Yes

Yes

Yes

Yes

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Yes

Yes

No

Yes

Yes

Yes

Yes

No

No

Yes

Plese check out the link below for more information:

https://help.salesforce.com/articleView?id=code_tools_ant.htm&type=0&language=en_US&release=206.13

What are the Best Practices to make your deployment faster?

Whenever we push any apex class or triggers to Production all of the apex tests are run as part of the deployment process. If there are lots of test classes and customization it can take a really long time to run the tests which will increase the time taken for Deployment.

We can always reduce the deployment time by following best practices :

Always Use (SeeAllData=false)
When you annotate your test class or test method with (SeeAllData=true) it opens up data access to records in your organization. This value should not be set to true because we don’t want our test methods to trust on existing data which may cause your test classes failed to run if there is no existing data found for particular scenario.

We should always create independent test data with seeAllData=False and it also avoids any SOQL to extract the existing data from org.

Apex Classes created after version 23 are automatically using SeeAllData = false unless the class or methods are marked explicitly with SeeAllData = true. We can still query Users, Profiles, User Groups etc. even if SeeAllData=false. However there are some objects that cannot be queried with SeeAllData = false e.g Standard Pricebook..

Please check the link below for more information:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_seealldata_using.htm

 

Run a Subset of Tests

Test levels enable you to have more control over which tests are run in a deployment. To shorten deployment time to production, run a subset of tests when deploying Apex components.

  • While deploying the change set, we can run specific test by choosing the option “Run Specific Tests” and defining the name of the relevant test classes.
  • While deploying using ANT migration tool, we can define which test should run:
<target name="deployCode">
    <sf:deploy username="${sf.username}" password="${sf.password}" 
           sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"
           deployroot="codepkg" testLevel="RunSpecifiedTests">
        <runTest>TestClass1</runTest>
        <runTest>TestClass2</runTest>
        <runTest>TestClass3</runTest>
    </sf:deploy>
</target>

Use @testSetup

You should use @testSetup at the top of your test class and this is very useful which can be time-saving when you need to create a common set of records that all test methods operate on or prerequisite data. Each test methods receives a fresh copy of test data created using @testSetup method.

In below example: we are creating an Account using @testSetup method, this record can be accessible in all test methods. :

@testSetup static void methodName() {
 Account acc = new Account();
 acc.Name = 'Test Account';
 insert acc;
}

For more information about @testSetup:

https://developer.salesforce.com/releases/release/Spring15/TestClasses

Use System.Assert()
In order to check whether the test data is really useful and returning the results as expected and contributing to code coverage, you must use System.Assert() method.  This is always useful to remove any test data which doesn’t contribute to code coverage.

In the below example, the expected name of the Account is ‘Test’. If we give the name other than ‘Test’, it will throw error.

public class SampleClass {
    public void insertAcct(String name, String extId) {
        Account acc = new Account(Name = name,External_ID__c = extId);
        insert acc;
        System.assertEquals('Test',acc.Name);
    }
}

For more information about system.Assert():

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_example.htm

Avoid using System.RunAs  
System.RunAs will take more time to execute than without. You will need to use System.RunAs as wisely to reduce execution time for running the test class. If your organization has more than a thousand test methods System.RunAs will start to add up and will make your deployment slow.

 

What is Dynamic Apex in Salesforce and how to use it ?

Dynamic apex enables developers to create more flexible applications by providing them with the ability to “Access sObject and field describe information”, “Write Dynamic SOQL Queries”, “Write Dynamic SOSL Queries” and “Dynamic DML”.

It consists of several components such as schema describe, dynamic SOQL, dynamic SOSL, and dynamic DML.

1) Access sObject and field describe information:

Example 1: Get the list of all schema describe, available sobject in salesforce database using Apex (Dynamic Apex):

Map<String, Schema.SObjectType> m = Schema.getGlobalDescribe();

In the above code, it returns map of all Sobjects names or Keys to sObject tokens or values for the standard and custom objects defined in the organization.

Example 2: Get all the fields of sObject using ( Dynamic Apex ):

Map<String, Schema.SObjectType> m  = Schema.getGlobalDescribe() ;
Schema.SObjectType s = m.get('API_Name_Of_SObject') ;
Schema.DescribeSObjectResult r = s.getDescribe() ;
Map<String,Schema.SObjectField> fields = r.fields.getMap() ;

Please also go through the available methods for Schema class:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_schema.htm#apex_System_Schema_getGlobalDescribe

Example 3: Get Record Type Id without SOQL query:

Id recTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get(Rec_Type_Name).getRecordTypeId();

Example 4:  Check whether the Object is Creatable and Insertable for loggedin user:

Schema.SObjectType objInfo = Schema.getGlobalDescribe().get('Account');

Schema.DescribeSobjectResult objResult = objInfo.getDescribe();
System.debug(objResult.isCreateable());
System.debug(objResult.isInsertable());

 

2) Write Dynamic SOQL Queries

SOQL is Salesforce Object Query Language for querying data in the Force.com platform. It is very much similar to SQL. But in SOQL, we can not query all fields from object. Following statement is not allowed in SOQL:
select * from Account;
But there is one workaround to query all fields of Object in SOQL query.
For e:g:  we will use SOQL query to fetch all fields of account object :

String SobjectApiName = 'Account';
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Map<String, Schema.SObjectField> fieldMap = schemaMap.get(SobjectApiName).getDescribe().fields.getMap();

String commaSepratedFields = '';
for(String fieldName : fieldMap.keyset()){
 if(commaSepratedFields == null || commaSepratedFields == ''){
 commaSepratedFields = fieldName;
 }else{
 commaSepratedFields = commaSepratedFields + ', ' + fieldName;
 }
}

string query = 'select ' + commaSepratedFields + ' from ' + SobjectApiName + ' Limit 5';
List<Account> accList = Database.query(query);

 

3) Write Dynamic SOSL Queries

Please refer to the Dynamic SOSL from How to use a SOSL query to search in multiple Salesforce objects?

4) Dynamic DML

Please refer to the Dynamic DML from Apex Developer Guide

How to call Rest Service using OAuth REST API ?

We created a REST Service in Salesforce in our previous blog, and now we want to call the REST service from another application. Salesforce DO NOT allow using Basic Authentication (Username & Password) for incoming REST calls. This is still true even if you are calling from another Salesforce instance.  We have to use OAuth to authenticate to Salesforce.

OAuth (Open Authorization) is an open protocol to provide secured authorization. Here are the list of OAuth flows used while making REST API calls:

In this blog, we are using Username-password flow to make a call to a REST Service in Salesforce using OAuth. Please follow the steps below to set up the REST call:

1) Remote Site Settings

First you need to create two entries in remote site settings:

  1. Enter the remote site Name, URL for Salesforce login https://login.salesforce.comremotesite.png
  2. Create another remote site Name, URL for accessing Salesforce data https://instance.salesforce.com.

2) Create Connected App

Now we create a Connected App:

  1. Go to Setup | Create | Apps.
  2. Under Connected App, Click “New”.
  3. Enter the name of Connected App and specify details as mentioned (in Screenshot) below.
  4. Click Save.

connectedap.png

Once you have created the Connected App, you will see the following screen with “Consumer Key” and “Consumer Secret”:

connectedAppSaved.png

 

We can use the “Consumer Key” which will be a client_id and “Consumer Secret” as client_secret inside the body of the call to make the callout.

grant_type=password&client_id='+clientId+'&client_secret='+clientSecret+'&username='+username+'&password='+password

Apex Code:-

/* Class for getting account record from other salesforce org through rest api integration
by calling class and its method from other org*/

public class TestWebService{
    public TestWebService(){
                                //You will get "clientId","clientSecret" when creating connected app in salesforce
        String clientId = '3MVG9szVa2RxsqBYoWov5yC4I5MxFgDDe3.6Z1g__FlEYNOPY45vALm1kA5oCZuFkHYxCzm2A3SdSoxFpUNU3';
        String clientSecret = '7917982719268332943';

        //We can also store our username password in custom setting.
        String username='ajomon@apexcoder.com';//salesforce username 
        String password='*l2YzP2TxlvI';//EUe4eHjMxXb8UFco1SPcpsZL9';//salesforce password
        // Generating the Access Token
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint('https://login.salesforce.com/services/oauth2/token');// this is the OAuth endpoint where this request will be hit
        req.setBody('grant_type=password&client_id='+clientId+'&client_secret='+clientSecret+'&username='+username+'&password='+password);
        
        Http http = new Http();
        HTTPResponse res = http.send(req);
        String str = res.getBody();
        wrapObj = (Wrapper)Json.deserialize(str,Wrapper.class);
        accessToken = wrapObj.access_token;
        instanceUrl = wrapObj.instance_url;
        methodGet();
    }
        
    // Retrieve the Contacts from the otehr org.
    public void methodGet(){
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        //req.setEndpoint(wrapObj.instance_url+'/services/apexrest/Account/getAccountById?name=champaKAli');
        
        req.setEndpoint(wrapObj.instance_url+'/services/apexrest/AccountService');
        req.setHeader('Authorization', 'OAuth '+wrapObj.access_token);
        Http http = new Http();
        HTTPResponse res = http.send(req);
        
        System.debug('***Response***** ' + res.getBody());
        //---------------------Here ------------------
        /*JSONParser parser = JSON.createParser(res.getBody());
        do{
            parser.nextToken();
        }while(parser.hasCurrentToken() && !'records'.equals(parser.getCurrentName()));
            parser.nextToken();
        List<account> acc = (List<Account>) parser.readValueAs(List<Account>.class);*/
    }
    public Contact con {get;set;}
    public String s1 {get;set;}
    public String accessToken;
    public String instanceUrl;
    public Wrapper wrapObj{get;set;}
    // Wrapper Class to Store the value from the Jason.
    public class Wrapper{
        String id;
        String instance_url;
        String access_token;
        String issued_at;
        String signature;
    }
}

In the above code, we are using client_id and client_secret to authorize the external app.

We can also parse the response using parser classes.

We can execute the above code using developer console and print all the accounts in system.debug() :

TestWebService tw = new TestWebService();
tw.methodGet();

How to create and use Apex Rest Services in Salesforce ?

The Force.com REST API lets you integrate external system with Force.com applications using simple HTTP methods, in either XML or JSON formats, making this an ideal API for developing mobile applications or third party applications.

Following are the benefits of using the REST API in your integrations:

  • Easy Access: Use standard HTTP method call-outs, available on every language and platform, to make requests and retrieve information from Force.com.
  • Flexible formats: Request and response can flow in XML or JSON format.
  • Standards-based security: Basic Authorization (Username/Password or SessionId), OAuth (Open Authorization) .
  • Data model: Standard/custom objects are accessible using REST API.
  • Very lightweight and easy to use as compared to SOAP based services.

Let’s create an Apex REST Services which can perform insert, update, delete records .  In the below example, we are querying, creating, updating and deleting Accounts by implementing a Rest-Based Service called AccountService.

Note: For updating and deleting Accounts, developer must pass the parameters while making a REST call.

Creating REST Service
@RestResource(urlMapping='/AccountService/*')
global class AccountService {

 @HttpGet
 global static List<Account> getAccounts() {
   List<Account> Accounts = [SELECT Id,Name from Account LIMIT 10];
   return Accounts;
 }

 @HttpPost 
 global static String createNewAccount(String Name) {
   Account a = new Account();
   a.Name = Name;
   insert a;

   return 'Account Created';
 }

 @HttpDelete
 global static String deleteAccountById() {
 
   RestRequest req = RestContext.request;
   String Id = req.params.get('Id');

   List<Account> a = [ Select ID from Account where Id= :Id];

   delete a;

   return 'Account Deleted';
 }

 @HttpPut
 global static String updateAccount(String Id, String NewName) {
   Account a = [ Select ID, Name from Account where Id= :Id];
   a.Name = NewName;
   update a;

   return 'Account Updated';
 }
}

In the above code,

  1. The REST service must be declared as global and static
  2. The keyword “@RestResource”  is used to signify that class should act as REST based web service.
  3. The urlMapping  property allows us to set path where the service will be available. This is how we set up the endpoint for the service. e.g.   https://.salesforce.com/services/apexrest/AccountService
  4. There are few http methods mentioned:-
    1. @HttpGet  – returning data using HTTP GET request.
    2. @HttpPut  – updating data using HTTP POST request.
    3. @HttpDelete –  deleting data using HTTP DELETE request.
    4. @HttpPost – inserting data using HTTP PUT request.
    5. @HttpPatch – upserting data using HTTP PUT request.
  5. In order to pass parameters to service,  we use RestRequest object in a method. See below sample code:
  6. RestRequest req = RestContext.request;
     String Id = req.params.get('Id');
Using REST Service

Invoke REST Service from Workbench : 

  1. login into workbench using below URL: https://workbench.developerforce.com/login.php
  2. From the menu , please choose utilities > click REST Explorer
  • GET – To get all the Accounts using @HttpGet
  1. Select HTTP GET  method from radio buttons.
  2. Enter the REST URI in the text box.
  3. We are making a HTTP GET call to retrieve all the accounts.
  4. Click on execute.
  5. Click on “Show Raw Response”.RestServiceWorkbench.png
  • Response Format: In the above screenshot, we can get response in XML or JSON by Clicking on “Headers” button and setting HTTP header with below code:
  • Content-Type: application/xml
    accept: application/xml
  • POST – To create an Account using @HttpPost
  1. Select HTTP POST method from radio buttons.
  2. Enter the REST URI in the text box.
  3. We are making POST call, so enter a body in JSON format.
  4. Click on execute, and see the raw response.

post

  • Delete an Account using @HttpDelete
  1. Select HTTP DELETE method from the radio buttons.
  2. Pass the account id as a parameter:
    /services/apexrest/AccountService?id=00141000009K7xLAAS
  3. Click on execute, and see the raw response.

Invoke REST SERVICE from APEX :

First you need to add the REST endpoint under Salesforce “Remote Site Settings”. To add the remote site settings, please follow the below steps:

  1. From Setup, enter Remote Site Settings in the Quick Find box, then select Remote Site Settings.
  2. Click New Remote Site.
  3. Enter Remote Site Name.
  4. Enter the URL for REST Service endpoint.
  5. Click Save.

remote-site-setting

Once the remote site setting is setup, now we can invoke our rest service using apex.

 

Call REST Service using OAuth

Now rest service is ready to be called from anywhere. In the following example,  we are making an external callout to our REST service using OAuth Session Id and we are using below endpoint, which is the following format: https://instance.salesforce.com/services/apexrest/Class_Name

We are hitting following end point from APEX https://na35.salesforce.com/services/apexrest/AccountService

public class RestServiceClass{
 
 @future (callout=true)
 public static void RestServiceMethod(String sessionId){

 HttpRequest req = new HttpRequest();
 req.setEndpoint('https://na35.salesforce.com/services/apexrest/AccountService');
 req.setMethod('GET'); 
 req.setHeader('Authorization', 'OAuth ' + sessionId);
 req.setHeader('Content-Type','application/json'); 
 req.setTimeout(120000);
 
  
 HttpResponse res = new HttpResponse();
 res = http.send(req);
 
 system.debug(res);
 }

 

Other Considerations:

  • We can set the Content-Type on the request header to Json or XML to get the results in respective formats.

rest_xml_header

  • If you have many records to process, consider using Bulk API, which is based on REST principles and optimized for large sets of data.
  • API Call limits to Salesforce will be enforced. Please see the link below:

https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_api.htm

For more information:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest_code_samples.htm