Tag Archives: Salesforce

Queueable Apex in Salesforce

The class which implements the Queueable interface are basically called as Queueable apex class. This interface enables you to add jobs to the queue and monitor them, which is an enhanced way of running your asynchronous Apex code compared to using future methods. The interface has only one method execute which takes the parameter of QueableContext.

For Apex processes that run for a long time, such as extensive database operations or external Web service callouts, you can run them asynchronously by implementing the Queueable interface and adding a job to the Apex job queue. In this way, your asynchronous Apex job runs in the background in its own thread and doesn’t delay the execution of your main Apex logic. Each queued job runs when system resources become available. A benefit of using the Queueable interface methods is that some governor limits are higher than for synchronous Apex, such as heap size limits.

It allows you to submit jobs for asynchronous processing similar to future methods with with these additional benefits:
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.
Monitoring: When you submit your job by invoking the System.enqueueJob method, the method returns the ID of the AsyncApexJob record. You can use this ID to identify your job and monitor its progress, either through the Salesforce user interface in the Apex Jobs page, or programmatically by querying your record from AsyncApexJob.
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 sequential processing.

Example:
This example is an implementation of the Queueable interface. The execute method in this example inserts a new account.

public class QueueableExample implements Queueable {

    public void execute(QueueableContext context) {
        Account acc = new Account(Name='Biswajeet');
        Insert acc;        
    }
}

To add this class as a job on the queue, call this method:

ID jobID = System.enqueueJob(new AsyncExecutionExample());

After you submit your queueable class for execution, the job is added to the queue and will be processed when system resources become available. You can monitor the status of your job programmatically by querying AsyncApexJob or through the user interface Setup || Monitoring || Apex Jobs.

To query information about your submitted job, perform a SOQL query on AsyncApexJob by filtering on the job ID that the System.enqueueJob method returns.

AsyncApexJob jobInfo = [SELECT Status,NumberOfErrors FROM AsyncApexJob WHERE Id=:jobID];

Test class for Queueable Jobs:

@isTest
public class AsyncExecutionExampleTest {
    static testmethod void test1() {
        //startTest/stopTest block to force async processes to run in the test.
        Test.startTest();        
        System.enqueueJob(new AsyncExecutionExample());
        Test.stopTest();

        Account acct = [SELECT Name FROM Account WHERE Name='Biswajeet' LIMIT 1];
        System.assertNotEquals(null, acct);
        System.assertEquals('Biswajeet', acct.Name);
    }
}

Note:

  • The execution of a queued job counts once against the shared limit for asynchronous Apex method executions.
  • You can add up to 50 jobs to the queue with System.enqueueJob in a single transaction.
  • Limits.getQueueableJobs() helps to check how many queueable jobs have been added in one transaction.
  • No limit is enforced on the depth of chained jobs, which means that you can chain one job to another job and repeat this.
  • You can add only one job from an executing job with System.enqueueJob, means that only child job can exist for parent queueable job.
  • For Developer Edition and Trial organizations, the maximum stack depth for chained jobs is 5.

Difference Between Deactivate User and Freeze User in Salesforce

Deactivate User:

  • Deactivating a user in Salesforce means that user will not be deleted from the system but will no longer be able to log in to Salesforce and their records can be transferred to another user. They cannot be part of workflows or part of any automated processes.
  • Deactivating a user will be available user licenses available for use in your organization.
  • Deactivated users lose access to any records that were manually shared with them, or records that were shared with them as team members. Users higher in the role hierarchy relative to the deactivated users also lose access to those records. However, you can still transfer their data to other users and view their names on the Users page.

Freeze User:

  • Freezing a user in Salesforce means that only stops the user from being able to login.
  • In some cases, you can’t immediately deactivate a user (such as when a user is selected in a custom hierarchy field or a user that’s assigned as the sole recipient of a workflow email alert). To prevent users from logging into your organization while you perform the steps to deactivate them, you can freeze user accounts.
  • Freezing user accounts doesn’t make their user licenses available for use in your organization.

Apex Trigger Context Variables

All triggers define implicit variables that allow developers to access runtime context.
These variables are contained in the System.Trigger class:

Variable Usage
isExecuting Returns true if the current context for the Apex
code is a trigger, not a Visualforce page,
a Web service, or an executeanonymous()
API
call.
isInsert Returns true if this trigger
was fired due to an insert operation, from the Salesforce user
interface, Apex,
or the API.
isUpdate Returns true if this trigger
was fired due to an update operation, from the Salesforce user
interface, Apex,
or the API.
isDelete Returns true if this trigger
was fired due to a delete operation, from the Salesforce user
interface, Apex,
or the API.
isBefore Returns true if this trigger
was fired before any record was saved.
isAfter Returns true if this trigger
was fired after all records were saved.
isUndelete Returns true if this trigger
was fired after a record is recovered from the Recycle Bin (that is, after an undelete operation from the Salesforce user
interface, Apex,
or the API.)
new Returns a list of the new versions of the sObject records. This
sObject list is only available in insert, update,
and undelete triggers, and the
records can only be modified in before triggers.
newMap A map of IDs to the new versions of the sObject records. This map
is only available in before
update
, after
insert
, after
update
, and after
undelete
triggers.
old Returns a list of the old versions of the sObject records. This
sObject list is only available in update and delete
triggers.
oldMap A map of IDs to the old versions of the sObject records. This map
is only available in update and
delete triggers.
size The total number of records in a trigger invocation, both old and
new.

Salesforce Named Credentials

  • Salesforce introduced Named Credentials in the Spring’15 release.
  • Named credential specifies the URL of a callout endpoint and its required authentication parameters in one definition.
  • No need to handle Remote site settings of the Named credential callout URL.
  • Named credentials separate the URL from the authentication, making it easier to make changes to both the endpoint URL and authentication if needed.
  • It supports Basic Password authentication and OAuth 2.0 authentication protocols.
  • You can configured Named credentials to use an org-wide named principal or to use per-user authentication so that users can manage their own credentials.

Apex HTTP Callout Without Named Credential:

String username = 'username';
String password = 'password';
String endpoint = 'https://testapi.com';

Http http = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint(endpoint);

//Add basic authentication header to the callout
Blob headerValue = Blob.valueOf(username + ':' + password); 
String authHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); 
req.setHeader('Authorization', authHeader);

HttpResponse response = http.send(req);
System.debug('response-' + response);

Example:
Setup | Quick Find – Search Named Credentials | New Named Credential

Create Named Credential as per your requirement:

Apex HTTP Callout With Named Credential:

Http http = new Http();
HttpRequest req = new HttpRequest();

req.setEndpoint('callout:Sample_API/some_path');
req.setMethod('POST');

HTTPResponse response = http.send(req);
System.debug('response-' + response);

Global Picklist Value Set in Salesforce

Global Picklist or Picklist Value Set is an Universal Picklist Values, which can be applied to any custom picklist fields that you create both on standard and custom objects.

Lets take an example, I have an object called “Student” and “Student Application” in these two object I have to create a picklist field called “Language”. So, here I’ve created a “Picklist Value Set” and used it on both object “Student Application”.

Click Setup || App Setup || Create || Picklist Value Set || Click ‘New’

Create “Language” Picklist Value Set:

Create “Language” Picklist from Picklist Value Set in “Student” and “Student Application” object:

Check “Language” Picklist Value Set, where it is used:

Note: You can have up to 500 picklist global value sets in an org. Each global value set, or restricted picklist, can contain a mix of 1,000 active and inactive values. Unrestricted picklists can have up to 1,000 active values. There’s no limit on the number of custom picklists that use global picklist value sets.

Picklist Value Set Considerations:

  • Validation rules are still defined at the field level, and are not part of the Picklist Value Set definition. This means, you can have the Business Unit picklist field on Account to respect a validation rule; and the same field on the Contact object not.
  • It is possible to create a mutli-select picklist field using a Picklist Value Set definition. However, in such cases the “replace” functionality available on regular picklist fields are not available.
  • Also, a picklist field created based on a Picklist Value Set cannot be used as a dependent picklist. It can still be used as a controlling picklist field. This is a known and documented limitation.