10 Salesforce Apex Classes Every Developer Should Know

10 Salesforce Apex Classes Every Developer Should Know Salesforce Shastras

When you are diving into, the huge ocean of Salesforce development! Navigating through it’s many tools and features is, a task of high intimidation. Amongst these, Apex classes is, standing as the backbone, of custom functionalities in the Salesforce ecosystem. In this blog post will aim to illuminate a light on 10 Salesforce Apex Classes Every Developer Should Know.

Let’s dig deep, shall we?

The Power of Apex

Apex is a OOPS programming language provided by Salesforce. It’s a strongly typed, object-oriented language that allows developers to execute flow and transaction control statements on the Salesforce platform server, in conjunction with calls to the API. Understanding and utilizing the right Apex classes can not only streamline your development process but also open up a plethora of customization options that can be tailored to specific business needs.


1. The System Class: The Root of All Apex

At the heart of Apex’s extensive library lies the System class. This class provides a collection of static methods that perform operations related to limits, logging, debugging, and testing. A deep dive into the System class can offer insights into:

Debugging and Logging

  • System.debug(logLevel, message): This method is crucial for developers to understand the inner workings and data manipulations happening within their code at runtime.
  • System.assert(), System.assertEquals(), and System.assertNotEquals(): These methods are vital for implementing test classes, ensuring your code behaves as expected.
public class SampleTestClass {
    
    public static void testMethod() {
        // Example of System.debug
        String logLevel = 'INFO';
        String message = 'Debugging information';
        System.debug(logLevel, message);
        
        // Example of System.assert
        Integer num1 = 5;
        Integer num2 = 10;
        System.assert(num1 < num2, 'num1 should be less than num2');
        
        // Example of System.assertEquals
        Integer expectedValue = 100;
        Integer actualValue = 100;
        System.assertEquals(expectedValue, actualValue, 'Values should be equal');
        
        // Example of System.assertNotEquals
        String expectedString = 'Hello';
        String actualString = 'World';
        System.assertNotEquals(expectedString, actualString, 'Strings should not be equal');
    }
}

Understanding Limits

  • Limits: Knowing governor limits is integral for efficient Apex development, you can use Limits class to retrieve information about various governor limits. Below is a sample class demonstrating how you can use Limits class to get information about different governor limits.
public class LimitInfo {
    
    public static void displayLimits() {
        Integer limitSoqlQueries = Limits.getLimitQueries();
        Integer limitSoqlRows = Limits.getLimitQueryRows();
        Integer limitSoslQueries = Limits.getLimitDmlStatements();
        Integer limitSoslRows = Limits.getLimitDmlRows();
        Integer limitEmailInvocations = Limits.getEmailInvocations();
        Integer limitQueueableJobsBatchSize = Limits.getLimitQueueableJobs();
        Integer limitAsyncCalls = Limits.getLimitAsyncCalls();
        Integer limitCallouts = Limits.getCallouts();
        System.debug('SOQL Queries Limit: ' + limitSoqlQueries);
        System.debug('SOQL Rows Limit: ' + limitSoqlRows);
        System.debug('SOSL Queries Limit: ' + limitSoslQueries);
        System.debug('SOSL Rows Limit: ' + limitSoslRows);
        System.debug('Email Invocations Limit: ' + limitEmailInvocations);
        System.debug('Queueable Jobs Batch Size Limit: ' + limitQueueableJobsBatchSize);
        System.debug('Async Calls Limit: ' + limitAsyncCalls);
        System.debug('Callouts Limit: ' + limitCallouts);
      }
}

2. The Database Class: Handling DML Operations

Salesforce data manipulation language (DML) operations are at the core of data handling, and the Database class offers methods that provide more flexibility and control compared to traditional DML statements like insert, update, or delete.

Key Methods and Their Use-Cases

  • Database.insert(records, allOrNone): This method allows you to insert records with a choice to either allow partial success (by setting allOrNone to false) or require all records to be inserted successfully.
  • Database.query(queryString): Dynamically querying records enables developers to construct more versatile and responsive applications.
public class DatabaseOperations {

    public static void insertRecords(List<Account> records, Boolean allOrNone) {
        // Insert records with the specified behavior
        Database.SaveResult[] results = Database.insert(records, allOrNone);
        
        // Iterate through the results to check success or failure
        for (Database.SaveResult result : results) {
            if (result.isSuccess()) {
                System.debug('Record with Id: ' + result.getId() + ' was inserted successfully.');
            } else {
                for(Database.Error error : result.getErrors()) {
                    System.debug('Error occurred while inserting record: ' + error.getMessage());
                }
            }
        }
    }
    
    public static List<Account> queryAccounts(String queryString) {
        // Execute the query and return the result
        return Database.query(queryString);
    }
}

3. The Trigger Class

Understanding the context of execution is pivotal in writing efficient triggers. Apex provides the Trigger class, which houses context variables offering insights into the state of the data and operation being performed.

Utilizing Context Variables

  • Trigger.New: A collection of new records in an insert or update trigger.
  • Trigger.OldMap: A map of IDs to the old versions of the sObjects before the update or delete operation.
trigger AccountTrigger on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    // This trigger will run before and after different types of operations on the Account object
    
    if (Trigger.isBefore) {
        if (Trigger.isInsert) {
            // Logic before inserting Account records
            for (Account acc : Trigger.new) {
                // Perform actions on the new records being inserted
            }
        } else if (Trigger.isUpdate) {
            // Logic before updating Account records
            for (Account oldAcc : Trigger.old) {
                // Perform actions on the old records before they are updated
            }
            for (Account newAcc : Trigger.new) {
                // Perform actions on the new records being updated
            }
        } else if (Trigger.isDelete) {
            // Logic before deleting Account records
            for (Account acc : Trigger.old) {
                // Perform actions on the records being deleted
            }
        }
    } else if (Trigger.isAfter) {
        if (Trigger.isInsert) {
            // Logic after inserting Account records
            for (Account acc : Trigger.new) {
                // Perform actions on the new records that have been inserted
            }
        } else if (Trigger.isUpdate) {
            // Logic after updating Account records
            for (Account oldAcc : Trigger.old) {
                // Perform actions on the old records after they have been updated
            }
            for (Account newAcc : Trigger.new) {
                // Perform actions on the new records after they have been updated
            }
        } else if (Trigger.isDelete) {
            // Logic after deleting Account records
            // Note: You cannot access Trigger.new in after delete context
            for (Account acc : Trigger.old) {
                // Perform actions on the records that have been deleted
            }
        } else if (Trigger.isUndelete) {
            // Logic after undeleting Account records
            for (Account acc : Trigger.new) {
                // Perform actions on the records that have been undeleted
            }
        }
    }
}
trigger AccountTrigger on Account (before update) {
    // This trigger runs before updating Account records
    
    // Accessing old records map
    Map<Id, Account> oldMap = Trigger.oldMap;
    
    // Accessing new records map
    Map<Id, Account> newMap = Trigger.newMap;
    
    // Iterate through the old records map
    for (Id accountId : oldMap.keySet()) {
        Account oldAccount = oldMap.get(accountId);
        // Perform actions on the old version of the record
    }
    
    // Iterate through the new records map
    for (Id accountId : newMap.keySet()) {
        Account newAccount = newMap.get(accountId);
        // Perform actions on the new version of the record
    }
}

These variables are indispensable for writing triggers that interact intelligently with data, ensuring that your business logic executes seamlessly across different scenarios.


4. The Test Class: Ensuring Code Quality

Apex testing is not just a best practice; it’s a requirement for deployment. The Test class provides methods that facilitate the creation of test data and the execution of test scenarios, ensuring your application is both robust and reliable.

Methods to Know

  • Test.startTest() and Test.stopTest(): These methods delineate a test scenario, allowing you to test governor limit consumption separately from the setup phase of your test.
  • Test.setMock(): It allows for mocking external callouts, making it possible to test integrations without hitting actual endpoints.

Example

Let’s assume we have a simple Apex class AccountService which makes a callout to an external HTTP service to retrieve account information:

public class AccountService {
    public static List<Account> fetchAccountsFromExternalService() {
        // Code to make HTTP callout and retrieve account information
        // For simplicity, let's assume the callout is made to an external service
        // and returns a list of accounts
        return new List<Account>();
    }
}

now, let’s write a test class for AccountService. We’ll use Test.startTest() and Test.stopTest() to demarcate the portion of code where we’re testing the callout:

@isTest
private class AccountServiceTest {

    // Mock class to simulate the HTTP callout response
    private class MockHttpResponseGenerator implements HttpCalloutMock {
        public HTTPResponse respond(HTTPRequest req) {
            // Create a mock HTTP response
            HTTPResponse res = new HTTPResponse();
            res.setHeader('Content-Type', 'application/json');
            res.setBody('{"Id": "001R000001OoAKI", "Name": "Test Account"}');
            res.setStatusCode(200);
            return res;
        }
    }

    @isTest
    static void testFetchAccountsFromExternalService() {
        // Set up mock HTTP callout
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

        Test.startTest();

        // Call the method being tested
        List<Account> accounts = AccountService.fetchAccountsFromExternalService();

        Test.stopTest();

        // Assert the results
        System.assertEquals(1, accounts.size());
        System.assertEquals('001R000001OoAKI', accounts[0].Id);
        System.assertEquals('Test Account', accounts[0].Name);
    }
}

5. The Http Class: Making Callouts

Integrating Salesforce with external services requires making HTTP callouts. The Http class along with HttpRequest and HttpResponse classes enable developers to seamlessly connect and interact with external APIs.

A Simple Callout Example

Constructing a HttpRequest, setting its endpoint and method, and then using an Http instance to send the request is a straightforward process that opens up endless integration possibilities.

// Import necessary classes
import http.*;

public class HttpCalloutExample {
    
    // Method to make HTTP callout
    public static void makeCallout() {
        // Instantiate a new HTTP request object
        HttpRequest req = new HttpRequest();
        
        // Set the endpoint URL for the request
        req.setEndpoint('https://api.example.com/resource');
        
        // Set the HTTP method (GET, POST, etc.)
        req.setMethod('GET');
        
        // Instantiate a new HTTP object to send the request
        Http http = new Http();
        
        try {
            // Send the HTTP request and store the response
            HttpResponse res = http.send(req);
            
            // Check if the request was successful (status code 200)
            if (res.getStatusCode() == 200) {
                // Process the response body
                String responseBody = res.getBody();
                System.debug('Response: ' + responseBody);
            } else {
                // Handle the error response
                System.debug('Error: ' + res.getStatus() + ' - ' + res.getStatusText());
            }
        } catch (Exception e) {
            // Handle any exceptions
            System.debug('Exception: ' + e.getMessage());
        }
    }
}

6. The Batchable Interface: Processing Large Data Sets

Salesforce provides the Database.Batchable<SObject> interface for processing records in batches, allowing for operations that exceed governor limits for DML rows or SOQL queries.

Implementing Batch Class

Implementing a class that implements Database.Batchable<SObject> involves defining three methods: start(), execute(), and finish(). This structure is essential for operations on large data sets, ensuring that your application can scale efficiently.

global class MyBatchable implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC) {
        // Query to fetch records for processing
        String query = 'SELECT Id, Name FROM Account';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Account> scope) {
        // Processing logic for each batch of records
        for (Account acc : scope) {
            // Example processing: updating the Account Name
            acc.Name = acc.Name + ' Processed';
        }
        // Update processed records
        update scope;
    }
    
    global void finish(Database.BatchableContext BC) {
        // Any post-processing logic can go here
    }
}

7. The Schedulable Interface: Automating Operations

For operations that need to occur on a schedule, Salesforce provides the Schedulable interface. Implementing this interface in a class allows it to be scheduled either programmatically using the System.schedule method or through the Salesforce UI.

global class MySchedulableClass implements Schedulable {
    
    global void execute(SchedulableContext sc) {
        // Your logic to be executed when the job is scheduled
        // This could be any Salesforce operations such as querying records, updating records, sending emails, etc.
        System.debug('Schedulable job executed at: ' + DateTime.now());
    }
}

Key Points in Scheduling

Understanding Cron expressions is crucial for setting up schedules. This feature elevates the automation capabilities within Salesforce, allowing for regular data maintenance tasks, batch job initiations, or custom reminders.

String cronExp = '0 0 0 15 3 ? 2022'; // Example cron expression for running at midnight on the 15th of March 2022
MySchedulableClass scheduledJob = new MySchedulableClass();
System.schedule('My Scheduled Job', cronExp, scheduledJob);

8. The Messaging Class: Email and SMS Communications

Salesforce isn’t just about data; it’s also about communication. The Messaging class provides methods for sending emails and SMS messages, enabling applications to communicate with users directly from within Salesforce.

Sending Emails Made Easy

  • Creating Messaging.SingleEmailMessage instances, setting recipients, subject, and body, and then sending them with Messaging.sendEmail() is a straightforward process for integrating email communications into your Salesforce applications.
// Create a new instance of Messaging.SingleEmailMessage
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

// Set the recipients of the email
email.setToAddresses(new List<String>{'recipient@example.com'});

// Set the sender email address
email.setReplyTo('sender@example.com');
email.setSenderDisplayName('Your Name'); // optional

// Set the email subject
email.setSubject('Example Subject');

// Set the email body
email.setPlainTextBody('This is an example email body.');

// If you want to send HTML content, you can use setHtmlBody instead
// email.setHtmlBody('<html><body><p>This is an example email body.</p></body></html>');

// Optionally, you can set additional email fields such as CC, BCC, etc.
// email.setCcAddresses(new List<String>{'cc@example.com'});
// email.setBccAddresses(new List<String>{'bcc@example.com'});
// email.setFileAttachments(); // You can also attach files if needed

// Send the email
Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{email});

9. The PageReference Class: Navigation and Redirection

Handling navigation within Salesforce is crucial for creating a seamless user experience. The PageReference class provides methods for redirecting users to different pages or external URLs, ensuring that your application is both dynamic and user-friendly.

Implement Redirection

  • Calling PageReference methods to set URLs, pass parameters, and redirect users can enhance the interactivity and navigability of your Salesforce applications.
public class MyController {

    // Method to navigate to a Visualforce page
    public PageReference goToPage() {
        // Create a new PageReference object and specify the page name
        PageReference pageRef = Page.MyVisualforcePage;

        // If you want to pass parameters to the page, you can use the getParameters() method
        pageRef.getParameters().put('param1', 'value1');
        pageRef.getParameters().put('param2', 'value2');

        // You can also set URL parameters directly
        // pageRef.getParameters().put('id', '001XXXXXXXXXXXXXXX');

        // Return the PageReference object to navigate to the page
        return pageRef;
    }

    // Method to navigate to a Visualforce page with a specific record ID
    public PageReference goToPageWithRecordId(String recordId) {
        // Create a new PageReference object and specify the page name
        PageReference pageRef = Page.MyVisualforcePage;

        // Set the record ID as a parameter to pass to the page
        pageRef.getParameters().put('id', recordId);

        // Return the PageReference object to navigate to the page
        return pageRef;
    }

    // Method to redirect to another Visualforce page
    public void redirectToPage() {
        // Create a new PageReference object and specify the page name
        PageReference pageRef = Page.MyOtherVisualforcePage;

        // Use the setRedirect method to specify whether to redirect the user's browser
        // to the page (true) or just navigate to it without changing the URL (false)
        pageRef.setRedirect(true);

        // Navigate to the page
        if (!Test.isRunningTest()) {
            // Only perform the redirect if not running a test
            // (redirects are not allowed in test context)
            ApexPages.currentPage().setRedirect(true);
            ApexPages.currentPage().setPrevious(pageRef);
        }
    }
}

In the example above:

  • goToPage() method demonstrates how to navigate to a Visualforce page named “MyVisualforcePage” and pass parameters to it.
  • goToPageWithRecordId(String recordId) method demonstrates how to navigate to a Visualforce page and pass a record ID as a parameter.
  • redirectToPage() method demonstrates how to redirect to another Visualforce page named “MyOtherVisualforcePage”. Note that redirections can only be done in non-test contexts, so there’s a check for that.

10. The UserInfo Class: Accessing User Information

Personalizing applications and tailoring functionalities based on the current user can significantly enhance the user experience. The UserInfo class offers methods to retrieve information about the current user, such as their language, profile, or permissions.

Personalization and Security

  • Utilizing UserInfo methods allows for dynamic application behavior, ensuring that features and data are accessible according to the user’s privileges and preferences.
public class UserInfoExample {

    // Method to get the current user's ID
    public static Id getUserId() {
        return UserInfo.getUserId();
    }

    // Method to get the current user's name
    public static String getUserName() {
        return UserInfo.getName();
    }

    // Method to get the current user's profile ID
    public static Id getProfileId() {
        return UserInfo.getProfileId();
    }



    // Method to get the current user's email
    public static String getUserEmail() {
        return UserInfo.getUserEmail();
    }

    // Method to get the current user's language
    public static String getUserLanguage() {
        return UserInfo.getLanguage();
    }

    // Method to get the current user's time zone
    public static String getUserTimeZone() {
        return UserInfo.getTimeZone().getID();
    }


    // Method to get the current user's session ID
    public static String getSessionId() {
        return UserInfo.getSessionId();
    }


    // Method to get the current user's organization ID
    public static String getOrganizationId() {
        return UserInfo.getOrganizationId();
    }

    // Method to get the current user's organization name
    public static String getOrganizationName() {
        return UserInfo.getOrganizationName();
    }

}

Conclusion

The journey through Salesforce development is paved with myriad functionalities and customizations. Knowing your way around the essential Apex classes not only equips you with the tools needed for effective Salesforce development but also opens up a world of possibilities for creating tailored business solutions. Whether it’s managing data, automating processes, integrating external services, or communicating with users, these ten Apex classes provide a solid foundation for any developer looking to make their mark in the Salesforce landscape. So, roll up your sleeves, and let’s start coding!

Reference : Introducing Apex

Leave a Reply

Your email address will not be published. Required fields are marked *