Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

Note:- Code is highlighted in a yellow background color.

19th July 2023

1. What is Asynchronous Apex?

Asynchronous Apex is used to run process in a separate thread at later time. It is


process or function that executes a task “in the background” without the user having
to wait for the task to finish.
We can typically use asynchronous process for callouts to external systems,
operations that require higher limits, solve Mixed DML Exception, and code that
needs to run at a certain time.
Benefits of Asynchronous process are User efficiency, Scalability and higher limits.

There different ways to implement Asynchronous process in Apex.


● Future methods
● Batch Apex
● Queueable Apex
● Scheduled Apex

2. Difference between synchronous and asynchronous in apex:-

Synchronous Apex :-
Synchronous term means existing or occurring at the same time. Synchronous Apex
means entire Apex code is executed in one single go.

Asynchronous Apex :-
Asynchronous term means not existing or occurring at the same time. Asynchronous
apex is executed when resources are available. So any calling method which calls
Asynchronous apex wont wait for outcome of Asynchronous call. Calling method will
go on further execution in code. And Asynchronous execution happens in separate
thread and then it will return to main program.
An async call is queued up in Salesforce and run on a separate thread of execution.
At this point it becomes decoupled from the calling action. That also means the
calling action won’t block and wait for a response from the asycn call. Using the
future annotation identifies methods that are executed asynchronously. They must
also be static methods. There are some considerations to know when using async
methods.

Synchronous:
In a Synchronous call, the thread will wait until it completes its tasks before
proceeding to next. In a Synchronous call, the code runs in single thread.
Example:
Trigger
Controller Extension
Custom Controller

Asynchronous:
In a Asynchronous call, the thread will not wait until it completes its tasks before
proceeding to next. Instead it proceeds to next leaving it run in separate thread. In a
Asynchronous call, the code runs in multiple threads which helps to do many tasks
as background jobs.

3. Synchronous and Synchronous Calling:-

This is a transaction which gets executed in a single thread. Where the called class
has to wait for the other synchronous to finish its execution.

SynchronousClass1.apxc

public class SynchronousClass1 {

public static void syncMethod1() {

System.debug('Before Calling');

SynchronousClass2.syncMethod2();

System.debug('After Calling');
}
}
SynchronousClass2.apxc

public class SynchronousClass2 {

public static void syncMethod2() {


System.debug('Synchronous 2 method is executed');
}
}

4. Synchronous and Asynchronous Calling:-

This is a transaction in which Synchronous classes gets executed in a single thread


and asynchronous in another thread. Where the called class don’t have to wait for
the other asynchronous to finish its execution.

SynchronousClass1.apxc

public class SynchronousClass1 {

public static void syncMethod1() {

System.debug('Before Calling');

AsyncClass.asyncMethod1();

System.debug('After Calling');
}
}

AsyncClass.apxc

public class AsyncClass {

@future
public static void asyncMethod1() {
System.debug('Inside future method');
}
}
Future Method

1. Future Methods in Salesforce

Future Methods in Salesforce using @future annotation


A future method runs in the background, asynchronously. You can call a future
method for executing long-running operations, such as callouts to external Web
services or any operation you’d like to run in its own thread, on its own time. You can
also use future methods to isolate DML operations on different sObject types to
prevent the mixed DML error. Each future method is queued and executes when
system resources become available. That way, the execution of your code doesn’t
have to wait for the completion of a long-running operation. A benefit of using future
methods is that some governor limits are higher, such as SOQL query limits and
heap size limits. You can call 50 future methods per transaction.

2. How to define a method as future?

Use the annotation @future at the top of the method.


Future methods must be always static and have a return type as void.

Public class AsyncClass{

@future
Public static void asyncMethod() {
//future code goes here
}
}

NOTE :-
1) Methods with the future annotation must be static methods
2) can only return a void type
3) The specified parameters must be primitive data types, arrays of primitive data
types, or collections of primitive data types
4) Methods with the future annotation cannot take sObjects or objects as arguments.
5) You can invoke future methods the same way you invoke any other method.
However, a future method can’t invoke another future method
6) No more than 50 method calls per Apex invocation
20th July 2023

1. How to track future method from setup?

Setup -> Environments -> Jobs -> Apex Jobs.


a. We can track our future methods here.
b. See the status and also track method name.
c. Get Id of our future method from here.

2. How to track future method using query?

SELECT Id, JobType, ApexClassId, Status, JobItemsProcessed, TotalJobItems,


NumberOfErrors, MethodName, CompletedDate, ExtendedStatus, ParentJobId,
LastProcessed FROM AsyncApexJob WHERE Id = '7075g00004vi0nP'

3. What is a Mixed DML Exception?

If we perform DML operation on standard/custom object and global objects(User,


UserRole, Group, GroupMember, Permission Set, etc…) in same transaction this
error will come.

To avoid this error, we should perform DML operation on standard/custom object


records in a different transaction.

In general all the apex classes and apex triggers execute synchronously (execute
immediately).

If we perform DML operation on standard/custom object records asynchronously


(execute in future context), we can avoid MIXED-DML-OPERATION error.

To execute logic asynchronously keep the logic in an apex method (in a separate
apex class, not in same apex trigger) which is decorated with @future annotation.

public class SynchronousClass1 {

public static void syncMethod1() {

PermissionSet perSet = new PermissionSet();


perSet.Label = 'Apex Per Set';
perSet.Name = 'ApexPerSet';
insert perSet;

Opportunity opp = new Opportunity();


opp.Name = 'Apex Opportunity';
opp.StageName = 'Closed Won';
opp.CloseDate = System.today();
insert opp;
}
}

We will get below error if the above code is executed:-

System.DmlException: Insert failed. First exception on row 0; first error:


MIXED_DML_OPERATION, DML operation on setup object is not permitted after
you have updated a non-setup object (or vice versa): Opportunity, original
object: PermissionSet: []

4. How to resolve Mixed DML Exception?

SynchronousClass1.apxc

public class SynchronousClass1 {

public static void syncMethod1() {

Opportunity opp = new Opportunity();


opp.Name = 'Apex Opportunity';
opp.StageName = 'Closed Won';
opp.CloseDate = System.today();
insert opp;

AsyncClass.asyncMethod1();
}
}

AsyncClass.apxc

public class AsyncClass {

@future
public static void asyncMethod1() {
PermissionSet perSet = new PermissionSet();
perSet.Label = 'Apex Per Set';
perSet.Name = 'ApexPerSet';
insert perSet;
}
}

5. How to resolve Mixed DML Exception inside a test class?

@isTest
public class TestClass {

@testSetup
public static void setupTestData() {

PermissionSet perSet = new PermissionSet();


perSet.Label = 'Apex Per Set';
perSet.Name = 'ApexPerSet';
insert perSet;

User u = [SELECT Id FROM User WHERE Id =: UserInfo.getUserId() LIMIT 1];

System.runAs(u) {
Opportunity opp = new Opportunity();
opp.Name = 'Apex Opportunity';
opp.StageName = 'Closed Won';
opp.CloseDate = System.today();
insert opp;
}
}

@isTest
public static void myMethod() {}
}

6. Calling future method from trigger:-

Below is the trigger for the scenario that if Account isActive checkbox is false then
delete its child contacts

AccountTrigger.apxt

trigger AccountTrigger on Account (after update) {


if(Trigger.isAfter && Trigger.isUpdate) {
AccountTriggerHandler.deleteContacts(Trigger.new);
}
}

AccountTriggerHandler.apxc

public class AccountTriggerHandler {

public static void deleteContacts(List<Account> accNewList) {

Set<Id> accountIds = new Set<Id>();

for(Account acc : accNewList) {


if(acc.isActive__c == false) {
accountIds.add(acc.Id);
}
}

AsyncClass.asyncMethod1(accountIds);
}
}

AsyncClass.apxc

public class AsyncClass {

@future
public static void asyncMethod1(Set<Id> accountIds) {
delete [SELECT Id FROM Contact WHERE AccountId IN : accountIds];
}
}

7. What are HTTP Status Codes?

An HTTP status code is a server response to a browser’s request. When you visit a
website, your browser sends a request to the site’s server, and the server then
responds to the browser’s request with a three-digit code: the HTTP status code.

These status codes are the Internet equivalent of a conversation between your
browser and the server. They communicate whether things between the two are
A-okay, touch-and-go, or whether something is wrong. Understanding status codes
and how to use them will help you to diagnose site errors quickly to minimize
downtime on your site. You can even use some of these status codes to help search
engines and people access your site; a 301 redirect, for example, will tell bots and
people that a page that has moved somewhere else permanently.

The first digit of each three-digit status code begins with one of five numbers, 1
through 5; you may see this expressed as 1xx or 5xx to indicate status codes in that
range. Each of those ranges encompasses a different class of server response.

Use the below link to refer all the status codes and their uses:-
https://restfulapi.net/http-status-codes/

8. What is @future(callout=true)?

To make a Web service callout to an external service or API, you create an Apex
class with a future method that is marked with (callout=true).

If we do not use (callout=true) we’ll get the below error at the time of callouts:-
System.CalloutException: Callout not allowed from this future method. Please enable
callout by annotating the future method. eg: @Future(callout=true)

9. What are remote site settings in salesforce?

Remote Site Setting : It is baiscally used to access external website resources from a
Salesforce application for your organization. You can access these external websites
through Visualforce pages, Apex Callout, and via XmlHttpRequest calls.
And it is also used to avoid accessing malicious websites from Salesforce.com, the
website first needs to be registered with remote site settings. Once the site is
registered, it can be used within Salesforce.com.

● Before any Apex callout can call an external site, that site must be registered
in the Remote Site Settings page, or the callout fails. Salesforce prevents
calls to unauthorised network addresses.
● o add a remote site settings:
1. From Setup, enter Remote Site Settings in the Quick Find box, then select
Remote Site Settings.
2. Click New Remote Site.
3. Enter a descriptive term for the Remote Site Name.
4. Enter the URL for the remote site.
5. Optionally, enter a description of the site.
6. Click Save.

If no Remote Site setting are added you’ll get below error while callout:-
System.CalloutException: Unauthorized endpoint, please check
Setup->Security->Remote site settings. endpoint =
http://restapi.adequateshop.com/api/Tourist?page=2

10. Callout using future method:-

public class FutureCallout {

@future(callout=true)
public static void callExternalWebservice() {

Http h = new Http();

HttpRequest req = new HttpRequest();


req.setEndpoint('http://restapi.adequateshop.com/api/Tourist?page=2');
req.setMethod('GET');

HttpResponse res = h.send(req);

System.debug('Status Code : '+res.getStatusCode());


System.debug('Body : '+res.getBody());
}
}
21st July 2023

1. Test Class for Callouts

By default, test methods don’t support web service callouts, and tests that perform
web service callouts fail.
To prevent tests from failing and to increase code coverage, Apex provides the
built-in WebServiceMock interface and the Test.setMock method. Use
WebServiceMock and Test.setMock to receive fake responses in a test method.

● The class implementing the WebServiceMock interface can be either global or


public.
● You can annotate this class with @isTest because it is used only in a test
context. In this way, you can exclude it from your org’s code size limit of 6 MB.

Apex Test Classes will not let us conduct a HTTP callout; therefore, it cannot be used
to test External APIs. However, there is a solution wherein Apex has an interface
called HttpCalloutMock for standard callout tests.

2. Test class for the previous code:-

FutureCalllout_Test.apxc (Test Class)

@isTest
public class FutureCalllout_Test {

@isTest
public static void callExternalWebservice() {
Test.startTest();
Test.setMock(HttpCalloutMock.class, new CalloutMock());
FutureCallout.callExternalWebservice();
Test.stopTest();
}
}

CalloutMock.apxc (Mock class)

@isTest
public class CalloutMock implements HttpCalloutMock{
public HttpResponse respond(HttpRequest req) {

HttpResponse res = new HttpResponse();

res.setStatusCode(200);
res.setBody('Test JSON Body');

return res;
}
}

3. Advantages and Disadvantages of Future Methods:-

Advantages of @future annotation


● We can make a callout from Trigger using @future annotation
● When there are CPU time limit exceptions and SOQL 101 Exceptions we can
use @future and push the business logic that's not of that priority to get
executed in Asynchronous mode.
● We can increase the request timeout using @future annotation

Drawbacks with @future annotation


● We cannot invoke a future method within another @future method
● Future methods cannot be used in Batch Apex.
● @future method cannot return any data back.
● We cannot pass complex data types(List, Set, and Map), custom data types
to a future method. We always have to send primitive data types.
● You can call up to 50 @future methods per transaction.

Queueable Apex

1. What is a queueable apex in salesforce?

Queueable apex is an asynchronous apex method. It’s similar to the @future


method. By using this queueable interface, we can process an Apex that runs for a
long time (such as web service call outs and extensive database operations). The job
isadded to Apex job queue. System.enqueueJob method returns the job id; so, we
can easily monitor its progress, either through the Salesforce UI in the Apex Jobs
page, or by querying the record using AsyncApexJob object.

2. Advantage of using queueable Apex

Queueable jobs are similar to future methods in that they’re both queued for
execution, It has following benefit compared to future methods:

● Getting an ID for your job: When we submit our job by invoking the
System.enqueueJob method, the method returns the ID of the new job. This
ID corresponds to the ID of the AsyncApexJob record. We can use this ID to
identify job and monitor its progress, either through the Salesforce user
interface in the Apex Jobs page, or programmatically by querying your record
from AsyncApexJob.
● Using non-primitive types: Your queueable class can contain member
variables of non-primitive data types, such as sObjects or custom Apex types.
Those objects can be accessed when the job executes.
● Chaining jobs: You can chain one job to another job by starting a second job
from a running job. Chaining jobs is useful if you need to do some processing
that depends on another process to have run first.

3. How to declare a class a Queueable?

Implement the Queueable interface to make a Apex class as Queueable class. The
Queueable interface has execute method which must be implemented inside the
class.

public class QueueableClass implements Queueable{

public static void execute(QueueableContext qc) {


}
}

4. How to call a Queueable Class?

System.enqueueJob(new QueueableClass());

OR

QueueableClass queueableClassObj = new QueueableClass();


System.enqueueJob(queueableClassObj );
5. What is QueueableContext?

It is used to get the Id of the current Queueable Job.

public class QueueableClass implements Queueable{

public static void execute(QueueableContext qc) {


System.debug('Queueable Id : '+qc.getJobId());
}
}

6. How to get Id of Queueable Job?

There are 2 ways of getting Id of Queueable Job:-

1. Using the QueueableContext parameter in the execute method. (See the


above example).
2. Using System.enqueueJob(new class_name()). This method returns Id of the
Job.
Id queueableId = System.enqueueJob(new QueueableClass());

The only difference between above two meth iiods is 1st method returns 18 digit ID
and 2nd method returns 15 digit ID.

7. Queueable class example

The below queuable class will query “Test Opportunity Anonymous'' opportunity and
also create it’s parent account.

public class QueueableClass implements Queueable {

public static void execute(QueueableContext qc) {

Opportunity opp = [SELECT Id, AccountId FROM Opportunity WHERE Name =


'Test Opportunity Anonymous'];

Account acc = new Account();


acc.Name = 'Async Apex Account';
insert acc;
opp.AccountId = acc.Id;
update opp;
}
}

8. Test Class for Queueable Apex

● Always use Test.startTest() and Test.stopTest() in Test classes to call


Asynchronous Apex.
● For chaining Queueable you cannot call the chained Queueable. Use
!Test.isRunningTest in the Queueable Apex.

Below is the test class for #7 Queueable Class:-

@isTest
public class QueueableClass_Test {

@testSetup
public static void setupTestData() {
Test.startTest();

Opportunity opp = new Opportunity();


opp.Name = 'Test Opportunity Anonymous';
opp.CloseDate = System.today();
opp.StageName = 'Closed Won';
insert opp;

Test.stopTest();
}

@isTest
public static void QueueableClass() {
Test.startTest();
System.enqueueJob(new QueueableClass());
Test.stopTest();
List<Account> accList = [SELECT Id FROM Account];
System.assertEquals(1, accList.size());
}
}

Note:- You’ll get System.AsyncException: Maximum stack depth has been


reached, if you do not use !Test.isRunningTest for the chained queueable.
9. Chaining of Queueable Jobs

Calling one Queueable class from another and so on is called as chaining of jobs.
Maximum 5 chaining is allowed, which means you can chain 5 jobs (1 parent job and
4 child jobs).

Note:-
1. You can call only 1 queueable class from a single queueable class. If more
that 1 queueable is called below error is thrown:-
System.LimitException: Too many queueable jobs added to the queue: 2

2. Only 5 jobs can be chained. If more than 5 are chained below error is thrown:-
System.AsyncException: Maximum stack depth has been reached.

1st Queueable Class

public class QueueableClass1 implements Queueable {

public static void execute(QueueableContext qc) {


System.debug('Inside 1st Queueable');
System.enqueueJob(new QueueableClass2());
}
}

2nd Queueable Class

public class QueueableClass2 implements Queueable {

public static void execute(QueueableContext qc) {


System.debug('Inside 2nd Queueable');
System.enqueueJob(new QueueableClass3());
}
}

3rd Queueable Class

public class QueueableClass3 implements Queueable {

public static void execute(QueueableContext qc) {


System.debug('Inside 3rd Queueable');
System.enqueueJob(new QueueableClass4());
}
}

4th Queueable Class

public class QueueableClass4 implements Queueable {

public static void execute(QueueableContext qc) {


System.debug('Inside 4th Queueable');
System.enqueueJob(new QueueableClass5());
}
}

5th Queueable Class

public class QueueableClass5 implements Queueable {

public static void execute(QueueableContext qc) {


System.debug('Inside 5th Queueable');
}
}

All the above 5 Queueable classes are chained.


22nd July 2023

1. Call a Queueable from Trigger passing a parameter


sObject(Trigger.new)

Scenario:- Write a trigger on insert of Account and call Queueable where Queueable
will create a child contact for the account

AccountTrigger.apxt

trigger AccountTrigger on Account (after insert) {

if(Trigger.isAfter && Trigger.isInsert) {


AccountTriggerHandler.createChildContact(Trigger.new);
}
}

AccountTriggerHandler.apxc

public class AccountTriggerHandler {

public static void createChildContact(List<Account> accNewList) {


System.enqueueJob(new AccountTriggerQueueable(accNewList));
}
}

AccountTriggerQueueable.apxc

public class AccountTriggerQueueable implements Queueable{

public List<Account> accNewList = new List<Account>();

public AccountTriggerQueueable(List<Account> accNewList) {


this.accNewList = accNewList;
}

public void execute(QueueableContext qc) {

List<Contact> conToCreate = new List<Contact>();

for(Account acc : accNewList) {


Contact con = new Contact();
con.LastName = 'New Con Created';
con.AccountId = acc.Id;

conToCreate.add(con);
}

if(!conToCreate.isEmpty()) {
insert conToCreate;
}
}
}

2. Callouts using Queueable Apex

For making callouts implement Database.allowsCallouts interface along with


Queueable interface. Also make sure to add endpoint in Remote site settings.

public class CalloutQueueable implements Queueable, Database.allowsCallouts{

public void execute(QueueableContext qc) {


Http h = new Http();

HttpRequest req = new HttpRequest();


req.setEndpoint('http://restapi.adequateshop.com/api/Tourist?page=2');
req.setMethod('GET');

HttpResponse res = h.send(req);

System.debug('Status Code : '+res.getStatusCode());


System.debug('Body : '+res.getBody());

}
}

3. Limitations of Queueable Apex

● You can add up to 50 jobs to the queue with System.enqueueJob in a single


transaction.
● Only 5 chaining allowed. One parent and 4 childs.
● Can add only one job from an executing job with System.enqueueJob, means
that only child job can exist for parent queueable job
Assignment:-
Write Test class for the above #1 point trigger.

You might also like