Thursday 25 March 2021

Overview of Governor Limits in Salesforce

INTRODUCTION

Salesforce is a cloud computing service as a software (SaaS) company. It is specialized in customer relationship management (CRM). Salesforce provides a range of cloud solutions that allow businesses to connect with different types of data and deliver services to their customers in various ways.

Multitenancy is a fundamental technology that operates alongside cloud computing. Since Salesforce and Apex operate in a multitenant setting, the term "Salesforce Governor Limits" is used.

In order to ensure the practical use of the resources available on the Force.com platform, Salesforce has regulatory restrictions. Salesforce sets certain limitations in order to effectively use the code. 

What are Salesforce Governor Limits?

As we understand, Apex runs in a multi-tenant environment, meaning that all customers and organizations share a single resource. It is important to ensure that no one monopolizes the resources, which is why Salesforce.com has provided a series of restrictions that monitor and limit code execution. Salesforce sets limitations in order to effectively use the resources, and they are known as Governor limits in Salesforce.  

The governor can throw errors and suspend program execution if any of its limitations are exceeded. As a result, we must ensure that our code is flexible and does not surpass the Governor's limits. All these limits are applied on a per-transaction basis.

Types of Salesforce Governor Limits:

  • Per-transaction Apex Limits  
  • Per-transaction Certified Managed Package Limits 
  • Size-specific Apex Limits 
  • Static Apex Limits 
  • Lightning Platform Apex Limits 
  • Miscellaneous Apex Limits

Per-transaction Apex Limits

Per-transaction Apex Limits count for each Apex transaction. While we discuss Batch Apex, for every execution of a batch of records in the Execute method, these limits are reset. For the synchronous and asynchronous Apex, the following table lists the limits.

Description 

Synchronous Limit 

Asynchronous Limit 

Total number of SOQL queries issued

100 

200 

Total number of records retrieved by SOQL queries 

50,000 

Total number of records retrieved by  
Database.getQueryLocator 

10,000 

Total number of SOSL queries issued 

20 

Total number of records retrieved by a single SOSL query 

2,000 

Total number of DML statements issued

150 

The total number of records processed as a result of DML statements, Approval Process, or database.emptyRecycleBin 

10,000 

Total stack depth for any Apex invocation that recursively fires triggers due to insertupdate, or delete statements

16 

Total number of callouts (HTTP requests or Web services calls) in a transaction 

100 

Maximum cumulative timeout for all callouts (HTTP requests or Web services calls) in a transaction 

120 seconds 

Maximum number of methods with the future annotation allowed per Apex invocation 

50 

0 in batch and future contexts; 1 in queueable context 

Maximum number of Apex jobs added to the queue with System.enqueueJob 

50 

1 

Total number of send email methods allowed 

10 

Total heap size

6 MB 

12 MB 

Maximum CPU time on the Salesforce servers

10,000 milliseconds 

60,000 milliseconds 

Maximum execution time for each Apex transaction 

10 minutes 

Maximum number of push notification method calls allowed per Apex transaction 

10 

Maximum number of push notifications that can be sent in each push notification method call 

2,000 

Maximum number of EventBus.publish calls for events configured to publish immediately 

150 


Per Transaction Certified Managed Package Limits

Certified Managed packaged
are the managed packages that have passed the AppExchange security review. Salesforce ISV Partners develop certified managed packages that have specific namespaces and are installed in your org. They get their own set of limits for most limits per transaction. 

The number of certified namespaces that can be invoked in a single transaction does not have a limit. The precondition, however, is that the number of operations should be carried out in a separate namespace that should not reach the per-transaction limits.  
And there's a cap on the total number of operations that can be performed in a transaction through namespaces. The overall limit is 11 times the limit per namespace. 

This table summarizes Collective limits for cross-namespace.

Description 

Collective Cross-Namespace Limit 

Total number of SOQL queries issued 

1,100 

Total number of records retrieved by Database.getQueryLocator 

110,000 

Total number of SOSL queries issued 

220 

Total number of DML statements issued 

1,650 

Total number of callouts (HTTP requests or Web services calls) in a transaction 

1,100 

Total number of send email methods allowed 

110 


For certified managed packages, all per-transaction thresholds count individually, except for: 
  • The maximum transaction execution time 
  • The maximum number of unique namespaces  
  • The maximum CPU time  
  • The total heap size
Irrespective of how many certified managed packages are running in the same transaction, these caps count for the whole transaction. We have to understand that the script from an AppExchange package, not produced and not approved by a Salesforce ISV Partner, does not have its own separate governor limits. The overall org governor limits are counted against any services used by the package. Based on managed package namespaces, collective resource messages and alert emails are created as well. 

Size-specific Apex Limits

These limits related to the code. These size-dependent limitations are specifically intended to ensure that classes, causes, organs, etc. do not contain oversized items.

Description 

Limit 

Maximum number of characters for a class 

1 million 

Maximum number of characters for a trigger 

1 million 

The maximum amount of code used by all Apex code in an org

6 MB 

Method size limit

65,535 bytecode instructions in compiled form 

Static Apex Limits

There are also more additional Apex governor limits, i.e., along with various transactions, for various forms of callouts, queries, loops, records, and batch sizes. These Limits are applied across all transactions. 

Description 

Limit 

Default timeout of callouts (HTTP requests or Web services calls) in a transaction 

10 seconds 

Maximum size of callout request or response (HTTP request or Web services call)

6 MB for synchronous Apex or 12 MB for asynchronous Apex 

Maximum SOQL query run time before Salesforce cancels the transaction 

120 seconds 

Maximum number of class and trigger code units in a deployment of Apex 

5,000 

Apex trigger batch size

200 

For loop list batch size 

200 

Maximum number of records returned for a Batch Apex query in Database.QueryLocator 

50 million 

Lightning Platform Apex Limits

For apex transactions, the limits listed below are not valid, so the lightning platform manages these limits.
 

Description 

Limit 

The maximum number of asynchronous Apex method executions (batch Apex, future methods, Queueable Apex, and scheduled Apex) per a 24-hour period

250,000 or the number of user licenses in your org multiplied by 200, whichever is greater 

Number of synchronous concurrent transactions for long-running transactions that last longer than 5 seconds for each org.

10 

Maximum number of Apex classes scheduled concurrently 

100. In Developer Edition orgs, the limit is 5. 

Maximum number of batch Apex jobs in the Apex flex queue that are in Holding status 

100 

Maximum number of batch Apex jobs queued or active concurrently

5 

Maximum number of batch Apex job start method concurrent executions

1 

Maximum number of batch jobs that can be submitted in a running test 

5 

Maximum number of test classes that can be queued per 24-hour period (production orgs other than Developer Edition)

The greater of 500 or 10 multiplied by the number of test classes in the org 

Maximum number of test classes that can be queued per 24-hour period (sandbox and Developer Edition orgs)

The greater of 500 or 20 multiplied by the number of test classes in the org 

Maximum number of query cursors open concurrently per user

50 

Maximum number of query cursors open concurrently per user for the Batch Apex start method 

15 

Maximum number of query cursors open concurrently per user for the Batch Apex execute and finish methods 

5 

Miscellaneous Apex Limits

Connect in Apex 
Each writing operation counts one DML statement against the governor limit for classes in the ConnectApi namespace. Calls to the ConnectApi method are also subject to rate limiting. A ConnectApi.RateLimitException is given when you reach the rate cap. 

Event Reports 
For a user who is not a system administrator, the maximum number of records that an event report returns is 20,000; for system administrators, 100,000. 

MAX_DML_ROWS limit in Apex testing 
In a single, synchronous Apex test execution context, the maximum number of rows that can be inserted, updated, or deleted is limited to 450,000. If you have reached the cap, you will see this error: Your run all tests is consuming too many DB resources. 

SOQL Query Performance 
The system will terminate nonselective SOQL queries to avoid long execution times. When a non-selective query in a trigger executes against an object that contains more than 200,000 documents, developers receive an error message.

Advantages of Governor Limits

  • Apex has coding limitations that are entirely different or unique. 
  • Governor limits help us remain inside the required apex coding place. 
  • Governor limits prevent other org to take up a lot of space in memory. 

How to avoid Governor Limits

We need to make sure that our code is flexible and does not surpass the governor limits. But sometimes we need to avoid these limits to fulfill the requirements. We can avoid salesforce governor limits using the following process: 
  • In For Loops, do not use SOQL queries and DML statements
  • Ensure that the Apex code manage more than one record at a time 
  • Querying vast amounts of data
  • Use Batch Apex for 50,000 records 
  • Organize multiple triggers on the same page 
  • Use collection for loops 
  • Use @future annotation
  • Use of the Limits Apex Methods to Avoid Hitting Governor Limits 

SuMMARY

Salesforce has several different forms of governor limits, and which help us to become more effective developers and administrators. We can avoid them using the best approaches. Click Here for more details.

If you have any questions you can reach out our Salesforce Consulting team here.

Thursday 18 March 2021

Display Picklist values dynamically in lightning component


Requirement:
While working on one of the user stories of Engineering sector project for a client based out of Tampa, FL, USA;  there was a requirement to provide an interface that would display selected Industry (Pick-list field) values for Accounts on the fly while performing Mass Edit.

Challenge: 

Mass Edit feature was implemented using the Custom Lightning component. And, t
here is no out-of-the-box (OOTB) feature available to display selected pick-list values in the in lightning component, while bulk edit is being performed.

Solution:
To overcome this limitation, we have created an Apex class that contains the mechanism to retrieve the list of Industry (pick-list) field values from the Account object.

This Apex class is then used by Custom Lightning Component (BulkEdit.Cmp) which displays the list of Accounts. Using component.get ("v.pickvalues") in DynamicPickController component, we are retrieving selected pick-list values from the Parent Component (BulkEdit.cmp). 

Then Industry pick-list values are being compared with the values that have been retrieved from Parent Component. If field values are matched, it will set the selected Industry field value.

If values are not matched, then it will set the first value from the pick list options.

Once comparison is done,  value is set to the attribute IndustryPick that we have defined in the Custom DynamicPickController.Cmp component.

BulkEdit.cmp
<aura:iteration items="{!v.selectedlst}" var="ac" >
                                    <c:DynamicPickController selectedOptions = '{!v.selectedlst}'
                                                  Name = '{!ac.lstTelLineAccLocUserobject2.Name}'
                                                  Industry = '{!ac.lstTelLineAccLocUserobject2.Industry}'
                                                  pickvalues = '{!v.pickvalues}'
                                                  />
</aura:iteration>

DynamicPickController.Js
doInit : function(component, event, helper) {
        var IndustryPick = [];
        for(var i = 0 ; i < component.get("v.pickvalues").length ; i++)
        {
            if(component.get("v.pickvalues")[i] == component.get("v.Industry"))  
            {
                IndustryPick.push({"label":component.get("v.pickvalues")[i], "value":component.get("v.pickvalues")[i], "selected":true})
            }
            else
            {
                IndustryPick.push({"label":component.get("v.pickvalues")[i], "value":component.get("v.pickvalues")[i]})
            }
        }
        component.set("v.IndustryPick", IndustryPick);
    }

DynamicPickController.Cmp
<aura:attribute name="pickvalues" type="list"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<lightning:select name="Industry" label="Select a Industry:" aura:id="Industry" value="{!v.Industry}">
                <aura:iteration items="{!v.IndustryPick}" var="option">
                    <option text="{!option.label}" value="{!option.label}" selected="{!option.selected}"/>
                </aura:iteration>
</lightning:select>

Output:

If you have any questions you can reach out our Salesforce Consulting team here.

Thursday 11 March 2021

Hyperlink a Record in lightning:datatable

Requirement:

While working on one of the user stories of healthcare sector project for a client based out of Atlanta, GA, USA, there was a need of displaying a list of Contacts in lightning:datatable having 2 columns with hyperlinks. One is contact name and other is account name. And clicking on it, it should redirect to contact record and account record respectively.

Challenge: 

The challenging part was, there is no standard functionality available in the lightning:datatable for a hyperlink field to redirect to record detail page.

Solution:

To overcome this limitation, we'd to make changes in column format for a Contact name and Account name fields with type:'url' and also need to add typeAttributes as display below.

{ label: 'Name', fieldName: 'contacturl', type: 'url', typeAttributes: { label: { fieldName: 'Name' }, target: '_blank' } }, { label: 'Account Name', fieldName: 'accounturl', type: 'url', typeAttributes: { label: { fieldName: 'AccountName' }, target: '_blank' } }




See below code files - ApexController, Component files, and output to have a clear understanding.

ContactController
public class ContactController {
    @AuraEnabled
    public static List < Contact > fetchContacts() {
        return [ SELECT Id, Name, Account.Id,
                Account.Name,Phone,Department,LeadSource FROM Contact];        
    }
}
The contact controller class is referenced by the HyperLinkDatable component to display retrieved contacts as a data table.

HyperLinkDatable.cmp
<aura:component implements="force:appHostable" controller="ContactController">
               
    <aura:attribute type="Contact[]" name="conList"/>
    <aura:attribute name="columns" type="List"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
   
    <lightning:datatable data="{!v.conList}"
                         columns="{!v.columns}"
                         keyField="Id"
                         hideCheckboxColumn="true"/>
   
</aura:component>

HyperLinkDatableController.js
({
    
    doInit : function( component, event, helper ) {        
        component.set('v.columns', [
            { label: 'Name', fieldName: 'contacturl', type: 'url',
             typeAttributes: { label: { fieldName: 'Name' }, target: '_blank' }},
            {label: 'Department',fieldName: 'Department', type: 'Text' },
            {label: 'Lead Source',fieldName: 'LeadSource', type: 'Phone' },
            {label: 'Phone',fieldName: 'Phone', type: 'Phone' },
            { label: 'Account Name', fieldName: 'accounturl', type: 'url',
             typeAttributes: { label: { fieldName: 'AccountName' }, target: '_blank' } }
        ]);
        //getting contact records
        var action = component.get( "c.fetchContacts" );
        action.setCallback(this, function( response ) {            
            var state = response.getState();
            if ( state === "SUCCESS" ) {
                var records = response.getReturnValue();
                //setting value for url
                records.forEach( function( record ) {
                    record.AccountName = record.Account.Name;
                    record.accounturl = '/' + record.Account.Id;
                    record.Name = record.Name;
                    record.contacturl = '/' + record.Id; 
                });
                component.set( "v.conList", records );                
            }            
        });
        $A.enqueueAction( action );        
    }    
})

After this, we need to create a Lightning App to integrate all of the files as a solution.

<aura:application
access="GLOBAL" extends="force:slds"> <c:HyperLinkDatatable/> </aura:application>

Output:


If you have any questions you can reach out our Salesforce Consulting team here.

Thursday 4 March 2021

Lightning Web Component : Validate/Format currency field using lighting- input Attribute


INTRODUCTION/SCENARIO

While working on the Lightning Web Components for our most recent project, a Banking website for our client's business in Naples, Florida, USA. we came across a scenario where had to validate the input field accepting a value between 1 to 150,000 and formatted with leading $ sign. 

CHALLENGE

We implemented this functionality using LWC, but challenging part was formatting the input value with $ sign using an input element of HTML. 

APPROACH / SOLUTION 

We've used lightning-input instead of an HTML input element. The Lightning input field itself has attributes with validation as well as a format for currency. We only need to set attributes as per the requirement and, it would perform the desired action in the OOTB manner. 

A Lightning Web Component renders UI that must include an HTML file, a JavaScript file, and a metadata configuration file. 


Every UI component must have an HTML file with the root tag <template>.


myComponent.html


<template>
    <div class="slds-card">

        <!--show hide the form based on the validation-->
        <template if:true={showAmountInputBox}>

            <div class="slds-p-around_medium">
                <h2>Tell us what you need</h2>
                <lightning-input type="number" formatter="currency" step="1" 
                class="form-control is-invalid" onfocusout={checkAmountValue} value={inputAmount}
                label="How much would you like to borrow?">
                </lightning-input>
            </div>

        </template>

    <!-- Check on focusout of the box if amount is between $1 to $150000 -->
    <template if:true={greaterAmount}>
        <p class="slds-p-around_medium">Amount must not be greater than $150000. </p>
    </template>
    <template if:true={lesserAmount}>
        <p class="slds-p-around_medium">Amount must not be less than $1. </p>
    </template>
    </div>
</template>

myComponent.js


import { LightningElement,track } from 'lwc';

export default class myComponent extends LightningElement {

    @track inputAmount; // to store amount from input box
    @track greaterAmount=false; // check if amount is greater than $150000
    @track lesserAmount=false; // check if amount is less than $1
  
// handle onfocusout event to verify input amount

 checkAmountValue(event){
    const typedValue = event.target.value;
        
    if(typedValue !== undefined){
        event.target.value=typedValue;
    }

    this.inputAmount=typedValue;
    this.showPrevNext = false; 

    if(this.inputAmount>150000){ 
        this.greaterAmount=true; 
        this.lesserAmount=false; 
     } 
     else if(this.inputAmount<1){ 
        this.lesserAmount=true; 
        this.greaterAmount=false; 
    }
    else if(this.inputAmount === "" || this.inputAmount == null || this.inputAmount < 150000 || this.inputAmount >1){
        this.greaterAmount=false; 
        this.lesserAmount=false; 
   }
    
 }
    
}

myComponent.js-meta.xml



<?xml version="1.0" encoding="UTF-8"?> 
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="myComponent"><apiVersion>45.0</apiVersion> 
    <isExposed>true</isExposed> 
    <targets> 
        <target>lightning__AppPage</target> 
        <target>lightning__RecordPage</target> 
        <target>lightning__HomePage</target> 
        <target>lightningCommunity__Page</target> 
        <target>lightningCommunity__Default</target> 
    </targets> 
</LightningComponentBundle> 

OUTPUT


SUMMARY

Hence, we have validation implemented with the formatting applied using the attributes of Lightning Input without any custom function OR JavaScript. 

If you have any questions you can reach out to our Salesforce Consulting team here.