Apex is a robust, statically typed, object-oriented programming language that allows developers to enhance the functionality of their Salesforce applications beyond what configurations alone can achieve.
It resembles Java and C# in syntax and structure, which provides a familiar footing for developers, but also includes additional features and system methods that make it uniquely powerful for Salesforce-specific tasks.
To help you navigate the world of Apex, we have put together an infographic to cover the fundamentals. Click here to go straight to the infographic.
The Role of Apex in the World of Salesforce
In the Salesforce environment, Apex plays a transformative role by enabling sophisticated business logic execution. Whether it’s through database manipulation or by addressing user-initiated events, Apex is instrumental in creating custom applications within Salesforce.
What’s notable is that Apex accomplishes this while adhering to strict governance limits, ensuring that the shared resources of the Salesforce multi-tenant cloud are used responsibly. You can also use Apex in combination with low-code tools such as Salesforce Flow and Process Builder. Most of the Salesforce features can also be used programmatically, for example, Approval Process and Sending Emails using Apex.
Seamless and Extended Functionality
Apex is the core language of the Salesforce platform. When actions need to be automated within Salesforce, upon a button click or after the update of a record, Apex comes into play. It enables developers to write triggers for handling data validation and automation, and to execute complex operations that are automatically triggered by changes in the user interface or API calls.
Primitive Data Types in Apex
Primitive data types in Apex are the basic data types that store single values and serve as the primary data elements upon which operations are conducted. These include:
- Integer: Represents a 32-bit number that does not include decimal places and is used for whole numbers.
- Example: Integer unitCount = 100;
- Long: A longer integer type represented by a 64-bit number which is useful when dealing with large integers.
- Example: Long earthPopulation = 7800000000L;
- Date: Stores dates in a
YYYY-MM-DD
format without any time information.- Example: Date birthdate = Date.newInstance(1990,12,25);
- Datetime: Combines date and time in a single type retaining both aspects.
- Example: Datetime appointment = Datetime.newInstance(2021, 9, 13, 14, 30, 0);
Apex Data Types
Keyword | Description | Example Usage |
---|---|---|
Boolean | Represents a value that is either true or false or null . | Boolean isActive = true; |
Integer | Represents a 32-bit number with no decimal points. | Integer count = 123; |
Long | Represents a 64-bit number with no decimal points. | Long bigNumber = 123456789L; |
Decimal | Represents a number that includes a decimal point. Currency fields are automatically assigned the type Decimal. | Decimal price = 19.99; |
Double | Represents a 64-bit number that includes a decimal point. | Double rate = 3.14159; |
String | Represents a sequence of characters. | String name = 'John Doe'; |
Date | Represents a date without a time component. | Date today = Date.today(); |
DateTime | Represents a date and time. | DateTime now = DateTime.now(); |
ID | Represents a Salesforce record identifier. | ID myId = '001xx000003DGb2AAG'; |
Blob | Represents binary data or files. | Blob data = Blob.valueOf('Hello'); |
Time | Represents a time without a date component. | Time t = Time.newInstance(12, 30, 0, 0); |
Object | Generic data type representing any object or primitive. | Object myObject = 123; |
Understanding Apex Collection Types
Collections are complex data structures that hold multiple items. Apex provides three primary collection types:
1. Lists: An ordered collection that can contain duplicate elements.
Code Example:
```apex
List<String> fruits = new List<String>{'Apple', 'Banana', 'Cherry'};
```
2. Maps: Stores values by associating unique keys to values, enabling fast data retrieval using those keys.
Code Example:
```apex
Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id, Name FROM Account LIMIT 10]);
```
3. Sets: An unordered collection of unique elements.
Code Example:
```apex
Set<Integer> uniqueNumbers = new Set<Integer>{1, 2, 3, 2, 1};
```
Apex Collections
List | Represents a strongly typed list of objects. | List |
Set | Represents a collection of unique, unordered elements. | Set |
Map | Represents a collection of key-value pairs. | Map |
Collection Selection and Operation
The choice of collection type is dictated by the needs of the operation:
- Use Lists when the order of elements and the ability to access elements by index is required.
- Use Sets when there is a need to ensure the uniqueness of elements and order is inconsequential.
- Use Map for associative arrays which can relate a unique key to a particular value, ideal for retrieval operations. You can also use Map methods to return a set or a list of items (keyset( ), values( )).
Apex Annotations Overview
Annotations in Apex provide a means of adding metadata to classes and methods. These modifiers tell the Apex compiler to treat the annotated element in a specific way, influencing execution behavior.
@isTest
Marks a class or method as a test component, ensuring that it does not affect your org’s code limit and runs only in test contexts.
Code Example:
```apex
@isTest
private class MyTestClass {
@isTest static void testMyMethod() {
// Test code
}
}
```
@HttpGet
Is used in a class that is exposed as a REST web service, indicating that a particular method handles HTTP GET requests.
Code Example:
```apex
@RestResource(urlMapping='/MyService/*')
global with sharing class MyRestResource {
@Httpget
global static String doGet() {
// Method to handle GET request
}
}
```
@future
Marks methods that are to be run asynchronously, in their own background process, useful for operations that are not needed to be run in the current execution context but shortly after without response and logging.
Code Example:
```apex
public class AsyncExecutionExample {
@future
public static void runFutureMethod(List<Id> recordIds) {
// Asynchronous operations
}
}
```
Purpose and Usage of Annotations
Annotations streamline code by clearly indicating the purpose and context of the code. They are essential – knowing these annotations is a must if you’re building on Salesforce.
Annotation | Description | Example Usage |
---|---|---|
@AuraEnabled | Enables a method or property to be called from a Lightning component. | @AuraEnabled public static String myMethod() { } |
@Future | Marks a method that should be run asynchronously in its own thread of control. | @Future public static void asyncMethod() { } |
@InvocableMethod | Allows a method to be invoked by a process or flow. | @InvocableMethod public static void myMethod() { } |
@InvocableVariable | Used in Apex classes declared with @InvocableMethod to define class properties. | public class MyClass { @InvocableVariable public String myVar; } |
@IsTest | Defines a class as a test class that contains methods defining unit tests. | @IsTest public class MyTestClass { } |
@TestSetup | Marks a method in a test class that provides common test data for test methods in the class. | @IsTest public class TestClass { @TestSetup static void setup() { } } |
@TestVisible | Makes a private or protected member of a class visible to test methods. | @TestVisible private static Integer testVar; |
Trigger Context Variables in Apex
Context variables within Apex triggers offer vital insights about the execution context within which the trigger operates. These include:
Trigger.new
A list of the new versions of the sObject records.
Code example to use in before insert
and before update
trigger contexts:
```apex
trigger OpportunityBefore on Opportunity (before insert, before update) {
for (Opportunity opp : Trigger.new) {
// Validate or modify Opportunity records in Trigger.new
}
}
```
Trigger.old
Provides the old versions of the sObject records (only available in update and delete triggers).
Code example to use in before delete
and after delete
trigger contexts:
```apex
trigger OpportunityBeforeDelete on Opportunity (before delete) {
for (Opportunity opp : Trigger.old) {
// Access old Opportunity record data before they are deleted
}
}
```
These help to adapt and apply the specific business rules required.
Apex Data Manipulation Language (DML)
DML in Apex enables you to perform persistent database operations. The five fundamental DML operations are:
- insert: Adds new records to the database.
- update: Modifies existing records.
- delete: Removes records.
- upsert: Either inserts or updates records depending on whether they exist.
- merge: Merges up to three records into one.
Exception Handling in DML Operations
When performing DML operations, exceptions should be handled gracefully. This can be accomplished through the use of try-catch
blocks that encapsulate DML statements to catch exceptions and manage errors.
Example:
```apex
try {
update myAccountsList;
} catch(DmlException e) {
// Handle exception
}
```
Reserved Words and System Methods
In Apex, certain keywords such as if
, else
, for
, while
, and many others, are reserved and have special meanings in the language’s syntax. An understanding of these words and proper usage is fundamental to writing effective Apex code. You can find the full list here.
Examples of Reserved Keywords
Keyword | Description | Example Usage |
---|---|---|
class | Used to declare a class. | public class MyClass { } |
extends | Indicates that a class is derived from another class. | public class MySubClass extends MyClass { } |
implements | Used for implementing an interface. | public class MyClass implements MyInterface { } |
interface | Used to declare an interface. | public interface MyInterface { } |
public | An access modifier indicating that the method or variable is visible to any class. | public Integer myVar; |
private | An access modifier indicating that the method or variable is only accessible within its own class. | private Integer myVar; |
protected | An access modifier that allows access to derived classes and classes within the same package. | protected Integer myVar; |
static | Indicates that a method or variable belongs to the class rather than instances of the class. | public static Integer value = 5; |
void | Specifies that a method does not return a value. | public void myMethod() { } |
return | Used to return a value from a method. | public Integer myMethod() { return 5; } |
for | Used for iterating over a range of values or array elements. | for (Integer i = 0; i < 10; i++) { } |
while | Creates a loop that executes as long as the specified condition is true. | while (a < b) { a++; } |
do | Works with while to create a loop that executes at least once. | do { a++; } while (a < b); |
try | Starts a block of code that will be tested for errors while it is being executed. | try { // code } |
catch | Allows you to define a block of code to be executed if an error occurs in the try block. | catch (Exception e) { } |
super | Can be used by classes that are extended from virtual or abstract classes to override constructors and methods from parent class. | super.myMethod(); |
System methods, provided by Salesforce within system classes, cover a wide range of functionality – from sending emails, to querying and manipulating records, to ensuring security compliance.
Standard Classes and System Methods
Standard Class | Description | Example Usage |
---|---|---|
Database | Provides methods for DML operations, handling all or none of the records. | Database.insert(records, false); |
System | Contains methods for logging, debugging, and other system operations. | System.debug('Debug message'); |
String | Represents a string and contains methods for string manipulation. | String s = 'Hello'.toUpperCase(); |
Math | Provides methods for mathematical operations. | Double result = Math.sqrt(16); |
Schema | Provides methods to retrieve schema information. | Schema.DescribeSObjectResult r = Account.SObjectType.getDescribe(); |
Test | Provides methods to create test data and run test methods. | Test.startTest(); // code // Test.stopTest(); |
Messaging | Contains methods for sending emails. | Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); |
Http | Provides methods for sending HTTP requests and receiving HTTP responses. | Http http = new Http(); HttpRequest request = new HttpRequest(); |
Final Thoughts
Mastering Apex is pivotal for any Salesforce Developer aiming to push the limits of Salesforce customization and build powerful, efficient applications tailored to specific business processes.
Proper usage of data types, collection types, annotations, context variables, DML operations, and system methods – aligned with best practices – ensures adherence to Salesforce’s governance limits and optimizes the performance, reliability, and scalability of implementations. With these fundamentals at their fingertips, Salesforce Developers can unlock the full potential of Salesforce’s powerful platform and create solutions that drive business success.
If you’re looking to learn more about development or any topic about Salesforce, feel free to join me and others at SFXD, a community of Salesforce professionals. We currently have 10,000+ members, with a very active core membership connecting every day on our Discord server.
I hope you enjoyed this article – see you in the next one!