Interview Questions on Queueable Apex in Salesforce
Hello everyone, Welcome in SFDC Worlds...!!
Last month I started the "Interview Series on Asynchronous Apex (i.e. Batch Apex, Apex Scheduler, Future Methods and Queueable Apex)".
In this blog series, I am starting last part of interview series on Asynchronous Apex - "Queueable Apex". I am covering use case, real time scenario questions and concepts. I have tried to cover all scenario based questions which are often asked by Salesforce Apex Developer in an interview.
Understanding the Queueable Apex in Salesforce
Understanding about the future methods and queueable apex first we will learn about what is synchronous process and why we need use asynchronous apex.
Synchronous Process :
In simple terms you can assume Synchronous as Sequential. In Synchronous process the thread waits for the task to be completed and then moves to the next task Sequentially. All the tasks are completed in a single thread.
The common example of a Synchronous apex is Trigger.
Example: Imagine you have a requirement like when you insert a contact or delete a contact update the account with number of contacts and then you need to perform web service callout for that account. Using the synchronous apex is no-no situation because we always need to deal with the governor limits and apex CPU time. So how can we solve this situation.
we solve this problem using the asynchronous process?
The answer is yes, asynchronous process will execute in its own thread it is independent.
Asynchronous process :
An asynchronous process is a process or function that executes a task “in the background” without the user having to wait for the task to finish.
In Asynchronous apex the thread does not waits for the task to be completed to move on to the next task. The tasks are run in different threads all together. These threads run in independent silos whenever the system is free.
Most common example is the @Future annotation.
So how many asynchronous flavors we have in salesforce?
I would say as of today we have total of 4 flavors. Out of 4 do we have any asynchronous process that is annotation based. So, we need not to write a separate class and handle the asynchronous process.
Queueable Apex
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).
Queueable apex and future method both run sdfs asynchronously but queueable apex provides these additional benefits.
1. Getting Id of your Job : ID JobId =system.enqueueJob(qe);
2. Chaining Job : In Queueable Apex we can chain one job to another.
3. Using Non-Primitive Data 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.
Before jumping on to queueable apex lets try to remember some of the limitations that future method is having.
MIND IT !
1. Can we pass objects, apex types as a parameter to the future method?
No, we cannot pass them as arguments. So, how can I do that?
2. Can I monitory future jobs?
No, it is a method that resides in an apex class and it will execute whenever the resources are available. So, how can we resolve this? Is there any way that I can implement asynchronous jobs and monitor them?
3. Can we implement chain process?
Forget with future because we cannot call future method from another future method. So, how can we resolve this?
The only solution to the above 3 problems is to implement the Queueable Apex. What is Queueable Apex and how can I implement them. Oh! Wait for lots of questions.
The Queueable Apex is a hybrid class. Why are you calling it a hybrid class? Yes, what I mean is that it is designed in a way by combining Batch Apex and Future Apex. So, it means do we have to write start, execute and finish method again like batch. As I said it is a combination not exact replica. No, you don't need to write start and finish methods. All you need is the execute method. How good is it right?
Queueable Apex Syntax
We need to implement Apex Class with Queueable Interface which contains only one method execute. We also need to implement DatabaseAllowsCallouts in case if you wanted to process the callouts from the Queueable apex.
public class QueueableApexExample implements Queueable { public void execute(QueueableContext context) { // some process } }
Execute Queueable Apex
Execute the Queueable apex with System.enqueueJob method which will return the job Id. Once you enqueue a new job, you get a job ID that you can actually monitor from the ApexJobs sections or by using AsyncApexJob object.
ID jobID = System.enqueueJob(new QueueableApexExample());
Queueable Apex Example
In this example we will append learnfrenzy at the end of account name
public class AccountQueueableExample implements Queueable { public List<Account> accList ; public AccountQueueableExample(List<Account> accList){ this.accList = accList ; } public void execute(QueueableContext context) { for(Account acc :accList){ // Update the Account Name acc.Name = acc.Name + 'learnfrenzy'; } update accList; } }
Run the job from the execute anonymous with below code
List<Account> accList = [Select Id , Name from Account ]; ID jobID = System.enqueueJob(new AccountQueueableExample(accList)); System.debug('jobID'+jobID);
Test class for Queueable Apex
@isTest public class AccountQueueableExampleTest { @testSetup static void setup() { List<Account> accounts = new List<Account>(); // add 100 accounts for (Integer i = 0; i < 100; i++) { accounts.add(new Account( name='Test Account'+i )); } insert accounts; } static testmethod void testQueueable() { // query for test data to pass to queueable class List<Account> accounts = [select id, name from account where name like 'Test Account%']; // Create our Queueable instance AccountQueueableExample accQObj = new AccountQueueableExample(accounts); // startTest/stopTest block to force async processes to run Test.startTest(); System.enqueueJob(accQObj); Test.stopTest(); // Validate the job ran System.assertEquals(100, [select count() from account where Name like = '%learnfrenzy%']); } }
Queueable Job chaining
One of the best features of Queueable Apex is job chaining. If you ever need to run jobs sequentially, Queueable Apex could make your life much easier. To chain a job to another job, submit the second job from the execute() method of your queueable class. You can add only one job from an executing job, which means that only one child job can exist for each parent job. For example, if you have a second class called SecondJob that implements the Queueable interface, you can add this class to the queue in the execute() method as follows:
public class FirstJob implements Queueable { public void execute(QueueableContext context) { // Processing logic here // Chain this job to next job by submitting the next job System.enqueueJob(new SecondJob()); } }
Limitations for Queueable Apex
let’s look at what are limitations for queueable apex.
1. How many jobs can we schedule from queueable apex? Only one.
2. Can I chain the jobs from test class? No, you cannot do that unless you want to end up with errors.
3. How many jobs I can add by using system.enqueueJob for a single transaction? 50
4. What is the stack depth for chaining the jobs? In developer edition it is limited to 5 including the parent job.
5. Which one is easy to modify queueable or future? The answer is future as it resides in the apex class and easy to remove the annotation “@future”. Does it impact the test class no it won’t impact the test class? How cool it is right switching between synchronous to asynchronous and vice versa.
Differences between Future and Queueable Apex
MIND IT !
FUTURE APEX | QUEUEABLE APEX |
---|---|
It is annotation based so we can use the same apex class to write the future method. Syntax: @future |
It is a class which implements’ queueable interface. Syntax: public class CLASS_NAME implements Queueable{} |
We cannot monitor the jobs | We can monitor the jobs based on the job Id. |
we cannot call a future from another future or batch apex. The limit on future method for single apex invocation is 50. | We can chain the Queueable jobs and the stack depth in developer org is 5 and in enterprise edition you can chain 50 jobs. |
Future method supports only primitive datatypes | Queueable supports both primitive and non-primitive data types. |
Interview Series
Hey guys, from this post i am starting interview series on Asynchronous Queueable Apex which are very helpful in interviews.
In this blog series, I have tried to cover Queueable Apex based questions that are often asked from a Salesforce developer in an interview.
Let start the first interview series on Queueable Apex (Between Interviewer & Interviewee).
Interview Series: Batch Apex
Interviewer: What is Queueable Apex?
Interviewee: It’s an extension of the Future Methods. It uses the Queueable interface which is an enhanced way of running your asynchronous Apex code compared to using future methods. The limitations which Future methods have, through Queueable Apex, we can overcome them.
Interviewer: How does Queueable Apex differ from Future methods?
Interviewee: Queueable Apex is similar to future methods in that they’re both queued for execution, but they provide us these additional benefits.
• When you queue a Queueable Apex, you get a job ID, that can be used to trace it easily, which is not possible in case of future methods.
• You can use non-primitive datatypes in Queueable Apex, like objects and sObjects, which is not possible in case of future methods, because it supports only primitive data types as params.
• You can chain jobs, by calling another starting a second job from a running job, which is not possible in case of future methods, because we can’t call another future method from a future context.
Interviewer: When will we use future methods instead of Queueable?
Interviewee: You use future methods instead of queueable is when your functionality is sometimes executed synchronously, and sometimes asynchronously. It’s much easier to refactor a method in this manner than converting to a queueable class. This is handy when you discover that part of your existing code needs to be moved to async execution. You can simply create a similar future method that wraps your synchronous method.
Interviewer: Can you write a sample Queueable Job?
Interviewee: Create a class, implement the Queueable interface, and override the execute method.
public class QueueableApexExample implements Queueable { public void execute(QueueableContext context) { //some process } }
Interviewer: What is QueueableContext?
Interviewee: It is an interface that is implemented internally by Apex, and contains the job ID. Once you queue the Queueable Job, the Job Id will be returned to you, by apex through QueueableContext’s getJobId() method.
Interviewer: How can I queue Queueable Job(QueueableApexExample)?
Interviewee: Using System.enqueueJob Method.
ID jobID = System.enqueueJob(new QueueableApexExample());
Interviewer: How can I use this Job Id to trace the Job?
Interviewee: Just perform a SOQL query on AsyncApexJob by filtering on the job ID.
AsyncApexJob jobInfo = [SELECT Status,NumberOfErrors FROM AsyncApexJob WHERE Id=:jobID];
Interviewer: I have 200 records to be processed using Queueable Apex, How Can I divide the execution Context for every 100 records?
Interviewee: Similar to future jobs, queueable jobs don’t process batches, so you can’t divide the execution Context. It will process all 200 records, in a single execution Context.
Interviewer: Can I do callouts from a Queueable Job?
Interviewee: Yes, you have to implement the Database.AllowsCallouts interface to do callouts from Queueable Jobs.
Interviewer: How Chaining works in Queueable Apex?
Interviewee: Chaining allows us to customize the execution order of a set of jobs in a process.
let’s say there are N jobs, A, B, C and so on. We have a process in which A has to run first and gives output to B and then B runs and gives output to C and so on. So, instead of calling the individual Queueable Jobs explicitly, we can link the calls, logically within Queueable Jobs, as shown Below
public class A implements Queueable { public void execute(QueueableContext context) { // Chain this job to next job by submitting the next job System.enqueueJob(new B()); } } public class B implements Queueable { public void execute(QueueableContext context) { // Chain this job to next job by submitting the next job System.enqueueJob(new C()); } } public class C implements Queueable { public void execute(QueueableContext context) { // Chain this job to next job by submitting the next job System.enqueueJob(new D()); } } and so on...
Interviewer: Can I chain a job that has implemented allowsCalloutsfrom a Job that doesn’t have?
Interviewee: Yes, callouts are also allowed in chained queueable jobs.
Interviewer: How many numbers of jobs, can be chained at a time?
Interviewee: You can add only one job from an executing job, which means that only one child job can exist for each parent job.
Since, no limit is enforced on the depth of chained jobs, you can chain one job to another. You can repeat this process with each new child job to link it to a new child job.
Interviewer: How many numbers of jobs, I can queue using System.enqueueJob()
at a time?
Interviewee: You can add up to 50 jobs to the queue with System.enqueueJob in a single transaction in Synchronous apex. In asynchronous transactions, you can add only one job to the queue.
Interviewer: Can I call Queueable from a batch?
Interviewee: Yes, But you’re limited to just one System.enqueueJob
call per execute in the Database.Batchable class. Salesforce has imposed this limitation to prevent explosive execution.
Interviewer: If I have written more than one System.enqueueJob
call, what will happen?
Interviewee: System will throw LimitException stating “Too many queueable jobs added to the queue: N”.
Interviewer: How can we handle this error, without using a try-catch?
Interviewee: We can check whether the current count of queuable jobs has exceeded the limit or not, if not, queue them.
Limits.getQueueableJobs()
returns the currently queued jobs count.
Limits.getLimitQueueableJobs()
returns the limit.
If(Limits.getQueueableJobs() < Limits.getLimitQueueableJobs()) { //System.enqueueJob() }
Interviewer: I have a use case to call more than one Queueable Jobs from a Batch apex, how can I achieve it?
Interviewee: Since we can’t call more than one Queueable Job from each execution Context, We can go for scheduling the Queueable Jobs.
The approach is we need to first check how many queueable jobs are added in the queue in the current transaction by making use of Limits class. If the number has reached the limit, then call a schedulable class and enqueue the queueable class from the execute method of a schedulable class.
Interviewer: how to test a Queueable Job?
Interviewee: A queueable job is an asynchronous process. To ensure that this process runs within the test method, the job is submitted to the queue between the Test.startTest and Test.stopTest block.
Also, The ID of a queueable Apex job isn’t returned in test context — System.enqueueJob returns null in a running test.
Interviewer: how to test Chaining?
Interviewee: Interviewee: You can’t chain queueable jobs in an Apex test. So you have to write separate test cases for each chained queueable job. Also, while chaining the jobs, add a check of Test.isRunningTest() before calling the enqueueJob.
Test.isRunningTest() Returns true if the currently executing code was called by code contained in a test method, false otherwise
public class A implements Queueable { public void execute(QueueableContext context) { // Test to make sure that Unit test are not running before chaining // the call. We don’t want to chain another job during a Unit test run. if(!Test.isRunningTest()){ System.enqueueJob(new B()); } } }
Use case :
Create an Queueable Apex class that inserts Contacts for Accounts.
Create a Queueable Apex class that inserts the same Contact for each Account for a specific state
Apex Class Name: addPrimaryContact
/*********************************************************************************************************************** Apex Class Name : addPrimaryContact Version : 1.0 Created Date : 14.02.2022 Function : addPrimaryContact class Modification Log : * Developer Date Description * ---------------------------------------------------------------------------------------------------------------------- * Saurabh Samir 14/02/2022 Initial version ***********************************************************************************************************************/ public class addPrimaryContact { // Declaring the varibales private Contact contact; private String state; //== Defualt constructor with parameters as account and state value public addPrimaryContact(Contact contactRecord, String stateValue) { this.contact = contactRecord; this.state = stateValue; } public void execute(QueueableContext context) { List<Account> accounts = getAccounts(state); // Condition to check for the List is empty if(accounts.size() > 0) { List<Contact> updateContacts = new List>Contact<(); // Loop to iterate over the list of Accounts for(Account account : accounts) { Contact con = new Contact(); con.AccountId = account.Id; updateContacts.add(con); } // Condition to check if the contact list is empty if(updateContacts.size() > 0) { Database.SaveResult[] results = Database.insert(updateContacts, false); // Loop to iterate over the DML Operation results for(Database.SaveResult result : results) { if(result.isSuccess()) { System.debug('Successufully inserted the contact. Contact Id : ' + result.getId()); } else { for(Database.Error error : result.getErrors()) { System.debug('Contact failed to Insert with error code : ' + error.getStatusCode() + ' with error Message : ' +error.getMessage()); } } } } } } // Method to fetch the List of account records based on the State value. public static List<Account> getAccounts(string state) { return [SELECT ID, Name, (SELECT Id, FirstName, LastName FROM Contacts) FROM Account WHERE BillingState = :state]; } }
In class we are passing parameters as contact and state value. The default constructor will receive this and we created 2 global variables, one for the contact and the other for the state value to hold and use them in our downstream logic.
The execute method is first doing a query on the Account object and fetching all the records matching the state value, then we are checking if there are any query results if so we are iterating over the query results and then We are creating new contacts for those accounts.
Here we used the Database.saveResult
to do the DML operation. What if I ask you to send an email to admin for failed accounts you can use chain process to send email to admins. Let us try for yourself as an assignment.
Hopefully, this interview series on Queueable Apex will help to understand Queueable Apex clearly and crack the interview.
All the Best...!!
For more details about Queueable Apex please refer to Control Processes with Queueable Apex trailhead
(5) Comments
Im really thankful to your interview questions. if possible please provide Interview Questions on Triggers also
Hi Venu M, Thanks for your feedback! Please find the links below for our most popular blogs on "Salesforce Interview Question on Triggers" and "Trigger Scenario Based Questions in Salesforce". https://learnfrenzy.com/blog/trigger-scenario-based-questions-in-salesforce https://learnfrenzy.com/blog/salesforce-interview-questions-on-triggers
I am really thankful . great work .if possible please provide Interview Questions on community cloud, integration, lwc .
Awesome Job Saurabh. Keep it up. Thank you so much. Please provide some questions related to LWC and Integrations.
Great website on interview questions and the concepts related to APEX.