Salesforce Apex Annotations

Salesforce Apex Annotations

On January 10, 2024, Posted by , In Salesforce, With Comments Off on Salesforce Apex Annotations

Table of Contents

Salesforce annotations are crucial in customizing the behavior of Apex code. They offer a streamlined way to provide metadata, enhance functionality, and clarify the purpose of code blocks.

Below is a detailed look at various types of annotations in Salesforce, accompanied by practical examples.

1. @AuraEnabled

The @AuraEnabled annotation in Salesforce is used to expose Apex methods as Aura-enabled methods, allowing them to be called from Lightning components. Methods annotated with @AuraEnabled can be invoked from client-side JavaScript controllers in Lightning components to perform server-side actions, such as querying records or updating data. This annotation helps facilitate communication between the client and server in Lightning components, enabling developers to create interactive and dynamic user interfaces in Salesforce Lightning Experience and Salesforce Mobile App.

Learn the intricacies of the @AuraEnabled Annotation and how it enhances your Lightning components.

Example:

public with sharing class AccountController {

    @AuraEnabled
    public static List<Account> getAccounts() {
        return [SELECT Id, Name, Industry FROM Account LIMIT 5];
    }

    @AuraEnabled
    public static void updateAccountName(String accountId, String newName) {
        Account acc = [SELECT Id, Name FROM Account WHERE Id = :accountId];
        acc.Name = newName;
        update acc;
    }
}

Looking to ace Salesforce job interviews? These Utimate Salesforce Interview Questions will guide you to success!

In this example, AccountController is a Apex class that contains two methods annotated with @AuraEnabled. The getAccounts method queries the first 5 accounts from the database and returns them as a list. This method can be called from a Lightning component to retrieve account data.

Want to automate your Salesforce processes seamlessly? Understanding triggers in Salesforce to master this essential skill.

The updateAccountName method takes two parameters, accountId and newName, and updates the name of the account with the specified accountId to the newName. This method can be called from a Lightning component to update account names.

The @AuraEnabled annotation is used to expose these methods to the client-side JavaScript controller in a Lightning component, allowing them to be called asynchronously.

CRS Info Solutions offers real-time Salesforce course for beginners designed to equip learners with practical knowledge and industry skills in Salesforce. Enroll for demo today.

2. @TestSetup


The @TestSetup annotation in Salesforce is used to define a method that sets up test data that is shared across all test methods in a test class. This annotation is particularly useful for creating common test data that needs to be used in multiple test methods, reducing duplication and ensuring consistency in test execution. Test setup methods annotated with @TestSetup are executed before each test method in the test class, providing a clean and consistent environment for testing.

Read more about custom page layouts in Salesforce.

Example:

@isTest
private class TestSetupExample {

    @TestSetup
    static void setupTestData() {
        // Create test records
        List<Account> accounts = new List<Account>();
        for(Integer i=0; i<5; i++) {
            Account acc = new Account(Name='Test Account ' + i);
            accounts.add(acc);
        }
        insert accounts;
    }

    @isTest
    static void testMethod() {
        // Test method that uses the test data created in the setup
        List<Account> accs = [SELECT Id, Name FROM Account];
        System.assertEquals(5, accs.size());
    }
}

In this example, the TestSetupExample class contains a method called setupTestData annotated with @TestSetup. This method is used to create test records, in this case, five Account records with names like “Test Account 0”, “Test Account 1”, etc. The @TestSetup annotation ensures that the test data is created before any test methods in the test class are executed.

Read more: Approval Process in Salesforce.

The testMethod method is a test method that queries the Account records created in the setup method and asserts that there are five records. Since the @TestSetup method has already created the test data, the testMethod can focus on testing the functionality without having to worry about creating test data within the test method itself.

3. @isTest


The @isTest annotation in Salesforce is used to define a method as a test method, allowing it to be executed as part of the Apex test framework. Test methods annotated with @isTest are used to test Apex code and ensure its functionality, helping developers identify and fix issues early in the development process. These methods do not count against Apex code limits and are crucial for maintaining code quality and ensuring the stability of Salesforce applications.

Example:

@isTest
private class TestExample {

    @isTest
    static void testMethod() {
        // Test logic
        Integer a = 1;
        Integer b = 2;
        Integer result = a + b;
        System.assertEquals(3, result, 'Sum should be 3');
    }
}

In this example, the TestExample class contains a method called testMethod annotated with @isTest. This method is a test method that contains the logic to be tested. In this case, it adds two integers a and b and asserts that the result is equal to 3 using the System.assertEquals method.

The @isTest annotation indicates that the testMethod is a test method and should be executed as part of the Salesforce test framework. Test methods annotated with @isTest don’t count against the organization’s Apex code limit and are used to verify that your code works as expected.

Read more: Types of relationships in Salesforce

4. @Deprecated

The @Deprecated annotation in Salesforce is used to indicate that a method or class is no longer recommended for use and may be removed in future versions. It serves as a warning to developers that the functionality should be avoided in favor of newer, more efficient alternatives. While the deprecated code will still function, Salesforce recommends updating to the recommended approach to ensure compatibility with future releases and to take advantage of improvements and best practices.

Example:

public class DeprecatedExample {

    // This method is deprecated and should not be used
    @Deprecated
    public static void oldMethod() {
        System.debug('This method is deprecated');
    }

    public static void newMethod() {
        System.debug('This is the new method');
    }
}

In this example, the oldMethod is marked as deprecated using the @Deprecated annotation. This indicates to developers that the method should no longer be used and may be removed in the future. The newMethod is a new method that should be used instead of oldMethod.

Using the @Deprecated annotation helps to communicate to other developers that a method is no longer recommended for use, allowing them to update their code accordingly.

Read more: What are Page layouts in Salesforce and how to create Page layouts?

5. @Future

The @Future annotation in Salesforce is used to designate a method as a future method, allowing it to be executed asynchronously at a later time. This annotation is typically used when a method needs to perform long-running operations, such as callouts to external systems or batch processing, without blocking the main thread. Future methods are queued and executed by the Salesforce platform, providing a way to offload intensive tasks and improve application performance.

Example:

public class FutureExample {

    @Future
    public static void myFutureMethod(String name) {
        System.debug('Hello, ' + name + '! This is executed asynchronously.');
    }

    public static void mainMethod() {
        // Call the future method
        myFutureMethod('John');
        System.debug('Main method continues to execute while the future method runs in the background.');
    }
}

In this example, the myFutureMethod is annotated with @Future, indicating that it should be executed asynchronously in the background. When the mainMethod is called, it invokes myFutureMethod with the name ‘John’. The mainMethod continues to execute while myFutureMethod runs in the background, allowing for parallel execution of code.

The @Future annotation is commonly used for long-running operations, such as making callouts to external systems or performing complex calculations, that would otherwise block the user interface. By using @Future, you can offload these operations to run asynchronously, improving the performance and responsiveness of your Salesforce application.

Read more about formula fields in Salesforce. This tutorial covers everything you need to know to master formula fields and enhance your Salesforce expertise.

6. @InvocableMethod

The @InvocableMethod annotation in Salesforce is used to define a method as an invocable method that can be called by external systems, such as Process Builder or Flow. This annotation allows the method to be exposed as an action that can be executed when certain conditions are met. It is commonly used in Salesforce to create custom actions that can be triggered from declarative tools, providing flexibility and customization options without the need for complex coding.

Example:

public class InvocableMethodExample {

    @InvocableMethod(label='Convert Leads')
    public static void convertLeads(List<Id> leadIds) {
        // Your logic to convert leads
        List<Database.LeadConvert> leadConverts = new List<Database.LeadConvert>();
        for(Id leadId : leadIds) {
            Database.LeadConvert lc = new Database.LeadConvert();
            lc.setLeadId(leadId);
            lc.setConvertedStatus('Qualified');
            leadConverts.add(lc);
        }
        List<Database.LeadConvertResult> results = Database.convertLead(leadConverts);
    }
}

In this example, the InvocableMethodExample class contains a method called convertLeads annotated with @InvocableMethod. This annotation marks the method as an invocable method that can be called from a Flow or Process Builder.

The convertLeads method takes a list of Lead record IDs as a parameter and converts these leads into contacts, accounts, and opportunities. This method can be used in a Flow or Process Builder to automate the lead conversion process.

The label attribute of the @InvocableMethod annotation specifies the label that will be displayed in the Flow or Process Builder when selecting this method. This makes it easier for admins to understand the purpose of the method and how it should be used in their automation processes.

Read more: Strings in Salesforce Apex

7. @ReadOnly

The @ReadOnly annotation in Salesforce is used to ensure that a method or class is read-only, meaning it cannot perform any DML (Data Manipulation Language) operations such as insert, update, or delete on records. This annotation is often used in situations where data should not be modified, such as in triggers that are only meant for querying records or in batch classes where the goal is to process large volumes of data without changing it.

Example:

public class ReadOnlyExample {

    @ReadOnly
    public static void readOnlyMethod() {
        // Query some data
        List<Account> accounts = [SELECT Id, Name FROM Account LIMIT 10];
        for(Account acc : accounts) {
            System.debug('Account Name: ' + acc.Name);
        }
    }

    public static void mainMethod() {
        // Call the read-only method
        readOnlyMethod();
        System.debug('Main method continues to execute');
    }
}

In this example, the readOnlyMethod is annotated with @ReadOnly, indicating that it should not perform any DML (Data Manipulation Language) operations, such as insert, update, or delete, on records. The method queries a list of Account records and prints their names to the debug log.

The mainMethod is a regular method that calls readOnlyMethod. Since readOnlyMethod is marked as read-only, it can be called from mainMethod without any restrictions. The read-only behavior ensures that the data queried in readOnlyMethod cannot be modified, providing a safe way to retrieve data without the risk of unintentional changes.

Read more: Loops in Salesforce Apex

8. RESTful Service Annotations

Description: These annotations define methods in Apex classes as RESTful services, enabling them to handle respective HTTP requests.

@HttpDelete

The @HttpDelete annotation in Salesforce is used to define an Apex method as an HTTP DELETE request handler. This annotation allows the method to be invoked by external systems using the DELETE HTTP method, typically used for deleting resources. Methods annotated with @HttpDelete must be in a class annotated with @RestResource and can accept parameters from the request.

@RestResource(urlMapping='/exampleEndpoint/*')
global with sharing class ExampleRestResource {

    @HttpDelete
    global static void doDelete() {
        // Your logic to delete a record
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        delete [SELECT Id FROM CustomObject__c WHERE Id = :recordId];
        res.statusCode = 204; // HTTP 204 No Content
        res.responseBody = Blob.valueOf('Record deleted successfully');
    }
}

In this example, the doDelete method is annotated with @HttpDelete and is responsible for deleting a record of the CustomObject__c object based on the ID provided in the request URI. The method sets the HTTP response status code to 204 (No Content) and provides a response body indicating the successful deletion of the record.

@HttpGet

The @HttpGet annotation in Salesforce is used to define an Apex method as an HTTP GET request handler. This annotation allows the method to be invoked by external systems using the GET HTTP method, typically used for retrieving resources. Methods annotated with @HttpGet must be in a class annotated with @RestResource and can accept parameters from the request.

@RestResource(urlMapping='/exampleEndpoint/*')
global with sharing class ExampleRestResource {

    @HttpGet
    global static void doGet() {
        // Your logic to retrieve data
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        CustomObject__c obj = [SELECT Id, Name FROM CustomObject__c WHERE Id = :recordId];
        res.statusCode = 200; // HTTP 200 OK
        res.responseBody = Blob.valueOf(JSON.serialize(obj));
    }
}

In this example, the doGet method is annotated with @HttpGet and is responsible for retrieving a record of the CustomObject__c object based on the ID provided in the request URI. The method sets the HTTP response status code to 200 (OK) and provides a response body containing the JSON representation of the retrieved object.

Understand the importance of Record Types in Salesforce and how they can help manage different business processes with ease.

@HttpPatch

The @HttpPatch annotation in Salesforce is used to define an Apex method as an HTTP PATCH request handler. This annotation allows the method to be invoked by external systems using the PATCH HTTP method, typically used for partial updates to resources. Methods annotated with @HttpPatch must be in a class annotated with @RestResource and can accept parameters from the request.

@RestResource(urlMapping='/exampleEndpoint/*')
global with sharing class ExampleRestResource {

    @HttpPatch
    global static void doPatch(String requestBody) {
        // Your logic to update a record
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        CustomObject__c obj = [SELECT Id, Name FROM CustomObject__c WHERE Id = :recordId];
        obj.Name = 'Updated Name';
        update obj;
        res.statusCode = 200; // HTTP 200 OK
        res.responseBody = Blob.valueOf('Record updated successfully');
    }
}

In this example, the doPatch method is annotated with @HttpPatch and is responsible for updating a record of the CustomObject__c object based on the ID provided in the request URI. The method sets the HTTP response status code to 200 (OK) and provides a response body indicating the successful update of the record.

Dive into Arrays in Salesforce Apex to handle collections of data efficiently in your Apex code.”

@HttpPost

The @HttpPost annotation in Salesforce is used to define an Apex method as an HTTP POST request handler. This annotation allows the method to be invoked by external systems using the POST HTTP method, typically used for creating new resources. Methods annotated with @HttpPost must be in a class annotated with @RestResource and can accept parameters from the request.

@RestResource(urlMapping='/exampleEndpoint')
global with sharing class ExampleRestResource {

    @HttpPost
    global static void doPost(String requestBody) {
        // Your logic to create a new record
        RestResponse res = RestContext.response;
        CustomObject__c obj = new CustomObject__c(Name='New Record');
        insert obj;
        res.statusCode = 201; // HTTP 201 Created
        res.responseBody = Blob.valueOf('Record created successfully');
    }
}

In this example, the doPost method is annotated with @HttpPost and is responsible for creating a new record of the CustomObject__c object. The method sets the HTTP response status code to 201 (Created) and provides a response body indicating the successful creation of the record.

@HttpPut

The @HttpPut annotation in Salesforce is used to define an Apex method as an HTTP PUT request handler. This annotation allows the method to be invoked by external systems using the PUT HTTP method, typically used for updating existing resources. Methods annotated with @HttpPut must be in a class annotated with @RestResource and can accept parameters from the request.

@RestResource(urlMapping='/exampleEndpoint/*')
global with sharing class ExampleRestResource {

    @HttpPut
    global static void doPut(String requestBody) {
        // Your logic to update a record
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        String recordId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        CustomObject__c obj = [SELECT Id, Name FROM CustomObject__c WHERE Id = :recordId];
        obj.Name = 'Updated Name';
        update obj;
        res.statusCode = 200; // HTTP 200 OK
        res.responseBody = Blob.valueOf('Record updated successfully');
    }
}

In this example, the doPut method is annotated with @HttpPut and is responsible for updating a record of the CustomObject__c object based on the ID provided in the request URI. The method sets the HTTP response status code to 200 (OK) and provides a response body indicating the successful update of the record.

Top 10 interviews questions on Salesforce Annotations with coding examples.

Benefits of Using Annotations in Salesforce: Scenarios and Advantages

  1. Enhanced Code Efficiency: Annotations like @Future and @ReadOnly allow developers to implement complex functionalities like asynchronous processing and handling large data sets efficiently.
    Scenario: Using @Future to offload heavy data processing tasks, ensuring the main thread remains responsive for user interactions.
  2. Improved Code Organization and Maintenance: Annotations like @isTest and @Deprecated assist in keeping the codebase organized by clearly differentiating test code from production code and phasing out obsolete methods.
    Scenario: Marking legacy methods with @Deprecated to warn developers against their use in new implementations.
  3. Increased Readability and Clarity: Annotations provide a clear understanding of the code’s purpose at a glance, enhancing the readability for other developers.
    Scenario: Utilizing @AuraEnabled to immediately signify the interaction between Apex and Lightning Components.
  4. Streamlined Testing and Debugging: With @TestSetup, creating test data becomes more efficient, and @isTest ensures test codes are isolated from production codes, simplifying testing and debugging processes.
    Scenario: Using @TestSetup to create a shared testing environment, reducing redundancy in test data creation.
  5. Integration with Salesforce Ecosystem: Annotations like @InvocableMethod enable seamless integration of custom Apex logic with Salesforce’s declarative tools like Process Builder and Flow.
    Scenario: Creating an @InvocableMethod that can be triggered by a Process Builder to perform custom actions based on certain criteria.

Salesforce annotations are powerful tools that not only enhance the capabilities of Apex code but also contribute to a more organized, efficient, and understandable codebase. Understanding and leveraging these annotations is key to developing advanced and maintainable Salesforce applications.

Read more: DML in Salesforce Apex

Frequently Asked Questions

1. Why do we use @future annotation in Salesforce?

The @future annotation in Salesforce is used to denote methods that should be executed asynchronously in the background, separate from the main thread. This is particularly useful for long-running operations, such as making callouts to external services or performing complex calculations, that could otherwise block the user interface and lead to a poor user experience. By marking a method with @future, Salesforce queues the method for execution and allows the current transaction to continue without waiting for the asynchronous method to complete.

Read more: SOQL Query in Salesforce

Another key reason for using @future is to avoid hitting Salesforce’s governor limits, such as the maximum CPU time or heap size. Asynchronous processing with @future allows for more efficient resource management, as the queued method runs in its own context and has its own set of governor limits. This helps prevent issues such as governor limit exceptions that could occur if the operation were performed synchronously within the main transaction.

Additionally, the @future annotation is often used to perform batch processing, where large volumes of records need to be processed in chunks. By breaking up the work into smaller batches and executing them asynchronously, developers can avoid hitting limits and ensure that the overall process is efficient and scalable. Overall, the @future annotation is a powerful tool in Salesforce development for managing long-running operations, avoiding governor limits, and improving the performance of applications.

Read more: Array methods in Salesforce Apex

2. When should the @ReadOnly annotation be used, and what are its limitations?

The @ReadOnly annotation in Salesforce should be used when you want to ensure that a method or class does not perform any DML (Data Manipulation Language) operations, such as insert, update, or delete, on records. It is commonly used in scenarios where you only need to read data from Salesforce and want to prevent accidental modification of records.

However, it’s important to note that the @ReadOnly annotation has limitations. It does not prevent the modification of static variables or static methods that perform DML operations. Additionally, it does not enforce read-only behavior for related objects, such as parent or child records, so care must be taken to ensure that all related records are treated as read-only if necessary.

Checkout: DML statements in Salesforce

3. What are the best practices for using the @AuraEnabled annotation in Lightning components?

When using the @AuraEnabled annotation in Lightning components, several best practices should be followed to ensure efficient and secure development. Firstly, only use @AuraEnabled on methods that are intended to be called from the client-side JavaScript controller. This helps prevent unnecessary exposure of server-side logic.

Secondly, use @AuraEnabled(cacheable=true) for methods that retrieve data from Salesforce and don’t require real-time updates. This allows the Lightning framework to cache the data for improved performance and reduced server load.

Lastly, always validate input parameters to @AuraEnabled methods to prevent injection attacks and ensure data integrity. Following these best practices helps ensure that your Lightning components are secure, performant, and maintainable.

Read more: Salesforce apex programming examples

4. How does the @InvocableMethod annotation differ from other Apex annotations, and when should it be used?

The @InvocableMethod annotation in Salesforce Apex is unique compared to other annotations because it allows you to define methods that can be invoked by external processes, such as Process Builder and Flow. Unlike annotations like @AuraEnabled or @HttpPost, which are primarily used for client-server communication, @InvocableMethod is used for server-server or server-external system communication.

@InvocableMethod should be used when you want to expose an Apex method as an action that can be executed by declarative tools like Process Builder or Flow. This is useful for automating complex business processes that require custom logic or integration with external systems. @InvocableMethod allows you to encapsulate this logic in a reusable Apex method that can be easily called from various places in your Salesforce org.

Collection is one of the important concept, checkout: Collections in Salesforce Apex

5. What considerations should be taken into account when using the @Http annotations in Apex REST services?

When using the @Http annotations in Apex REST services, several considerations should be taken into account to ensure secure and efficient implementation. First and foremost, always validate incoming requests to prevent injection attacks and ensure data integrity. Additionally, use the appropriate @Http annotation (@HttpGet, @HttpPost, @HttpPut, @HttpDelete, @HttpPatch) based on the HTTP method being used and the purpose of the method.

It’s also important to handle exceptions gracefully and return meaningful error messages to the client. This helps improve the usability of your REST services and provides helpful feedback to consumers. Lastly, consider implementing rate limiting and authentication mechanisms to protect your REST services from abuse and unauthorized access.

Read more: Arrays in Salesforce Apex

Comments are closed.