Change Data Capture in Salesforce

A Change Data Capture event, or change event, is a notification that Salesforce sends when a change to a Salesforce record occurs as part of a create, update, delete, or undelete operation. The notification includes all new and changed fields, and header fields that contain information about the change. Change Data Capture can generate change events for all custom objects defined in your Salesforce org and a subset of standard objects.

When to use Change Data Capture:

  • Receive notifications of Salesforce record changes, including create, update, delete, and undelete operations.
  • Capture field changes for all records.
  • Get broad access to all data regardless of sharing rules.
  • Get information about the change in the event header, such as the origin of the change, which allows ignoring changes that your client generates.
  • Perform data updates using transaction boundaries.
  • Use a versioned event schema.
  • Subscribe to mass changes in a scalable way.
  • Get access to retained events for up to three days.

Subscribe to Change Event Channel:
Salesforce offers multiple ways to subscribe to a change event channel. For external application to Salesforce, we can use Streaming API, or tools and libraries based on CometD, an open-source library that simulates push technology. Streaming API provides a subscription mechanism based on CometD.
To process data changes in Salesforce, we can write an Apex trigger for the change event. Change event triggers are called as Asynchronous Apex Trigger.

Example:
To get change notifications, we have to enable Change Data Capture for the required object. Here I have enabled the Lead Object Change Data Capture, for Change Notifications to listen to Lead record changes.

Go to Setup | Enter Change Data Capture in the Quick Find box, and click Change Data Capture | In Available Entities, select Lead object and click the > arrow |
Click Save.

Return Custom Error Messages From Apex Controller In Salesforce Lightning

Sample Code:

We can use System.AuraHandledException to return custom error message from server side apex controller to lightning component in Salesforce.

string errorMessage = 'Your Error Message';
AuraHandledException auraEx = new AuraHandledException(errorMessage);
auraEx.setMessage(errorMessage);
throw auraEx;

Get Record Type Id With Dynamic sObject Name & Record Type Name

Sample Methods:

 //Get recordTypeId by Object Name & Record Type Name
    public static Id recordTypeIdByName(string objAPIName, string recTypeName){
        Id recTypeId;
        if(String.isNotBlank(objAPIName) && String.isNotBlank(recTypeName)){
            recTypeId= Schema.getGlobalDescribe().get(objAPIName).getDescribe().getRecordTypeInfosByName().get(recTypeName).getRecordTypeId();
        }  
        return recTypeId;  
    }
    
    //Get recordTypeId by Object Name & Record Type Developer Name
    public static Id recordTypeIdByDevName(string objAPIName, string recTypeDevName){
        Id recTypeId;
        if(String.isNotBlank(objAPIName) && String.isNotBlank(recTypeDevName)){
            recTypeId= Schema.getGlobalDescribe().get(objAPIName).getDescribe().getRecordTypeInfosByDeveloperName().get(recTypeDevName).getRecordTypeId();
        }  
        return recTypeId;  
    }
    
    //Get all recordTypeId Map (Name as key and recordTypeId as value) by Object Name
    public static Map<String,Id> recordTypeMap(string objAPIName){
        Map<String, Id> recTypeNameIdMap = new Map<String,Id>();
        if(String.isNotBlank(objAPIName)){
            for(Schema.RecordTypeInfo recInfo : Schema.getGlobalDescribe().get(objAPIName).getDescribe().getRecordTypeInfosByName().values()){
                recTypeNameIdMap.put(recInfo.getName(),recInfo.getRecordTypeId());
            }
        }
        return recTypeNameIdMap;
    }

//Get Record Type Id or developer name by passing developer name or Id
public static string getRecordTypeInfoByIdOrDeveloperName(String recordType){
    string returnValue = '';
    Boolean isValidId = recordType instanceOf Id;
    
    for(Schema.SObjectType objType : Schema.getGlobalDescribe().Values()){
        Schema.DescribeSObjectResult doResult = objType.getDescribe(SObjectDescribeOptions.DEFERRED);
        if(isValidId){
            if(doResult.getRecordTypeInfosById().get(recordType) != null){
                returnValue = doResult.getRecordTypeInfosById().get(recordType).getDeveloperName();
                break;
            }
        }else{
            if(doResult.getRecordTypeInfosByDeveloperName().get(recordType) != null){
                returnValue = doResult.getRecordTypeInfosByDeveloperName().get(recordType).getRecordTypeId();
                break;
            }
        }
    }
    returnValue;
}