Hi Friends, Before starting this set please go through Basic Interview Questions on Batch Apex
Q. What is apex Flex Queue?
The Apex Flex queue enables you to submit up to 100 batch jobs for execution. Any jobs that are submitted for execution are in holding status and are placed in the Apex Flex queue. Up to 100 batch jobs can be in the holding status.
Q. Can you change order of job in Apex Flex Queue?
Jobs are processed first-in first-out—in the order in which they’re submitted. You can look at the current queue order and shuffle the queue, so that you could move an important job to the front, or less important ones to the back.
Boolean isSuccess = System.FlexQueue.moveBeforeJob(jobToMoveId, jobInQueueId);
Q. How many job can run concurrently?
The system can process up to five queued or active jobs simultaneously for each organization
Q. Explain status of jobs in Apex Flex Queue?
Holding : Job has been submitted and is held in the Apex flex queue until system resources become available to queue the job for processing.
Queued : Job is awaiting execution.
Preparing : The start method of the job has been invoked. This status can last a few minutes depending on the size of the batch of records.
Processing : Job is being processed.
Aborted : Job aborted by a user.
Completed : Job completed with or without failures.
Failed : Job experienced a system failure.
Q. Let’s say, I have 150 Batch jobs to execute, Will I be able to queue them in one go?
Once you run Database.executeBatch, the Batch jobs will be placed in the Apex flex queue and its status becomes Holding. The Apex flex queue has the maximum number of 100 jobs, Database.executeBatch throws a LimitException and doesn’t add the job to the queue. So atmost 100 jobs can be added in one go.
Also, if Apex flex queue is not enabled, the Job status becomes Queued, Since the concurrent limit of the queued or active batch is 5, so atmost 5 batch jobs can be added in one go.
Q. Can I Use FOR UPDATE in SOQL using Database.QueryLocator?
No, We can’t. It will throw an exception stating that “Locking is implied for each batch execution and therefore FOR UPDATE should not be specified”
Q. Can I query related records using Database.QueryLocator?
Yes, You can do subquery for related records, but with a relationship subquery, the batch job processing becomes slower. A better strategy is to perform the subquery separately, from within the execute method, which allows the batch job to run faster.
Q. Can you write a batch class blueprint?
global class batchExample implements Database.Batchable<sObject> { global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) { // collect the batches of records or objects to be passed to execute } global void execute(Database.BatchableContext bc, List<sObject> records){ // process each batch of records } global void finish(Database.BatchableContext bc){ // execute any post-processing operations } }
Q. Difference between query locator and iteratable?
Iterable and querylocator are both used for apex batches.
QueryLocator can be used when your data that needs to be executed in batch can be fetched using query. And it has limit of 5million reccords.
Wherein When records can not be filtered by SOQL and scope is based on some cusotm business logic, then we go for iterable. And it has limit of 50K records
Q. Let’s say Record A has to be processed before Record B, but Record B came in the first Batch and Record A came in the second batch. The batch picks records which are unprocessed every time it runs. How will you control the processing Order?
The Processing order can’t be controlled, but we can bypass the record B processing before Record A. We can implement Database.STATEFUL and use one class variable to track whether Record A has processed or not. If not processed and Record B has come, don’t process Record B. After all the execution completes, Record A has already been processed so Run the batch again, to process Record B.
Q. Let’s say, we have run an apex batch to process 1000 records, and It is running with batch size 200. Now, while doing DML on 395th record, an error occurred, What will happen in that case?
In batches, If the first transaction succeeds but the second fails, the database updates made in the first transaction are not rolled back.
Since the batch size is 200, so the first batch will be processed completely and all data will be committed to DB. In seconds batch, if we are committing records using normal DML statements like insert, update than the whole batch will be rollbacked. So records 201 to 400 will not be processed.
Q. How can you stop a Batch job?
The Database.executeBatch and System.scheduleBatch method returns an ID that can be used in System.abortJob method.
Q. Give Example of Iterable?
global class MyTest implements Iterable<Account> { } global Iterable<Account> start(Database.BatchableContext bc) { //This should return object of the class that has implemented iterable interface. return new MyIterableClass(); }
Q. Write batch apex program to get phone no. in the Contact object with the phone no. in the Corresponding Account object. Where Contact is a child of Account.
global class ContactUpdate implements Database.Batchable<sObject> { global Database.QueryLocator start(Database.BatchableContaxt bc) { String query = 'select id, phone, Account.phone from Contact'; return Database.getQueryLoactor(query); } global void execute(Database.BatchableContext bc, List<Contact> scope) { for(contact con: scope) { con.phone = con.Account.phone; Conlist.add(con); } update con; } global void finish(Database.Batchable Context bc) { } }
Q. Create an Apex Class to invoke the batch apex job.
public class TestMyBatch { public string cname{get; set;} public pageReference show() { customerBatch mybatch = new customerBatch (cname); Id id = Database.executeBatch (mybatch, 400); system.debug ('My Job id' + id); } }
Q. Call we call future method in batch class?
Methods declared as the future aren’t allowed in the classes that implement Database.Batchable interface.
Methods declared as future can’t be called from Batch Apex class.
Q. How to use Aggregate queries in Batch Apex
Aggregate queries don’t work in Batch Apex because aggregate queries doesn’t support queryMore(). They run into the error ‘Aggregate query does not support queryMore(), use LIMIT to restrict the results to a single batch’
To fix this error what we should do.
1. Create an Apex class implements Iterator<AggregateResult>.
2. Create an Apex class implements Iterable<AggregateResult>.
3. Implementing to Database.Batchable<AggregateResult>, and Using Iterable at start execution in Batch Apex.
Q.What is the difference between database.batchable & database.batchablecontext bc?
1. database.batchable is an interface.
2. database.batchableContext is a context variable which store the runtime information eg jobId
Q. Which platform event can fire from batch ?
The BatchApexErrorEvent object represents a platform event associated with a batch Apex class.
It is possible to fire platform events from batch apex. So whenever any error or exception occurs, you can fire platform events which can be handled by different subscriber.
Batch class needs to implement “Database.RaisesPlatformEvents” interface in order to fire platform event.
global class SK_AccountProcessBatch implements Database.Batchable<sObject>,Database.RaisesPlatformEvents{ //batch logic }
Q. What if you change the name of Execute method to Execute1 in the batch class? Will the batch job still run?
Go ahead and change Execute to Excute1 and try saving the class.
Output
Class batchUpdateAccountsContacts must implement the method: void Database.Batchable<SObject>.execute(Database.BatchableContext, List<SObject>)
Finding
It won let you save the batch class as it says class must implement execute method
Is there a way in which I can call a future method from a batch Job?
Calling a future method is not allowed in the Execute method, But a web service can be called. A web service can also call an @future method. So, we can define a web service having a future method invocation and call the web service from the execute method of Batch Job.
what is batchable context? why we need it?
1. database.batchable is an interface.
2. database.batchableContext is a context variable which store the runtime information eg jobId
It gives the context of the batch class. Represents the parameter type of a batch job method and contains the batch job ID.
This interface is implemented internally by Apex.
What is use of batch job Id which we get from database.batchableContext?
It gets information about the job
AsyncApexJob jobInfo = [SELECT Status, NumberOfErrors
FROM AsyncApexJob WHERE Id = :jobID];
How to know it is batch job?
We have to create an global apex class which extends Database.Batchable Interface because of which the salesforce compiler will know,
this class incorporates batch jobs.
Can i write method other than start, execute, finish?
No we cannot write other method. Whatever method is there is Database.batchable interface only that we can call.
Can we keep start, finish, execute method?
As the class implements batchable interface, we need to define the methods.
Difference between query locator and iteratable?
Iterable return types have no hard maximum scope size, unlike QueryLocator, which will not allow more than 2,000 records per execute call.
If logic is complex and not filtered through query then we will use iteratable.
Why batch class is global?
global makes a class usable by code outside of a managed package.
How to execute batch job?
batchAccountUpdate b = new batchAccountUpdate();
database.executeBatch(b);
What is database.stateful?
It is an interface which maintains state of variables.
eg- send failure of number of records failed to salesforce admin over email
How to identify stateful variables in batch class?
If we declare variable global then automatically it becomes stateful
insert vs database.insert?
If we use the DML statement (insert), then in bulk operation if error occurs, the execution will stop and Apex code throws an error which can be handled in try catch block.
If DML database methods (Database.insert) used, then if error occurs the remaining records will be inserted / updated means partial DML operation will be done.
database.insert vs Stateful?
Database.insert – It show failure for records where complete batch is failed and wont pick the records where some records are passed for a particular batch and therefore we need to use database.stateful
What we can do from finish method?
We can do post processing logic
Is finish asynchronous?
Finish method is sync because it does not go in queue. Only execute method is async.
What we do to do callout from batch?
1. Use Database.allowcallout interface on class level
2. Do callout from execute method
Can we do callout from start method?
We can do from start using iteratable method but it will hit the limit so best is to do from execute.
When we use database.shedulable interface?
The class that implements this interface can be scheduled to run at different intervals.
Can we call future from batch ?
No, we cannot because future is method and cannot be qeueued.
Can we call queuable from batch?
We can call because it is a job and can be queued. It can be called from finish.
Can I call a batch from another batch?
We can call from finish.
Can we get records without querying a batch?
We will do using iterator
from Batch A we will call batch B
In Batch B constructor will pass success records
In this case we dont need to query but we will use iterator
Q. What is the upper limit of scope parameter if batch class returns iterable?
If the start method of the batch class returns an iterable, the scope parameter value has no upper limit. However, if you use a high number, you can run into other limits.
Count the “Customer – Direct” account records processed by the batch class?
Batch Apex is stateless by default. That means for each execution of your execute method, you receive a fresh copy of your object. All fields of the class are initialized, static and instance. If your batch process needs information that is shared across transactions, one approach is to make the Batch Apex class itself
stateful by implementing the Database.Stateful interface.
global class AccountBatchApex implements Database.Batchable<sObject>, Database.Stateful{ global integer numberofDirectCustomers = 0; global Database.QueryLocator start(Database.BatchableContext bc){ String soqlQuery = 'SELECT Name, AccountNumber, Type From Account'; return Database.getQueryLocator(soqlQuery); } global void execute(Database.BatchableContext bc, List<Account> scope){ for (Account acc : scope){ if(acc.Type.equals('Customer - Direct')){ numberofDirectCustomers++; } } } global void finish(Database.BatchableContext bc){ } }
Q.Give example of Batch Apex class for deleting records?
public class BatchDelete implements Database.Batchable<sObject> { public String query; public Database.QueryLocator start(Database.BatchableContext BC){ return Database.getQueryLocator(query); } public void execute(Database.BatchableContext BC, List<sObject> scope){ delete scope; DataBase.emptyRecycleBin(scope); } public void finish(Database.BatchableContext BC){ } }
Q. Update account description, number of employees, contact last name using batch apex. Get the failure record ids in the email. Also schedule the job for every Monday ?
global class batchUpdateAccountsContacts implements Database.Batchable <sObject>,Database.Stateful,Schedulable { global batchUpdateAccountsContacts(){ } Set<id> successRecord = new Set<id>(); Set<id> failRecord = new Set<id>(); global Database.QueryLocator start(Database.BatchableContext info){ String SOQL='Select id,name,NumberOfEmployees, description,(select id, name from contacts) from Account'; return Database.getQueryLocator(SOQL); } global void execute(Database.BatchableContext info, List<Account> scope){ List<Account> accsToUpdate = new List<Account>(); List<Contact> cUpdate = new List<Contact>(); for(Account a : scope) { a.description ='Test'; a.NumberOfEmployees = 70; accsToUpdate.add(a); for (Contact c:a.contacts){ c.lastname = 'test+a'; cUpdate.add(c); } } Database.SaveResult[] srList = Database.update(accsToUpdate, false); Database.SaveResult[] srList1 = Database.update(cUpdate, false); for (Database.SaveResult sr : srList) { if (sr.isSuccess()) { // Operation was successful, so get the ID of the record that was processed successRecord.add(sr.getId()); } else { for(Database.Error err : sr.getErrors()) { } failRecord.add(sr.getId()); } } for (Database.SaveResult sr : srList1) { if (sr.isSuccess()) { successRecord.add(sr.getId()); } else { for(Database.Error err : sr.getErrors()) { } failRecord.add(sr.getId()); } } } global void finish(Database.BatchableContext info){ // Get the ID of the AsyncApexJob representing this batch job // from Database.BatchableContext. // Query the AsyncApexJob object to retrieve the current job's information. AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email FROM AsyncApexJob WHERE Id = :info.getJobId()]; // Send an email to the Apex job's submitter notifying of job completion. Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {a.CreatedBy.Email}; mail.setToAddresses(toAddresses); mail.setSubject('Account and contact update' + a.Status); mail.setPlainTextBody ('The batch Apex job processed ' + a.TotalJobItems + ' batches with '+ a.NumberOfErrors + ' failures.'+successRecord+'successRecordids: '+ 'failRecordids: '+ failRecord); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } global void execute(SchedulableContext SC){ database.executeBatch(new batchUpdateAccountsContacts(),100); //for cron expression // String cronexpression = ‘0 0 0 ? * * *’ // System.schedule(‘Testing’, cronexpression, testobj); } }
Q. Explain Batch Apex With Webservice Callout
global class AccountBatchApex implements Database.Batchable<sObject>, Database.AllowsCallouts{ global Database.QueryLocator start(Database.BatchableContext bc){ String soqlQuery = 'SELECT Name, AccountNumber, Type From Account'; return Database.getQueryLocator(soqlQuery); } global void execute(Database.BatchableContext bc, List<Account> scope){ for (Account acc : scope){ if(acc.Type.equals('Customer - Direct')){ try{ HttpRequest request = new HttpRequest(); HttpResponse response = new HttpResponse(); Http http = new Http(); String username = 'YourUsername'; String password = 'YourPassword'; Blob headerValue = Blob.valueOf(username + ':' + password); String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); request.setHeader('Authorization', authorizationHeader); request.setHeader('Content-Type', 'application/json'); request.setEndpoint('Your Endpoint URL'); request.setMethod('POST'); request.setBody('Information to Send'); response = http.send(request); if (response.getStatusCode() == 200) { String jsonResponse = response.getBody(); System.debug('Response-' + jsonResponse); } } catch(Exception){ System.debug('Error-' + e.getMessage()); } } } } global void finish(Database.BatchableContext bc){ } }
Q. Create three account records, one with missing required information. Once the code is executed then the two records are saved to the database. The one record which is not saved should print error ?
Account[] accts = new List<Account>{ new Account(Name='Account1'), new Account(), new Account(Name='Account3') }; Database.SaveResult[] sr = Database.insert(accts, false); for (Database.SaveResult sr : sr) { if (sr.isSuccess()) { // Operation was successful, so get the ID of the record that was processed System.debug('Successfully inserted account. Account ID: ' + sr.getId()); } else { for(Database.Error err : sr.getErrors()) { system.debug('err'+err); System.debug('The following error has occurred.'); System.debug(err.getStatusCode() + ': ' + err.getMessage()); System.debug('Account fields that affected this error: ' + err.getFields()); } }
thank you for great effort to make these kind of videos