0% found this document useful (0 votes)
12 views393 pages

Apex (1-18)

Uploaded by

Kaleem
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views393 pages

Apex (1-18)

Uploaded by

Kaleem
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 393

Day 01

Introduction to

Apex
kshitijdhoble
Overview of Apex
● Apex is a strongly typed, object-oriented programming
language, similar to Java and runs on Force.com Platform.
● It is used by developers to execute flow and transaction
control statements on the Salesforce platform.
● It allows developers to add business logic to most system
events, including button clicks, related record updates, and
Visualforce pages.
● Apex offers more advanced automation capabilities and
enables extensive customization like creation of triggers,
data manipulation, and integration with other systems.

kshitijdhoble
Use Cases
● Custom Business Logic: Automate complex business
processes.
● Data Manipulation: Perform operations on Salesforce data
(insert, update, delete).
● Integration: Connect Salesforce with external systems.
● Custom Web Services: Create custom SOAP and REST
web services.

kshitijdhoble
Benefits
● Seamless Integration: Built natively on the Salesforce
platform, ensuring smooth integration with Salesforce
data and features.
● Scalability: Designed to handle large volumes of data and
complex processes.
● Security: Enforces Salesforce's robust security model.
● Efficiency: Reduces the need for point-and-click
automation by allowing advanced customizations.

kshitijdhoble
Basic Syntax & Structure
Apex Class Structure: An Apex Class is the blueprint for
creating Objects. It contains Properties, Methods, &
Constructors. Here’s a basic example:

public class MyClass {


public String name; // Properties
public Integer age;

public MyClass(String name, Integer age){ //


Constructor
this.name = name;
this.age = age;
}
public void message(){ // Method
System.debug(‘Hello, ‘ + name + ‘!’);
}
} kshitijdhoble
Why Do We Need Apex?
There are primarily two approaches to customizing
applications. Declarative & Programmatic approach.

● Declarative approach, or we can say Point-and-click


automation tools in Salesforce let you automate business
processes to build and customize Salesforce apps
efficiently, without writing code.
● Key tools and features include:
○ Workflow Rules (to be deprecated)
○ Process Builder (to be deprecated)
○ Approval Process
○ Flow Builder
kshitijdhoble
Why Do We Need Apex?
● In Salesforce, the "Programmatic Approach" involves
writing code and scripts to implement custom
functionality and complex business logic, offering
flexibility for highly customized and scalable solutions.
● Key Programmatic Tools include:
○ Apex/VisualForce
○ Lightning Web Components
○ Triggers, Classes & Controllers
○ Batch & Scheduling Processes
○ JavaScript/CSS & Custom Metadata

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 02
Data Types & Variables

in
Apex
kshitijdhoble
Variables in Apex
● A Variable is name of memory location used to store data

that have a particular data type.

● So, as we know that Apex is Strongly-typed language,

Variables in Apex must be declared with a specific data

type and can be initialized with a value.

● Name of Variable is called “Identifier”.

kshitijdhoble
Rules to Declare Variables
● A Variable Name must begin with an Alphabet not with
number and special characters.
● Special characters and spaces are not allowed while
declaring variables, excluding Underscore (_).
● We can’t use Reserved Apex Keywords to declare variables.

Valid ✅ Invalid ❌
Integer i3; String _ia; String str_;
String i_5; String i 2; String i$5;
String $a2; String $_s_4;

kshitijdhoble
Constants in Apex
● In Apex, a Constant is a variable whose value is fixed and
cannot be changed once it is assigned.
● Constants are declared using the keyword “final”.
● Often used to define values that should remain consistent
and immutable, such as configuration settings, fixed values
for calculations, or any value that should not change
during runtime.
● Constants are often declared as “static” because they are
shared across all instances of the class.

kshitijdhoble
Constants in Apex
● In the MathConstants example:
○ static: The constants belong to the class, not instances.
○ final: The values are immutable and cannot be changed.
○ So, PI and MAX_STUDENTS are fixed values that can be
accessed via the class name and cannot be altered

public class MathConstants {


public static final Double PI = 3.14159;
public static final Integer MAX_STUDENTS = 30;

public void displayConstants() {


System.debug('Value of PI: ' + PI);
System.debug('Max number of students: ' + MAX_STUDENTS);
}
}

kshitijdhoble
Data Types in Apex
● In Apex, data types define the kind of data a variable can
hold.
● Apex is a strongly typed language, meaning you must
declare the type of data a variable will store.
● There are some major data types in Apex:
○ Primitive Types
○ Collections Types
○ Salesforce Specific Types
○ Special Types
○ Custom Types

kshitijdhoble
Primitive Data Types
● Integer
○ Represents 32-bit whole numbers (both positive and
negative) without decimal places (…-3, -2, -1, 0, 1, 2, 3…).
○ Size: 4 bytes. Range: -2147483647 to 2147483647
○ Example: Integer num = 100; Integer x = -25;
● Long
○ Represents a 64-bit integer, useful for handling large
range of numbers .
○ Size: 8 bytes. Range: −263 to 263-1
○ Example: Long largeNum = 1234567890123L;

kshitijdhoble
Primitive Data Types
● Double
○ Represents 64-bit floating-point numbers, which can
contain decimal points.
○ Size: 8 bytes. Range: Approx. ±1.7E-308 to ±1.7E+308.
○ Example: Double price = 99.99;
● Decimal
○ Represents a 64-bit integer, useful for handling large
range of numbers .
○ Size: Variable, with fix precision. Range: Can handle
large & small numbers but with fixed precision.
○ Example: Decimal salary = 12345678.90;

kshitijdhoble
Primitive Data Types
● String
○ Represents a sequence of characters enclosed with
single quotes ( ‘ ‘ ).
○ Size: Variable, depends on the length of the string
○ Example: String name = ‘Kshitij Dhoble’;
● Boolean
○ Represents a true or false value .
○ Size: 1 byte.
○ Example: Boolean isActive = true;
Boolean isCompleted = false;

kshitijdhoble
Primitive Data Types
● Date
○ Represents a calendar date without time.
○ Size: 8 bytes.
○ Example: Date today = Date.today();
● Time
○ Represents a specific time of the day without a date.
○ Size: 8 bytes.
○ Example: Time currentTime = Time.now();
● DateTime
○ Represents a specific date and time.
○ Size: 8 bytes.
○ Example: DateTime now = DateTime.now();

kshitijdhoble
Collection Data Type
● List
○ Represents an ordered collection of elements, which
can be of any data type like primitive, user-defined
objects, sObjects, or other collections.
○ Data is stored in sequence and are case-insensitive.
○ We can store duplicate data in a list.
○ Example:

List<String> names = new List<String>{'Kshitij', 'Rudra'};

kshitijdhoble
Collection Data Type
● Set
○ Represents a collection of unique elements, useful for
eliminating duplicates. It can store primitive data
types, sObjects, or user-defined objects.
○ Sequence of data is not followed and are
case-sensitive.
○ We cannot store duplicate data in a set.
○ Example:

Set<Integer> num = new Set<Integer>{1, 2, 3};

kshitijdhoble
Collection Data Type
● Map
○ Represents a collection of key-value pairs, where each
key is unique.
○ Data is stored in key-value pair and are case-sensitive.
○ In Map, Value can be duplicate but Key should be
unique.
○ Example:

Map<String, Integer> scores = new Map<String, Integer> {

‘Kshitij’ => 10,‘Rudra’ => 8 };

kshitijdhoble
Salesforce Specific Types
● ID
○ Represents Salesforce record IDs, which are 15-character
or 18-character unique identifiers.
○ This is system generated and can’t be edited/deleted.
○ 15 Digit IDs (0066A000004rMoL) are case-sensitive.
Salesforce uses it internally to maintain database, also
visible in the UI.
○ 18 Digit IDs (0066A000004rMoLIA0) are case-insensitive.
The last 3 characters are the checksum of the
capitalization of 1st 15 characters. It is returned by API
Calls. Meanwhile, the API will accept 15 digit ID but
always returns 18 digit ID.
kshitijdhoble
Salesforce Specific Types
● First 3 characters of an ID denotes the object type. These
prefixes never change for objects. And we can’t predict the
prefix of custom object, it’s based on internal SFDC rules.
● These are some prefixes of standard objects:

Objects Prefixes
Account 001
Contact 003
Leads 00Q

kshitijdhoble
Salesforce Specific Types
● sObject
○ A special data type used to work with Salesforce
records. It represents a generic Salesforce object.
○ Fields can be accessed dynamically using get and put
methods. Here’s an example:

Account acc = new Account()


// here, Account is generic sObject
acc.put(‘Name’, ‘KshitijTech’);
String name = (String)acc.get(‘Name’);
System.debug(‘Account Name: ‘ + name);
// we can use Custom_Object__c too

kshitijdhoble
Special Types
● Null
○ Represents a state where a variable has no value
assigned to it.
○ We can assign null to any variable (primitive or
non-primitive) to indicate that it has no value
○ Example:
Integer number = null;

String text = null;

kshitijdhoble
Special Types
● Blob
○ Represents raw binary data, allowing you to work with data
that is not text-based.
○ Typically used for file handling, such as storing
attachments, images, or any binary files.
○ The maximum size of a Blob can be up to 6 MB per
operation in Salesforce.
○ Example:

Blob myBlob = Blob.valueOf(‘Hello Salesforce’);


// creating a Blob from a String

kshitijdhoble
Special Types
● Object
○ It’s a base class for all data types, which means it can
hold any type of value, including primitive data types,
collections, sObjects, and custom objects, but while
retrieving, we need to cast it back to original type.
○ Example:

Object myObj; // declaring


Integer intVal = (Integer)myObj; // retrieving/casting
System.debug(‘Int Value: ‘ + intVal);

kshitijdhoble
Custom Types
● Enum
○ Defines a set of named constants. Useful for representing a
collection of related constants.
○ Used to represent fixed state of status, values, categories,
and types.
○ It provide type safety restricts the value that variable can
take, reducing the risk of invalid values.
○ Example:

public enum status = { ‘NEW’, ‘IN_PROGRESS’,

‘COMPLETED’ };

kshitijdhoble
Custom Types
● User-defined Classes
○ Classes that we define to create custom data types
with specific attributes and methods.
○ Example: defining and using the class below.

public class Employee {


// variables, constructors, methods
}
public class EmpDemo {
public static void demo() {
// initializing Employee class
Employee emp = new Employee();
}// call methods & displaying outputs
}
kshitijdhoble
Custom Types
● Wrapper Classes
○ Custom classes used to encapsulate different types of
data into a single unit.
○ Useful for combining multiple data types or objects
into one class. Here’s an example:
public class AccWrapper {
public Account acc;
public Boolean isActive;
public AccWrapper(Account acc, Boolean isActive) {
this.acc = acc;
this.isActive = isActive;
}
}
kshitijdhoble
Best Practices
● Always initialize variables to avoid NullPointer exceptions.
● Use meaningful names & camelCase.
● Use Constants for the values that do not change.
● Use primitive types over wrapper classes when null values
are not need.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 03
Type Conversion, Operators &
Logic Control Statements in

Apex
kshitijdhoble
Type Conversion
● Type conversion is the process of converting a value from

one data type to another. Apex supports automatic

(implicit) and manual (explicit) type conversion.

● Generally, Apex requires explicit conversion from one data

type to another.

● However, few of them can be implicitly converted

automatically like lower to higher numeric type.

kshitijdhoble
Implicit Type Conversion
● Implicit conversion occurs automatically when you assign

a value of one data type to a compatible data type.

● In Apex, implicit conversions are limited and generally

occur when converting from a more specific type to a

more general type. Here’s an example:


Integer num = 20;
Double d = num
// Automatic conversion Integer to Double
System.debug(num); // Output: 10.0

kshitijdhoble
Explicit Type Conversion
● Explicit conversion, or casting, requires a developer to

explicitly specify the target data type.

● This is done using the cast operator (targetType).

● Example:
Double d = 20;
Integer num = (Integer)d;
// Explicit Conversion Double to Integer
System.debug(num); // Output: 10

kshitijdhoble
Explicit Conversions (Casting)
● The .valueOf() is an explicit conversion method in

Apex is a static method provided by several classes to

convert values from one type to another.

● Commonly used to convert primitive data types or

strings into other types.

● Purpose: Convert a value of one type into a specific

type, usually a string representation.

● Common Usage: Converting numbers or other data

types into strings, or parsing strings into numeric types.

kshitijdhoble
Integer Type Conversions
● Integer Conversions

Integer num = 123;


String str = String.valueOf(num); // “123”
Long longNum = num; // implicit
Double doubleNum = num; // implicit
Decimal decimalNum = (Decimal)num; // explicit

kshitijdhoble
Long Type Conversions
● Long Conversions

Long longNum = 123L;


Integer num = (Integer)longNum; // explicit
String str = String.valueOf(longNum); // “123”
Double doubleNum = longNum; // implicit
Decimal decimalNum = (Decimal)longNum; // explicit

kshitijdhoble
Double Type Conversions
● Double Conversions

Double doubleNum = 123.45;


Integer num = (Integer)doubleNum; // 123
Long longNum = Long(doubleNum); // “123”
String str = String.valueOf(doubleNum); // “123.45”
Decimal decimalNum = (Decimal)doubleNum;
// conversion of Double to Integer & Long done
explicitly, but it may lose precision.

kshitijdhoble
Decimal Type Conversions
● Decimal Conversions

Decimal decimalNum = 123.45;


Integer num = (Integer)decimalNum; // 123
Long longNum = Long(decimalNum); // 123
String str = String.valueOf(decimalNum); // “123.45”
Double doubleNum = (Double)decimalNum;

kshitijdhoble
String Type Conversions
● String Conversions

String str = ‘true’;


Boolean bool = Boolean.valueOf(str); // true
String str = ‘123’;
Integer num = Integer.valueOf(str); // 123
Long num = Long.valueOf(str); // 123L

kshitijdhoble
String Type Conversions
● String Conversions

String str = ‘123.45’;


Double doubleNum = Double.valueOf(str); // 123.45
Decimal decimalNum = Decimal.valueOf(str); // 123.45
String str = ‘2024-03-08’;
Date date = Date.valueOf(str); // August 3, 2024
String str = "2023-01-01 12:00:00";
Datetime dt = Datetime.valueOf(str);
// August 3, 2024, 12:00 PM

kshitijdhoble
Boolean Type Conversions
● Boolean Conversions

Boolean bool = true;


String str = String.valueOf(bool); // "true"

kshitijdhoble
Date Type Conversions
● Date Conversions

Date date = Date.today();


String str = String.valueOf(date); // “2024-03-08”
Datetime dt = Datetime.newInstance(Date,
Time.newInstance(0, 0, 0, 0));
// August 3, 2024, 12:00 PM

kshitijdhoble
DateTime Type Conversions
● DateTime Conversions

DateTime dt = DateTime.now();
String str = String.valueOf(dt);
// "2023-01-01 12:00:00"
Date date = dt.date(); // August 3, 2024

kshitijdhoble
Handling Null Values
● When converting types, always handle null values to

prevent runtime errors.

String str = null;


Integer num = (str != null) ?
Integer.valueOf(str) : null;

kshitijdhoble
Note
● IDs can always be assigned to Strings.

● Strings can be assigned to IDs, but at runtime, the value is

checked to ensure that it is legitimate ID. If it’s not, a runtime

exception thrown.

● Instance of a keyword can always be used to test if the String is

ID or not.

● Once a value is passed from number of lower type to higher

type, the value get converted to the higher type of number.

kshitijdhoble
Operators in Apex
● These operators provide a wide range of functionalities in

Apex, enabling developers to perform various operations

efficiently. Some major types of Operators include:

○ Arithmetic Operators

○ Comparison Operators

○ Logical Operators

○ Bitwise Operators

○ Assignment Operators

kshitijdhoble
Arithmetic Operators
Operator Details Example
Addition ( + ): Adds two operands. Integer sum = 5 + 3; // 8

Subtraction ( - ): Subtracts the second


Integer difference = 5 - 3; // 2
operand from the first.

Multiplication ( * ): Multiplies two


Integer product = 5 * 3; // 15
operands.

Division ( / ): Divides the first operand Integer quotient = 5 / 3; // 1


by the second. If both operands are Decimal quotient = 5.0 / 3.0;
integers, the result is an integer. // 1.66

Modulus ( % ): Returns the remainder


of dividing the first operand by the Integer remainder = 5 % 3; // 2
second.

kshitijdhoble
Comparison Operators
Operator Details Example

Equal to ( == ): Returns true if both


Boolean isEqual = 5 == 3; // false
operands are equal.

Not equal to ( != ): Returns true if


Boolean isNotEqual = 5 != 3; // true
operands are not equal.

Greater than ( > ): Returns true if the


Boolean isGreater = 5 > 3; // true
left operand is greater than the right.

kshitijdhoble
Comparison Operators
Operator Details Example

Less than ( < ): Returns true if the


Boolean isLess = 5 < 3; // false
left operand is less than the right.

Greater than or equal to ( >= ):


Returns true if the left operand is Boolean isGreaterOrEq = 5 >= 3; // true
greater than or equal to the right.

Less than or equal to ( <= ):


Returns true if the left operand is Boolean isLessOrEq = 5 <= 3; // false
less than or equal to the right.

kshitijdhoble
Logical Operators
Operator Details Example

Logical AND ( && ):


Returns true if both Boolean result = (5 > 3) && (5 < 10); // true
operands are true.

Logical OR ( || ): Returns
true if at least one of the Boolean result = (5 > 3) || (5 < 2); // true
operands is true.

Logical NOT ( ! ): Reverses


Boolean result = !(5 > 3); // false
the logical state of its
operand.

kshitijdhoble
Bitwise Operators
Operator Details Example
Bitwise AND ( & ): Performs a bitwise
Integer result = 5 & 3; // 1
AND operation.

Bitwise OR ( | ): Performs a bitwise OR


Integer result = 5 | 3; // 7
operation.

Bitwise XOR ( ^ ): Performs a bitwise


Integer result = 5 ^ 3; // 6
XOR operation.

Bitwise NOT ( ~ ): Inverts all the bits of its


Integer result = ~5; // -6
operand.

kshitijdhoble
Assignment Operators
Operator Details Example
Assignment ( = ): Assigns the right-hand
Integer a = 5; // a = 5
operand to the left-hand operand.

Addition assignment ( += ): Adds the


right-hand operand to the left-hand operand
Integer a = 5; a += 3; // 8
and assigns the result to the left-hand
operand.

Subtraction assignment ( -= ): Subtracts the


right-hand operand from the left-hand
Integer a = 5; a -= 3; // 2
operand and assigns the result to the left-hand
operand.

kshitijdhoble
Assignment Operators
Operator Details Example
Multiplication assignment ( *= ): Multiplies
the left-hand operand by the right-hand
Integer a = 5; a *= 3; // 15
operand and assigns the result to the
left-hand operand.

Division assignment ( /= ): Divides the


left-hand operand by the right-hand operand
Integer a = 6; a /= 3; // 2
and assigns the result to the left-hand
operand.

Modulus assignment ( %= ): Performs the


modulus operation and assigns the result to Integer a = 5; a %= 3; // 2
the left-hand operand.

kshitijdhoble
Miscellaneous Operators
Operator Details Example

Ternary Operator ( ? : ): Returns one Integer result = (5 > 3) ? 10 : 20;


of two values based on a condition. // 10

Instanceof Operator ( instanceof ):


Boolean isString =
Checks whether an object is an
instance of a specific type.
'Hello' instanceof String; // true

kshitijdhoble
Logic Control Statements
● Control Flow & Loop Statements determine the flow of
execution in your code based on conditions or repeated
execution.
● Common Control Flow Statements in Apex include:
○ If - else
○ switch
● And various types of Loops include:
○ while
○ do - while
○ for
○ for - each

kshitijdhoble
if Statements
● The if-else statement executes a block of code based on
whether a condition is true or false.
● Basic if Statement example:

Integer num = 10;


if (num > 5) {
System.debug('Number is greater than 5');
} // Output: Number is greater than 5

kshitijdhoble
if - else Statements
● if - else Statement example:

Integer num = 3;
if (num > 5) {
System.debug('Number is greater than 5');
} else {
System.debug('Number is 5 or less');
} // Output: Number is 5 or less

kshitijdhoble
If - else if - else Statements
● if - else if - else Statement example:

Integer num = 5;
if (num > 5) {
System.debug('Number is greater than 5');
} else if (num == 5) {
System.debug('Number is 5');
} else {
System.debug('Number is less than 5');
} // Output: Number is 5

kshitijdhoble
Shorthand if Statements
● The ternary operator is a concise way to perform an if-else
check in a single line.

Integer num = 4;
String result =
(num > 5) ? 'Greater than 5' : '5 or less';
System.debug(result);
// Output: 5 or less

kshitijdhoble
Switch Statements
● It tests a variable against a list of values, each with its own
block of code. Here’s an example:

String fruit = 'Apple';


switch on fruit {
when 'Apple' {
System.debug('Fruit is an apple');
} when 'Banana' {
System.debug('Fruit is a banana');
} when else {
System.debug(‘it’s something else');
}
}
// Output: Fruit is an apple
kshitijdhoble
Loop Statements
● A loop in Apex is a control structure that allows you to
execute a block of code repeatedly based on a condition.
● The primary purpose of using loops is to automate
repetitive tasks by running the same code multiple times
without having to write it out manually for each iteration.
● A loop typically consists of:
○ Initialization: Setting the loop's starting point.
○ Condition: Checking if the loop should continue.
○ Body: Code that runs each iteration.
○ Iteration: Moving to the next cycle by updating a
variable.

kshitijdhoble
While Loop
● The while loop continues to execute a block of code as
long as a specified condition is true. Here’s an example:

// Iteration of numbers less than 5


Integer i = 0;
while (i < 5) {
System.debug('i: ' + i);
i++;
}
// Output: i: 0, i: 1, i: 2, i: 3, i: 4

kshitijdhoble
Do - While Loop
● The do-while loop is similar to the while loop but ensures
the block of code executes at least once before checking
the condition.
Integer i = 0;
do {
System.debug('i: ' + i);
i++;
} while (i < 5);
// Output: i: 0, i: 1, i: 2, i: 3, i: 4

kshitijdhoble
For Loop
● for loop allows you to execute a block of code repeatedly
based on a given condition. It consists of three parts:
○ Initialization: This is where you initialize a counter
variable, usually a number. This part is executed once
at the beginning of the loop.
○ Condition: The loop continues to execute as long as
this condition is true. It is checked before each
iteration.
○ Increment/Decrement: This part updates the counter
variable after each iteration. It usually increments or
decrements the counter.

kshitijdhoble
For Loop
● Example:

for (Integer i = 0; i < 5; i++) {


System.debug('i: ' + i);
}
// Output: i: 0, i: 1, i: 2, i: 3, i: 4

kshitijdhoble
For Loop
● You can also use a for loop to iterate over collections like
lists or sets in Apex. Here’s an example:
List<String> fruits = new List<String>{'Apple',
'Banana', 'Cherry'};
for (Integer i = 0; i < fruits.size(); i++) {
System.debug(fruits[i]);
} // Apple Banana Cherry
● Explanation:
○ Initialization: Integer i = 0 sets the starting index to 0.
○ Condition: i < fruits.size() ensures the loop runs until i is less
than the size of the list.
○ Increment: i++ increases the index by 1 after each iteration.

kshitijdhoble
For each Loop
● The for each loop in Apex is used to iterate over collections
such as lists, sets, or maps. It provides a clean and concise
way to iterate through elements without needing to
manage index variables manually.
● Basic Syntax:

for (Datatype variableName : collection) {


// Code block to execute for each element
// in the collection
}

kshitijdhoble
For each Loop
● Example with collection:

// iterating names from the list of strings


List<String> names = new List<String>{'Shrawni',
'Mandar', 'Parth'};
for (String name : names) {
System.debug(name);
} // Shrawni Mandar Parth

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 04
Keywords, Classes/Objects
& Constructors in

Apex
kshitijdhoble
Reserved Keywords in Apex
● Reserved keywords are special words predefined by the

Apex language that cannot be used for any other purpose,

such as naming variables or methods.

● They have specific roles and functions in the language's

syntax.

● Reserved keywords includes some Access Modifiers that

determine the visibility and accessibility of classes,

methods, and variables.

kshitijdhoble
Reserved Keywords
Usage Keywords

Control Flow if, else, switch, case, default, break, continue, do, while, for

Exception try, catch, finally, throw, assert

boolean, byte, char, double, float, int, long, short, decimal,


Data Type
string

Collection list, set, map

class, interface, enum, extends, implements, super, this,


Object Oriented
new, instanceof

private, protected, public, global, static, transient,


Access Modifier
final, abstract, override

kshitijdhoble
Reserved Keywords
Usage Keywords

insert, update, upsert, delete, undelete, merge, upsert,


DML Operations
database

SOQL Queries select, from, where, order by, group by, having, limit, offset

System Methods system, type, void, super, this, return, trigger, testmethod

Collection list, set, map

finalize, null, true, false, enum, sObject, with, when, and,


Miscellaneous
or, not, like

kshitijdhoble
Note
● Remember that some keywords, like after, before, count,

excludes, first, includes, and last, are special types of

keywords that aren’t reserved words and can be used as

identifiers.

kshitijdhoble
Access Modifiers
● An Access Modifiers are keywords used to define the

visibility and accessibility of a class, method, or variable.

● It determines where the particular class, method, or

variable can be accessed within the Salesforce platform.

● It controls the scope and encapsulation of the code,

ensuring that certain parts of the codebase are protected

from unauthorized or unintended access, thus maintaining

security and integrity.

kshitijdhoble
Access Modifiers
● private: Accessible only within the class it is defined.

○ To keep data or methods hidden from other classes.

● protected: Accessible within the class and its inner classes,

as well as in classes that extend the class (subclasses).

○ Use: To allow access to data or methods by subclasses.

● public: Accessible by any other class in your Salesforce

organization.

○ To make data or methods available throughout your

organization.

kshitijdhoble
Access Modifiers
● global: Accessible by any class in any Salesforce

organization, including managed packages.

○ To share data or methods with classes in different

Salesforce orgs or managed packages.

● static: Belongs to the class rather than an instance of the

class. Shared among all instances.

○ To create variables or methods that should be shared

across all instances of a class.

kshitijdhoble
Access Modifiers
● transient: Prevents variables from being saved during

serialization, such as when saving a Visualforce view state.

○ To store temporary data that doesn’t need to be saved.

● final: Prevents a class from being extended or a method

from being overridden.

○ To ensure the implementation of a class or method

remains unchanged.

kshitijdhoble
Access Modifiers
● abstract: Declares a class that cannot be instantiated on

its own and must be subclassed. Also used for methods

that must be implemented by subclasses.

○ To define a base class with methods that must be

implemented by subclasses.

kshitijdhoble
Defining Classes
● A Class is a blueprint for creating objects. It defines

properties (fields) and behaviors (methods), constructors

and inner classes that the objects created from the class

will have and can also used to define custom data types.

● Here’s a basic syntax of a class:

public class ClassName {


// variables
// methods and constructors
// inner classes
}

kshitijdhoble
Defining Classes
● Here’s a quick example:

public class MyClass{


public String name; // properties
public Integer age;
// constructor
public MyClass(String name, Integer age){
this.name = name;
this.age = age;
}
// method
public void displayInfo() {
System.debug(“Name: “ + name “, Age: “ + age);
}
kshitijdhoble
Defining Objects
● An object is an instance of a class. It represents a specific

entity created based on the class blueprint. An object has

its own state and behavior as defined by its class.

● We have to create object using new keyword. This keyword

is used to allocate memory.

● Here’s a basic syntax of a object:

ClassName objName = new ClassName();

kshitijdhoble
Defining Objects
● Here’s a quick example:

// creating object of MyClass (of previous example)


MyClass person = new MyClass('Kshitij', 23);

// Calling the method on the object


person.displayInfo();

// output: Name: Kshitij, Age: 23

kshitijdhoble
Constructors
● Constructor in Apex are special methods that are called

when an object is instantiated from a class.

● It initialize newly created object and set up its initial state.

● A constructor has the same name as the class and does

not have a return type, not even void.

● Primarily, Constructors are of 2 types:

○ Default Constructors

○ Parameterized Constructors

kshitijdhoble
Default Constructors
● A default constructor is a constructor that takes no

arguments.

● If no constructor is explicitly defined in a class, Apex

provides a default constructor automatically.

● That means a constructor that is automatically generated

by the compiler when there are no programmer-defined

constructors

kshitijdhoble
Default Constructors
● Default Constructor Example:

// taking previous class example (MyClass)


public MyClass(){ // default constructor
this.name = “Default Name”;
this.age = 0;
}
public void displayInfo() { // method
System.debug(“Name: “ + name “, Age: “ + age);
}// Creating object using default constructor
MyClass defaultObj = new MyClass();
defaultObj.displayInfo();
// Output: Name: Default Name, Age: 0

kshitijdhoble
Parameterized Constructors
● it’s a constructor that accepts arguments to initialize the

object's fields with specific values.

● This feature provides flexibility and control, allowing

programmers to set the initial state of an object according

to their requirements.

● We already gone through the example of Parameterized

Constructor (Defining Class Example) in which the

constructor have String and Integer type arguments.

kshitijdhoble
Constructor Overloading
● A class can have multiple constructors, each with a

different parameter list. This is known as constructor

overloading.

● It allows creating objects in different ways, depending on

the requirements.

● Defining multiple constructors with various parameter lists

to initialize objects in different ways, no matter whatever

the requirements.

kshitijdhoble
Constructor Overloading
● Constructor Overloading example:
public class MyClass{
public String name;
public Integer age;
public MyClass(){ // default constructor
this.name = “Default”;
this.age = 0;
} // parameterized constructor
public MyClass(String name, Integer age){
this.name = name;
this.age = age;
}displayInfo() {
System.debug(“Name: “ + name “, Age: “ + age);
}
}
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 05
Methods: Parameters &
Return Types in

Apex
kshitijdhoble
Defining Methods
● A Method is a block of code designed to perform a

particular task.

● In object-oriented programming, methods are defined

within a class.

● Methods can receives inputs (parameters) and return a

result.

kshitijdhoble
Defining Methods
● Here’s the basic syntax:
public [static] returnType methodName(parameterList){
// method body
// code to be executed/business logic
}
● Access Modifiers: public, private, protected, global
○ public methods are accessible by any Apex code.
○ private methods are accessible within the class.
○ protected methods are accessible within the class and
by the classes that extends the class.
○ global methods are accessible by any Apex code
anywhere.
kshitijdhoble
Defining Methods
● static methods belongs to the class itself, can be called

using ClassName and no need to create object to invoke

static method.

● Return Type is the type of value the method returns. If no

value is returned, use void.

● Method Name is the descriptive name that follows

camelCase convention.

● Parameter List is comma-separated list of input

parameters.

kshitijdhoble
Defining Methods
● Here’s an example how methods defined:
public class MyClass{
// Method with no return value and no parameters
public void sayHello() {
System.debug('Hello, Apex!');
}

// Method with a return value and parameters


public Integer addNumbers(Integer a, Integer b) {
return a + b;
}
}

kshitijdhoble
Invoking Methods
● To call a method, we use the method name followed by

parentheses.

● If the method requires parameters, we pass the arguments

inside the parentheses.

● If the method belongs to the current class, you can call it

directly.

● If it belongs to another class, you need an object of that

class to call the method.

kshitijdhoble
Invoking Methods
● Here’s an example (invoking methods of previous example):
public class TestMethods {
public static void test() {
// Creating an instance of the class
MyClass example = new MyClass();

// Invoking the sayHello() method


example.sayHello(); // output: Hello, Apex!

// Invoking the addNumbers() method


Integer sum = example.addNumbers(10, 20);
System.debug('Sum: ' + sum); // output: 30
}
}
kshitijdhoble
Parameters
● Parameters are used to pass data to methods. They allow

methods to be more flexible and reusable.

● Parameter Types:

○ Primitive: Integer, String, Boolean, Double, etc.

○ Complex: Objects, sObjects, Collections (List, Set, Map).


public class MyClass{
// method with different parameters
public void updateName(Account acc, String
newName) {
acc.Name = newName;
}
} kshitijdhoble
Return Types
● The Return Type specifies what type of value a method will

return.

● If a method does not return any value, its return type

should be void. Here’s an example:


public class MyClass {
// method that returns String
public String greetMsg(String name){
return “Hello, “ + name + “!”;
} // method that returns void
public void logMessage(String message){
System.debug(message);
}
kshitijdhoble
Best Practices
● Descriptive Method Names: Choose meaningful names

that convey the method’s purpose. Use verbs to describe

actions with camelCase.

○ Example: totalPrice, fetchAccountDetails

● Single Responsibility Principle: Each method should have

a single responsibility. Avoid methods that do too much.

○ Example: Instead of having a method that both fetches

and processes data, split it into fetchData and

processData.
kshitijdhoble
Best Practices
● Overloading Methods: Use method overloading to provide

different ways of calling a method based on different

parameter lists.

● Here’s an example:

public Integer multiply(Integer a, Integer b) {


return a * b;
}
public Double multiply(Double a, Double b) {
return a * b;
}

kshitijdhoble
Best Practices
● Avoid Hardcoding: Use constants or configuration objects

instead of hardcoding values within methods. Example:

public void applyDiscount(Double originalPrice) {

final Double DISCOUNT_RATE = 0.1; // constant

Double discountedPrice =
originalPrice * (1 - DISCOUNT_RATE);

System.debug('Discounted Price: ' +


discountedPrice);
}

kshitijdhoble
Best Practices
● Parameter Validation: Validate method parameters to

ensure they meet the expected criteria (We will go through

the concept of exception handling further).

● Here’s an example:
public void setAge(Integer age) {

// validating parameters/handling exceptions


if (age < 0) {
throw new IllegalArgumentException('Age
cannot be negative');
}
this.age = age;
} kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 06
Deep Dive into Collections,
Exception Handling in

Apex
kshitijdhoble
Deep Dive into Collections
● On 2nd Day of learning Apex Programming, we have gone

through the Collection Data Type, and now, we are going

to take a deep dive.We learned Collection and its 3 types:

○ List

○ Set

○ Map

● These different types of Collections have their own

properties, according to which we can select a particular

type to store data.


kshitijdhoble
List
● List is used to store data in sequence

● It’s a widely used collections which can store every data

type, like primitive, user-defined objects, sObjects, or other

collections.

● Main properties of List:

○ Data is stored in sequence

○ Duplicate data can be stored.

● Therefore, we should use List when sequence of element is

important, and unique data is not important.

kshitijdhoble
How to Initialize List
● Basic syntax:

List<data type> listName = new List<data type>();


// new is the keyword allocates memory to the
reference variable

// declaring empty List of String type


List<String> s1 = new List<String>();

// declaring and initializing List with values


List<Integer> i1 = new List<Integer>{10, 20, 30};

kshitijdhoble
List Methods
Methods Purpose

add( element ) To add an element

Inserts an element into the list at the specified


add( index, element)
index position.

Adds all of the elements in the specified list/set to


addAll( fromList/fromSet )
the list.Both lists must be of the same type.

clear( ) Removes all the elements from set.

clone( ) Makes a duplicate copy of a list

Compares the lists and returns true if lists are same.


equals( another list )
Order of list should be same.

kshitijdhoble
List Methods
Methods Purpose

get( index ) Returns the list element for a specified index.

isEmpty( ) To check if list is empty or not, returns boolean value.

remove( index ) Removes list element at a specified index.

set( index, element ) Replace a list element at a specified index.

size( ) Returns the number of element in a list.

sort( ) Sorts the items in a list.

contains( element ) Returns true if the list contains the specified element.

kshitijdhoble
List Method Example
// declaring List
List<String> names = new List<String>();

// adding elements
names.add(“Kshitij”); names.add(“Rudra”);
names.add(“Shrawni”); names.add(“Parth”);
System.debug(names);
// output: Kshitij, Rudra, Shrawni, Parth

// adding elements in specified index


names.add(2, Mandar);
// output: Kshitij, Rudra, Mandar, Shrawni, Parth

kshitijdhoble
List Method Example
// adding another list at specified index
List<String> emp =
new List<String>{“Kamlesh”, “Hemant”};
names.addAll(1, emp);
// output: Kshitij, Kamlesh, Hemant, Rudra,
Mandar, Shrawni, Parth

// sorting the list


names.sort();
// output: Hemant, Kamlesh, Kshitij, Mandar,
Parth, Rudra, Shrawni
// getting size of list
names.size();
// output: 7

kshitijdhoble
List Method Example
// removing element of specified index
names.remove(5);
// output: Hemant, Kamlesh, Kshitij, Mandar,
Parth, Shrawni

// getting element of specified index


names.get(2);
// output: Kshitij

// setting element of specified index


names.set(3, “Nikhil”);
System.debug(“updated list: “ + names);
// output: Hemant, Kamlesh, Kshitij, Nikhil,
Mandar, Parth, Shrawni
kshitijdhoble
List Method Example
// to check the list if empty or not
names.isEmpty(); // output: false

// to check if specified element available in list


names.contains(“Shrawni”); // output: true

// to get String representation of list


String result = names.toString();
// output: Hemant, Kamlesh, Kshitij, Nikhil,
Mandar, Parth, Shrawni

kshitijdhoble
List Method Example
// cloning list
List<String> candidates = names.clone();

// to check if both lists are equal or not


Boolean equalOrNot = names.equals(candidates);
// output: true

// clearing list
names.clear();

kshitijdhoble
Set
● Set is the collection of unique elements which is
unordered.
● Can store primitive data types, sObjects or user-defined
objects.
● Main properties of Set:
○ Only stores unique elements and not duplicate.
○ Sequence of element is not followed.
○ Elements in Set are case-sensitive.
● Therefore, we should use Set when uniqueness of data is
important and sequence is not important.

kshitijdhoble
How to Initialize Set
● Basic syntax:

Set<data type> setName= new Set<data type>();


// new is the keyword allocates memory to the
reference variable

// declaring empty Set of String type


Set<String> s1 = new Set<String>();

// declaring and initializing Set with values


Set<Integer> i1 = new Set<Integer>{10, 20, 30};

kshitijdhoble
Set Methods
Methods Purpose

add( element ) To add an element in set if its not already present.

Adds all of the elements in the specified list/set to


addAll( fromList/fromSet )
the set if they are not already present.

clear( ) Removes all the elements from set.

clone( ) Makes a duplicate copy of a set.

Compares this set with the specified set and


equals( another set )
returns true if both sets are equal.

isEmpty( ) Returns true if the set has zero elements.

kshitijdhoble
Set Methods
Methods Purpose

To add an element in set if its not already


contains( element )
present.

Returns true if the set contains all of the


containsAll( list/set ) elements in the specified list/set. The list must be
of the same type as the original set.

Removes the specified element from set if


remove( )
present.

Removes the elements in the specified list from


removeAll( list of elements )
the set if they are present.

Removes the elements in the specified set from


removeAll( set of elements )
the original set if they are present.

kshitijdhoble
Set Methods
Methods Purpose

size( ) Returns the number of elements in the set.

Compares the lists and returns true if sets are


equals( another set )
same, returns boolean value.

Retains only the elements in this set that are


retainAll( list of element )
contained in the specified list.

Retains only the elements in the original set that


retainAll( set of element )
are contained in the specified set.

toString( ) Returns the string representation of the set.

kshitijdhoble
Set Method Example
// methods like add() addAll() clear() clone()
contains() equals() isEmpty() remove() size()
toString() has same implementation as of list.

// declaring set
Set<String> names = new Set<String>{'Kshitij',
'Shrawni', 'Mandar'};

// containsAll (list of elements)


List<String> list1 = new List<String>{'Kshitij',
'Shrawni'};
System.debug(containsAll(list1));// Output: true
// similar goes with set

kshitijdhoble
Set Method Example
// removeAll (list of elements)
removeAll(list1);
System.debug(names); // Output: Set{'Shrawni'}
// same goes with set

// retainAll (list of elements)


retainAll(list1);
System.debug(names); // output: Set{‘Kshitij’}
// same goes with set

kshitijdhoble
Map
● Map is a collection of key-value pair. Key can be any
primitive type and value can be primitive, sObjects, and
other collections.
● Data stored in Map is not in sequence.
● Main properties of Map:
○ Data stored in key-value pair.
○ Data stored is not in sequence.
○ Key must be unique and value can be duplicate.
● Therefore, we should use Map when we want to quickly

find out something with the help of key.

kshitijdhoble
How to Initialize Map
● Basic syntax:

Map<key, value> mapName = new Map<key, value>();


// new is the keyword allocates memory to the
reference variable

// declaring empty Map of String type


Map<String, Integer> s1 = new Map<String, Integer>();

// declaring and initializing Map with key-values


Map<String, Integer> i1 = new Map<String,Integer>
{“English”=>10, “Maths:=>20, History=>17};

kshitijdhoble
Map Methods
Methods Purpose

clear( ) Removes all of the key-value mappings from map.

clone( ) Makes a duplicate copy of the map.

Makes a duplicate copy of a map, including sObject


deepClone( )
records if this is a map with sObject record values.

Returns true if the map contains a mapping for the


containsKey( )
specified key.

Compares this map with the specified map and


equals( ) returns true if both maps are equal; otherwise,
returns false.

kshitijdhoble
Map Methods
Methods Purpose

isEmpty( ) Returns true if the map has zero key-value pairs.

keySet Returns a set that contains all of the keys in map.

Associates the specified value with the specified


put( key, value )
key in the map.

Copies all of the mappings from the specified map


putAll( from map )
to the original map.

Removes mapping for the specified key from the


remove( key )
map, if present, and returns corresponding value.

kshitijdhoble
Map Methods
Methods Purpose

size( ) Returns the number of key-value pairs in the map.

Returns the value to which the specified key is


get( key ) mapped, or null if the map contains no value for
this key.

toString( ) Returns the string representation of the map.

Returns a list that contains all the values in the


value( )
map.

kshitijdhoble
Map Method Example
// methods like clear() clone() equals() isEmpty()
size() toString() has the same implementation as of
list and set.

// declaring map
Map<String, Integer> emp = new Map<String, Integer>
{'Kshitij'=>24, 'Shrawni'=>21,
'Mandar'=>10};

// containsKey
System.debug(emp.containsKey(“Kshitij”));
// true
System.debug(emp.containsKey(“John”));
// false

kshitijdhoble
Map Method Example
// size of map
emp.size(); // output: 3

// get value of specified key


emp.get(“Shrawni”); // output: 21

// adding new key-value in map


emp.put(“Rudra”=>20);

// clone map
Map<String, Integer> empClone = emp.clone();

kshitijdhoble
Map Method Example
// adding all the mappings to a specified map
Map<String, Integer> emp1 = new Map<String, Integer>
{'Kamlesh'=>30, 'Parth'=>34,};

emp1.putAll(emp);

// remove mapping of specified key


emp1.remove(“Parth”);

kshitijdhoble
Exception Handling
● Exception Handling is crucial in programming to manage

unexpected situations that arise during code execution.

● In Apex, exception handling helps ensure that your code can

gracefully handle errors and maintain the integrity of the

system.

● Exception is a runtime error which interrupts the normal

execution of the program.

● Hence, to keep the flow of application running, we need to

handle exceptions.

kshitijdhoble
Exception Handling
● What exactly happens when exception occurs?

○ The flow of the code disrupts.

○ Any DML operations processed before exception are

rolled back and not committed to database.

○ Exceptions get logged in debug log.

○ Salesforce sends an email for unhandled exceptions if

it isn’t catched.

○ User can see the error message on Salesforce UI.

kshitijdhoble
Exception Statements
● The throw statement is used to explicitly throw an

exception.

● You can throw a system-defined exception or a custom

exception.

● This is useful when you need to signal that an error

condition has occurred and handle it using try-catch block.

● Here’s the basic syntax:

throw new ExceptionType('Error message');

kshitijdhoble
Exception Statements
● We can handle exceptions using try-catch, finally blocks.

○ Try block contains the code that might throw an

exception. If exception occurs, catch block receives it.

○ Catch block contains code that handles the exception.

We can have multiple catch blocks to handle different

types of exceptions.

○ Finally block contains the code that is always

executed, weather exception occurs or not. It’s often

used for cleanup tasks.


kshitijdhoble
System-defined Exceptions
● In Apex, system-defined exceptions are predefined

exceptions provided by the Salesforce platform that

represent common error scenarios.

● These exceptions are built into the Apex language and are

used to handle specific types of errors that occur during

runtime.

● These exceptions are thrown by default.

kshitijdhoble
System-defined Exceptions
● There are various system-defined exceptions in Apex.

● Some Key System-defined exceptions in Apex include:

○ QueryException: thrown when SOQL query fails due


to syntax errors or exceeding governor limits.

○ DmlException: occurs when DML operation fails due


to issues like trigger errors, field-level security
restrictions or validation rule failure.

○ NullPointerException: raised when attempting to


access variable or method on a null object reference.

kshitijdhoble
System-defined Exceptions
● Example:
try {
// Attempt to call a method on a null object
Account acc = null;
String accName = acc.Name; // This will throw
NullPointerException
} catch (NullPointerException e) {
// Handle null pointer exceptions
System.debug('Null Pointer Exception: ' +
e.getMessage());
} finally { // Code that will always execute
System.debug('This block is always executed.');
}

kshitijdhoble
Custom Exceptions
● Custom exceptions are user-defined and extend the

Exception class.

● They are used to represent specific error conditions that

are unique to the application’s logic.

● We can define our own exception types that can be used

to handle specific error conditions in a more controlled

manner.

kshitijdhoble
Custom Exceptions
● Example:
public class TestCustomException {
public void checkNumber(Integer num) {
if (num < 0) {
throw new MyCustomException('Number must
be non-negative.');
}
}
}

kshitijdhoble
Exception Methods
Methods Purpose

getMessage( ) Returns the error message of exception.

getTypeName( ) Returns the type of exception as a String.

Returns the detailed information about where the


getStackTraceString( )
exception occurred.

Returns the cause of the exception if it was caused


getCause( )
by another exception, useful for nested exceptions.

Used to get line number where the exception


getLineNumber( )
occurred.

getTypeName( ) Returns the type of exception in String.

kshitijdhoble
Best Practices
● Catch specific exceptions rather than generic ones. This
allows for more precise error handling and debugging.

● Always log the exception details using System.debug().

● Do not leave catch blocks empty. Always handle or log the


exception.

● Use the finally block to close resources or perform any


cleanup operations.

● Custom exceptions should be used to represent specific


application-level errors and should be meaningful to the
context of the application.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 07
Salesforce Object Search
Language (SOQL) in

Apex
kshitijdhoble
SOQL
● Salesforce Object Query Language, is similar to SQL
(Structured Query Language).

● Specifically designed to query data in Salesforce allows us


to retrieve data from Salesforce database based on
specified conditions provided.

● SOQL is used in Apex code, Salesforce reports and various


Salesforce tools.

● SOQL is not case-sensitive, but in some parts, it’s


case-sensitive including field names, object names and
string comparison.

● A single SOQL query can return maximum 50000 rows.

kshitijdhoble
When to use SOQL
● Retrieve Data: Fetch records from one or more Salesforce
objects (like Account, Contact, Custom objects, etc.).
● Filter Results: Get specific records by using conditions
(like WHERE clauses) to filter the data.
● Join Objects: Query related objects using relationships
(like parent-child relationships).
● Sort Data: Order the retrieved records using ORDER BY
clauses.
● Aggregate Data: Use functions like COUNT, SUM, AVG to
perform calculations on the data.
● In short, use SOQL to query and manipulate Salesforce
data effectively and efficiently.

kshitijdhoble
SOQL Syntax
● Here’s the basic syntax of SOQL:

SELECT fields FROM object WHERE conditions

● Example 01:

○ To retrieve the names of all Accounts

SELECT Name FROM Account

● Example 02:

○ To retrieve all fields of all Accounts

SELECT FIELDS(ALL)
FROM Account
WHERE Name != null kshitijdhoble
SOQL Syntax in Apex
● In Salesforce, writing SOQL queries within square brackets
[ ] is a specific syntax used in Apex code.

● This syntax is known as "inline SOQL," and it allows you to


embed SOQL queries directly within Apex code.

● Here’s an example:

// query to retrieve names of all Accounts


List<Account> acc = [SELECT Name FROM Account];

kshitijdhoble
SOQL Syntax in Apex
● Why do we need to write queries in [square brackets]?

○ As we know, Apex is a server-side programming


language that runs on the Salesforce platform. It
provides the ability to execute SOQL queries to retrieve
data from Salesforce objects. The square brackets are
used to indicate that the enclosed query is a SOQL
query that Apex should execute.

○ So, when we write SOQL query in square brackets, it


always returns a List of sObjects.

kshitijdhoble
SOQL Syntax in Apex
● Example with output:

// query to retrieve names of all Accounts


List<Account> acc = [SELECT Name FROM Account];
// iterating
for (Account a : acc) {
System.debug(a.Name);
}
// output (in debug log):
USER_DEBUG|[7]|DEBUG|[
Account:{Name=Acme Corporation},
Account:{Name=Global Industries},
Account:{Name=Tech Solutions}
]

kshitijdhoble
Iteration of Query
● In Apex, we can iterate over the results of a SOQL query
using for or for-each loops, however, for-each loop is more
concise and recommended for iterating through
collections.
// using for loop
List<Account> accounts = [SELECT Name FROM Account];
for (Integer i = 0; i < accounts.size(); i++) {
System.debug(accounts[i].Name);
}
// using for-each loop
for (Account acc : [SELECT Name FROM Account]) {
System.debug(acc.Name);
}

kshitijdhoble
Variable Binding
● Variable binding allows us to use Apex variables in your
SOQL queries, enhancing flexibility and security.

● This approach helps make your queries more dynamic and


secure by preventing SOQL injection.

● In the given example below, the :accId syntax is used for


variable binding. It tells SOQL to replace :accId with the
value of the accId variable at runtime.

● Here’s an example:
public Id accId = '0015g00000P5W8kAAF';
Account acc = [SELECT Id, Name
FROM Account
WHERE Id = :accId];
kshitijdhoble
Keywords
Category Keywords

SELECT, FROM, WHERE, WITH, GROUP BY, HAVING,


Clauses
ORDER BY, LIMIT, OFFSET

TYPEOF, WHEN, THEN, ELSE, END, USING SCOPE, FOR VIEW,


Miscellaneous FOR REFERENCE, UPDATE TRACKING, UPDATE VIEWSTAT,
FOR UPDATE

● SELECT: Specifies the fields to retrieve from the database.


● FROM: Indicates the object from which to retrieve data.
● WHERE: Filters records based on specified conditions.
● WITH: Filters records using data categories.

kshitijdhoble
Keywords
● GROUP BY: Aggregates records by specified fields.
● HAVING: Filters aggregated records based on conditions.
● ORDER BY: Sorts the query results by specified fields.
● LIMIT: Restricts the number of records returned.
● OFFSET: Skips a specified number of records in query results.
● TYPEOF: Handles polymorphic relationships in queries.
● WHEN: Specifies conditions within a TYPEOF expression.
● THEN: Defines the result for a WHEN condition.
● ELSE: Provides an alternative result if no WHEN conditions
met.

kshitijdhoble
Keywords
● END: Concludes a TYPEOF expression.
● USING SCOPE: Limits query results based on a specified
scope.
● FOR VIEW: Retrieves records for viewing purposes.
● FOR REFERENCE: Retrieves records for reference purposes.
● UPDATE TRACKING: Tracks changes to records.
● UPDATE VIEWSTAT: Updates view statistics for records.
● FOR UPDATE: Locks records for update.

kshitijdhoble
Operators
Category Operators

Logical Operators AND, OR, NOT

=, !=, <, >, <=, >=, LIKE, IN, NOT IN,


Comparison Operators
INCLUDES, EXCLUDES, BETWEEN

● AND: Combines multiple conditions, all of which must be


true.
● OR: Combines multiple conditions, any of which can be true.
● NOT: Negates a condition, making it true if the condition is
false.

kshitijdhoble
Operators
● ( = ) Checks if a value is equal to a specified value.
● ( != ) Checks if a value is not equal to a specified value.
● ( < ) Checks if a value is less than a specified value.
● ( > ) Checks if a value is greater than a specified value.
● ( <= ) Checks if a value is less than or equal to a specified
value.
● ( >= ) Checks if a value is greater than or equal to a specified
value.

kshitijdhoble
Operators
● LIKE: Checks if a value matches a specified pattern.
● IN: Checks if a value matches any value in a specified list.
● NOT IN: Checks if a value does not match any value in a
specified list.
● INCLUDES: Checks if a multi-select picklist field includes a
specified value.
● EXCLUDES: Checks if a multi-select picklist field excludes a
specified value.
● BETWEEN: Checks if a field value falls within a specified
range.

kshitijdhoble
Aggregate Functions
● Aggregate Functions are used to perform calculations on a
set of records and return a single value.
● useful for summarizing or grouping data to get meaningful
insights. Here are the main aggregate functions in SOQL:

Function Purpose

AVG( ) Returns the average value of a numeric field.

COUNT( ) Returns the number of rows matching the query criteria.

COUNT_DISTINCT( ) Returns the number of rows matching the query criteria.

MIN( ) Returns the minimum value of a field.

MAX( ) Returns the maximum value of a field.

SUM( ) Returns the total sum of a numeric field.

kshitijdhoble
Wild Cards
● In SOQL, the % and _ wildcards are used with LIKE operator:

○ % Matches zero or more characters. For example, name

LIKE 'John%' finds “John”, “Johnson”, “Johnny”, etc.

○ _ Matches exactly one character. For example, name

LIKE 'J_hn' finds “John” and “Jahn” but not "Johnson"

kshitijdhoble
Relationship Queries
● Relationship queries traverse parent-to-child and

child-to-parent relationships between objects to filter and

return results.

● Relationship queries are similar to SQL joins. However, you

cannot perform arbitrary SQL joins.

● Parent-to-child and child-to-parent relationships exist

between many types of objects. For example, Account is a

parent of Contact.

kshitijdhoble
Relationship Queries
● Parent-to-Child Relationship Queries (Subqueries):
○ Parent-to-Child relationship queries involve querying
related child records from a parent record.
○ This is done using subqueries.
○ Here’s an example: Query list of Accounts along with
their related Contacts.
SELECT Name,(SELECT FirstName, LastName
FROM Contacts)FROM Account

kshitijdhoble
Relationship Queries
● Child-to-Parent Relationship Queries (dot notation)
○ Child-to-Parent relationship queries involve querying
fields from a parent record when you are querying
from the child record.
○ This is done using dot notation.
○ Here’s an example: list of Contacts along with the
name of the Account they belong to.
SELECT FirstName, LastName, Account.Name
FROM Contact

kshitijdhoble
Multi-level Relationship Queries
● SOQL supports up to five levels of parent-to-child
relationships.
● We can traverse up to a maximum of five levels when
querying data from child-to-parent relationships.
● Here’s an example:
SELECT Name,
(SELECT LastName,
(SELECT AssetLevel,
(SELECT Description,
(SELECT LineItemNumber
FROM WorkOrderLineItems)
FROM WorkOrders)
FROM Assets)
FROM Contacts)
FROM Account kshitijdhoble
Dynamic SOQL
● Dynamic SOQL refers to the creation of a SOQL string at
runtime using Apex code.
● This allows for more flexible and customizable queries
based on user input or other variables.
● Here are some key points:
○ Creation: Dynamic SOQL queries are constructed as
strings at runtime.
○ Execution: Use Database.query or
Database.queryWithBinds methods to execute the
dynamic query.
○ Flexibility: Allows for dynamic filtering and querying
based on varying criteria.

kshitijdhoble
Dynamic SOQL
● Dynamic SOQL refers to the ability to create SOQL

queries at runtime, providing more flexibility.

● The method Database.query executes the dynamic SOQL

and returns the results. Example:


String queryString = 'SELECT Id, Name
FROM Account
WHERE Name LIKE \'%Acme%\'';
List<Account> acc = Database.query(queryString);

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 08
Salesforce Object Search
Language (SOSL) in

Apex
kshitijdhoble
SOSL
● SOSL (Salesforce Object Search Language) is a language
used to perform text searches in Salesforce records.

● It allows you to search for specific information across


multiple Salesforce objects simultaneously.

● Unlike SOQL (Salesforce Object Query Language), which is


used to retrieve records from a single object, SOSL can
search across different objects, including standard and
custom objects, based on text fields.

kshitijdhoble
SOSL
● Why we need SOSL?

○ SOSL is particularly useful when you need to search for


data across multiple objects, such as when a user
enters a search term in a global search bar.

○ Instead of querying each object individually using


SOQL, SOSL provides a more efficient way to find
records that match the search term across multiple
objects in one go.

○ It is also handy when we are unsure of which object


contains the data you are looking for.

kshitijdhoble
SOSL Syntax
● We can write SOSL in 2 formats:

○ Query Language Format: It is a specific query


language used within the Salesforce ecosystem.
FIND 'searchTerm'
IN SCOPE
RETURNING ObjectName1 (Field1, Field2),
ObjectName2 (Field1, Field2)

// example
FIND 'Acme'
IN ALL FIELDS
RETURNING Account(Name),
Contact(FirstName, LastName)
kshitijdhoble
SOSL Syntax
○ Apex Query Format: In Apex, SOSL queries are written
within square brackets [ ] and the result is a list of lists
of sObjects.
List<List<sObject>> results =
FIND 'searchQuery'
IN searchGroup
RETURNING objectType1(fields),
objectType2(fields)];
// example
List<List<sObject>> searchResults =
[FIND 'Acme' IN ALL FIELDS
RETURNING Account(Id, Name),
Contact(Id, Name)];

kshitijdhoble
Keywords in SOSL
Keywords Purpose

FIND Specifies the text to search for.

Defines the scope of fields to search (e.g., ALL FIELDS, NAME


IN
FIELDS, EMAIL FIELDS).

RETURNING Specifies the fields and objects to return.

Adds filters such as DivisionFilter, DataCategorySpec,


WITH
NetworkIdSpec, PricebookId, and Metadata.

LIMIT Limits the number of rows returned.

OFFSET Skips a specified number of rows in the result set.

Tracks keywords used in searches (e.g., TRACKING,


UPDATE
VIEWSTAT).

kshitijdhoble
Scope in SOSL
● In SOSL, the scope determines which fields are searched.
Here are the different scopes we can use:

Scope Purpose

ALL FIELDS Searches across all searchable fields.

NAME FIELDS Searches within name-related fields.

EMAIL FIELDS Searches within email-related fields.

PHONE FIELDS Searches within phone-related fields.

SIDEBAR FIELDS Searches within fields indexed for the Salesforce sidebar

kshitijdhoble
Filters in SOSL
● In SOSL, we can use various filters to refine your search
results. Here are the main filters available:
Filters Purpose

DivisionFilter Filter results based on divisions.

DataCategorySpec Filters results based on data categories.

NetworkIdSpec Filters results based on network IDs.

PricebookId Filters results based on pricebook IDs.

Metadata Filters results based on metadata.

WITH SNIPPET Filters results to include snippets of the search results.

UPDATE TRACKING Tracks keywords used in searches.

UPDATE VIEWSTAT Tracks view statistics of the search results.

kshitijdhoble
Wildcards in SOSL
● Wildcards in SOSL (Salesforce Object Search Language)
are special characters used to broaden the scope of a
search query by allowing partial matches. They are useful
when you don’t know the exact term you’re searching for
or want to capture variations of a word or phrase.

● There are 2 wildcards in SOSL:

○ Asterisk ( * )

○ Question Mark ( ? )

kshitijdhoble
Wildcards in SOSL
● Asterisk ( * )
○ The asterisk wildcard matches zero or more characters
in a search term. It’s used to search for any sequence of
characters before or after a specified string. It is
typically placed at the beginning or end of a search
term to find words that start with or contain a specific
string.
○ Here’s an example:
FIND 'Acme*' IN ALL FIELDS RETURNING Account(Id, Name)
// This will find any record where a field starts with
"Acme" (e.g., "Acme Corp", "Acme Inc.").

FIND '*tech' IN NAME FIELDS RETURNING Contact(Id, Name)


// This will find any contact whose name ends with
"tech" (e.g., "TechSolutions", "Innotech").

kshitijdhoble
Wildcards in SOSL
● Question Mark ( ? )
○ The question mark wildcard matches exactly one
character. It’s used when you want to search for a
string with one variable character.
○ Example:
FIND 'Sm?th' IN NAME FIELDS RETURNING Contact(Id, Name)
// This will find contacts with names like "Smith" or
"Smyth" but not "Smithe" or "Smoth".

FIND '?ohn' IN NAME FIELDS RETURNING Contact(Id, Name)


// This will match "John" or "Rohn" but not "Djohn".

kshitijdhoble
SOSL Result Structure
● Why SOSL returns List of List of sObjects?

○ SOSL can search across multiple Salesforce objects at


once in single query, and each object type can have its
own set of search results.

○ Each list contains the results from the search for a


particular sObject type.

○ A SOSL query always returns results in the same order


that was specified in the SOSL query.

kshitijdhoble
SOSL Result Structure
● SOSL searches can retrieve data from several different
objects in a single query. For each object type specified in
the RETURNING clause, SOSL generates a separate list of
results.
● The outer List<List<sObject>> structure allows SOSL to
group the search results by object type. Each inner
List<sObject> corresponds to the search results for one
object type. This means that if we search across three
objects (Account, Contact, Opportunity), the result will be a
list containing three lists - one for each object type.
● This structure makes it easier to handle and process results
by object type. We can individually access the results for
each object type by referencing the appropriate index in
the outer list.
kshitijdhoble
SOSL Result Structure
// Consider the following SOSL query:
List<List<sObject>> searchResults = [FIND 'Acme' IN ALL
FIELDS RETURNING Account(Id, Name), Contact(Id, Name)];

// Explanation of results and visual representation:


searchResults = [
[Account1, Account2], // List of Account objects
[Contact1, Contact2] // List of Contact objects
]
// searchResults is a list containing two lists:
searchResults[0]: Contains a list of Account records
that matched the search query.
searchResults[1]: Contains a list of Contact records
that matched the search query.

kshitijdhoble
Dynamic SOSL
● Dynamic SOSL allows you to construct and execute SOSL
queries at runtime, giving you flexibility in building search
queries based on user input or other dynamic conditions.

● This can be especially useful in scenarios where the search


criteria or objects being queried are not known until the
code is executed.

● Dynamic SOSL allows us to create more flexible


applications. For example, we can create a search based on
input from an end user, or update records with varying
field names.

kshitijdhoble
Key Concepts
● String-based query construction:
○ Unlike static SOSL, where the query is hard-coded,
dynamic SOSL involves constructs query as a string.
○ The query string is built using Apex string
manipulation techniques, such as concatenation or
string variables.
● Execution using Search.query( ):
○ The dynamically constructed query string is passed to
the Database.query() method, which executes the
SOSL query.
○ This method returns the results in the same format as
a static SOSL query: a List<List<sObject>>.

kshitijdhoble
Detailed Structure
● Defining search term in String variable:
String searchTerm = ‘Acme’’;
● Constructing SOSL query by concenating search term:
String soslQuery = 'FIND \'' + searchTerm + '\'
IN ALL FIELDS
RETURNING Account(Id, Name),
Contact(Id, Name)';
● Executing the query using Search.query( ):
List<List<sObject>> searchResults =
Search.query(soslQuery);

kshitijdhoble
Advantages
● Advantages of Dynamic SOSL

○ Flexibility: You can create highly flexible queries based


on runtime conditions, user inputs, or other variables.

○ Reusability: Dynamic SOSL allows you to build


reusable code that can adapt to different search
criteria without hardcoding every possible scenario.

○ Interactivity: Dynamic SOSL can be used in interactive


applications where search parameters are provided by
users at runtime.

kshitijdhoble
Use Cases
● User-Driven Searches: Create searches based on what
users are looking for.

● Dynamic Field Updates: Update records with varying field


names based on runtime conditions.

kshitijdhoble
SOQL / SOSL Difference
Feature SOQL SOSL

Retrieve records from a single Search for specific text across


Purpose
object or related objects. multiple objects.

Queries specific fields in one or Searches multiple objects


Scope
more related objects. and fields simultaneously.

Returns a list of lists of


Return Type Returns a list of sObjects.
sObjects.

Returns predefined fields,


Field Can select specific fields to
unless specified using
Limitation retrieve.
RETURNING clause.

Works on a single object at a time, Can search across multiple


Search
though you can query related objects at once (standard
Scope
objects using relationships. and custom).

kshitijdhoble
Best Practices
● Input Sanitization: Be cautious of SOSL injection, a
security risk where malicious input could alter your query.
Always validate or escape user inputs.

● Error Handling: Use try-catch blocks to handle any


exceptions that may occur during the execution of
dynamic SOSL queries.

● Performance Considerations: Dynamic SOSL queries can


become complex and may impact performance if not
constructed efficiently. Use them judiciously, especially in
environments with large datasets.
kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 09
DML Statements &
Database Class Methods in

Apex
kshitijdhoble
What is DML?
● Data Manipulation Language (DML) refers to the set of

operations used to manipulate data within a database.

● In Salesforce, DML operations allow you to interact with

Salesforce objects (sObjects) to create, update, delete, and

retrieve records.

● These operations are essential for managing data and are

used within Apex to perform various database-related

tasks.
kshitijdhoble
DML Uses
● DML used in Salesforce when you need to manage and
manipulate records in the database.

● Whether you need to create new records, update existing


ones, or remove records, DML operations provide the
necessary commands to perform these tasks
programmatically.

● This allows developers to automate processes, enforce


business logic, and ensure data integrity within Salesforce.

kshitijdhoble
Syntax & Structure
● Direct DML Statements:
○ These are straightforward commands like insert,
update, delete, etc. Example:
Account acc = new Account(Name='Acme Corporation');
insert acc;
● Database Class Methods: (We will cover this further)
○ This provides more control over DML operations,
allowing for fine-grained exception handling and the
ability to execute partial operations. Example:
Account acc = new Account(Name='Acme Corporation');
Database.SaveResult sr = Database.insert(acc, false);

kshitijdhoble
Various DML Statements
● Insert: To add new records in Salesforce.

// Inserting a new Account record


Account acc = new Account();
acc.Name = 'New Account';
acc.Industry = 'Technology';
acc.AnnualRevenue = 1000000;

// Insert the Account record


insert acc;

kshitijdhoble
Various DML Statements
● Update: To modify existing records in Salesforce.

// Query an existing Account record


Account acc = [SELECT Id, Name, Industry FROM Account
WHERE Name = 'New Account' LIMIT 1];

// Update the Account record


acc.Industry = 'Software';
acc.AnnualRevenue = 2000000;

// Perform the update


update acc;

kshitijdhoble
Various DML Statements
● Delete: To remove records from Salesforce.

// Query the Account record to be deleted


Account acc = [SELECT Id
FROM Account
WHERE Name = 'New Account'
LIMIT 1];

// Delete the Account record


delete acc;

kshitijdhoble
Various DML Statements
● Undelete: To restore records that have been deleted and
are still in the Recycle Bin.

// Query the deleted Account record


Account acc = [SELECT Id
FROM Account
WHERE Name = 'New Account'
AND IsDeleted = TRUE
LIMIT 1
ALL ROWS];

// Undelete the Account record


undelete acc;

kshitijdhoble
Various DML Statements
● Upsert: To insert a record if it doesn't exist or update it if it
does.
// Create new Account record with external Id field
Account acc = new Account();
acc.Name = 'New Account';
acc.Industry = 'Finance';
acc.ExternalId__c = '12345'; // Assume externalId__c
is a unique field

// Perform the upsert operation


upsert acc ExternalId__c; // If the ExternalId__c
already exists, it will update the record,
otherwise, it will insert a new one

kshitijdhoble
Various DML Statements
● Merge: Combines up to 3 records of same object type into
one, keeping the master record and merging others. Use
merge to clean up duplicate records in Salesforce org.
Account master = [SELECT Id FROM Account
WHERE Name='Acme Corp'
LIMIT 1];
Account duplicate1 = [SELECT Id FROM Account
WHERE Name='Acme Corp'
AND Id != :master.Id LIMIT 1];
Account duplicate2 = [SELECT Id FROM Account
WHERE Name='Acme Corp'
AND Id != :master.Id
AND Id != :duplicate1.Id
LIMIT 1];
merge master duplicate1 duplicate2;
kshitijdhoble
Bulk DML Operations
● Bulk DML operations are used when you need to perform
DML on multiple records at once.
● Apex automatically optimizes bulk DML operations to
ensure efficiency and to avoid hitting governor limits.
● Here’s a simple example in which we are trying to insert
100 contacts at once using DML statement.
// inserting 100 contacts at once
List<Contact> contacts = new List<Contact>();
for (Integer i = 0; i < 100; i++) {
contacts.add(new Contact(FirstName='John',
LastName='Doe' + i));
}
insert contacts;

kshitijdhoble
Database Class Methods
● The Database class in Apex provides specialized methods
for executing DML (Data Manipulation Language)
operations.

● These methods offer more flexibility and control compared


to standard DML operations like insert, update, delete, etc.

● Specifically, the Database class methods allows to handle


exceptions, control transactions, and process records in
bulk, making it easier to manage complex data operations.

kshitijdhoble
Use Cases
We use Database class methods for several reasons:
● Partial Success Handling: Unlike standard DML
operations that fail entirely if one record causes an error,
Database class methods allow partial success. This means
some records can be successfully processed even if others
fail.
● Exception Handling: Database methods provide a way to
capture detailed error information, enabling developers to
handle exceptions more effectively.
● Bulk DML Operations: These methods are designed to
work efficiently with large datasets, respecting Salesforce's
governor limits and allowing bulk processing.
● Transaction Control: They allow more refined control over
transactions, such as rolling back operations if certain
conditions aren't met.
kshitijdhoble
Methods in Database Class
Methods Purpose

Inserts records with an option to allow


Database.insert(records, allOrNone)
partial success.

Updates records with the option for partial


Database.update(records, allOrNone)
success.

Deletes records with the option for partial


Database.delete(records, allOrNone)
success.

Upserts records with the option for partial


Database.upsert(records, allOrNone)
success.

Database.merge(masterRecord,
Merges records with a master record.
recordsToMerge)

- records: List of sObjects to perform DML operation.


- allOrNone: Boolean indicating if all records
must perform operation successfully or none at all
kshitijdhoble
Exception Handling in DML
● Exception Handling is the process of managing errors or
exceptions that occur during code execution.
● In the context of DML operations, exceptions can happen
due to various reasons like validation rule failures, missing
required fields, or sharing rule violations.
● Handling Exceptions Using Database Class Methods:
○ Exceptions can be captured using try-catch blocks,
allowing developers to gracefully manage errors.
○ The Database methods return a Database.SaveResult
object or a list of Database.SaveResult objects. This
object contains information about the success or
failure of each DML operation, making it possible to
handle exceptions on a per-record basis.

kshitijdhoble
Exception Handling in DML
Database Class Methods Result Object:

● The Database.SaveResult object is returned by Database


class methods and provides information about the
outcome of DML operations.

● isSuccess(): Returns true if the operation was successful.

● getId(): Returns the ID of the record if the operation was


successful.

● getErrors(): Returns an array of Database.Error objects


that contain detailed information about the errors.

kshitijdhoble
Partial Execution
● Partial Exception occurs when a DML operation succeeds
for some records and fails for others.

● The Database class methods allow partial success,


meaning the operation does not rollback the entire
transaction if one or more records fail.

● Instead, it processes the successful records and provides


detailed information on the failures.

● DML don’t allow partial execution and directly throw


exception, and the whole transaction gets rolled back.

● So, in this case, we need to use Database Class Methods.


Further we will see such scenario in which we’ll discuss it
with and without these methods.
kshitijdhoble
Scenario - Partial Execution
● DML don’t support partial execution. Here’s a scenario:
// creating 2 Contact records
List<Contact> cc = new List<Contact>();
cc.add(new Contact( FirstName = 'Kshitij',
LastName = 'Dhoble', Email = '[email protected]'));
cc.add(new Contact( FirstName = 'Rudra',
Email = '[email protected]'));
insert cc;// this code will get exception because we
skipped LastName as it’s required field in salesforce
try{insert cc;} catch(DmlException e){
System.debug(‘Exception during record insertion’);}
// after using try-catch, we didn’t get exception,
but in debug log, we can see the message provided in
catch block. Contd…
kshitijdhoble
Scenario - Partial Execution
● This is how DML don’t support partial execution. That’s
why, Database Class Methods comes in picture.
// The same scenario using Database Class Methods.
So in the try-catch block, we’ll replace the DML
statement (insert) with this method.

Database.SaveResult[] results =
Database.insert(cc, true);

// but again, the record not saved and same error


message in debug log. This is because, in the method,
we passed the 2nd parameter as true, which means
“don’t allow partial execution”. Contd…

kshitijdhoble
Scenario - Partial Execution
● Hence we need to pass false to perform partial execution.
// handling exceptions with partial execution.
try{ Database.saveResult[] results =
Database.insert(cc, false);
for(Database.saveResult rr : results){
if (rr.isSuccess()){
System.debug(“Contact Inserted” + rr.getId());
}else{ for(Database.error er : rr.getErrors()){
System.debug(“Error” + er.getMessage());}}
}catch(DmlException e){
System.debug(“Exception during record insertion”
+ e.getLineNumber());
}

kshitijdhoble
Scenario - Partial Execution
● In the previous Apex code, we passed the parameter as
false. Also we iterated over results to get ID of records
which are saved successfully and error message for records
which are failed

● And now, one record is inserted and another not inserted.

● Hence, this proves that Database Class Methods can


perform partial execution.

● By using this, we can avoid rolling back of whole


transaction.

kshitijdhoble
Transaction Control / Roll Back
● Salesforce treats DML operations within a single execution
context as a transaction.

● If one operation fails, the entire transaction is rolled back


unless we explicitly handle exception using Database
methods.

● We can use savepoints to rollback to a specific state in the


transaction using method: Database.setSavepoint()

● Rollback: The Database.rollback() method reverts the


transaction to a specified savepoint.

kshitijdhoble
Best Practices
● Bulkifying Code: Always handle multiple records at once
to avoid hitting governor limits.

● Use Database methods for better exception handling and


control over operations.

● Avoid Hardcoding IDs: Use dynamic SOQL or


@salesforce/schema to reference IDs and fields.

● Always catch exceptions and handle them appropriately to


avoid transaction failures.

● Combine similar DML operations to reduce the number of


DML statements in your code.

kshitijdhoble
Note
● Never exceed allowed number of DML Statements as per

governor limits.

● Never write DML Statements inside loop.

● We can only execute 150 DML statements per execution of

code, that’s why we should write DML statements outside

the loop.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 10
Synchronous Apex - Triggers
in

Apex
kshitijdhoble
Synchronous Apex
● Synchronous Apex refers to processes that execute

immediately in a single thread.

● When a synchronous process is initiated, it waits until it

completes before the next operation begins.

● This means the user interface (UI) will block and wait for

the process to finish, making it ideal for operations that

need immediate feedback.

kshitijdhoble
Why Synchronous Apex?
● Why Do We Use Synchronous Apex?

● Synchronous Apex is used when you need immediate


results from a process, such as:

○ Real-time data validation or processing.

○ Operations that must be completed in sequence


without delays.

○ Ensuring that a task is completed before moving on to


the next step (e.g., validating user input before saving
records).

kshitijdhoble
Types of Synchronous Apex
● Types of Synchronous Apex:

● Triggers: An Apex code that executes before or after the


changes occurs to Salesforce records.

● Apex Callouts: Apex can call external web services


synchronously. The callout waits for a response from the
external service before proceeding.

● Visualforce Controllers: Controllers that process logic


when a user interacts with a Visualforce page. Operations
are handled immediately, with real-time feedback on UI.

kshitijdhoble
What is Trigger?
● A Trigger in Salesforce Apex is a piece of code that
automatically executes before or after certain events occur
on a Salesforce object.

● Triggers allow developers to implement complex business


logics and to perform custom actions when records are
created, updated, deleted, or undeleted, etc in Salesforce.

● Triggers are written in Apex, Salesforce's proprietary


programming language, and they operate on
database-level events to automate processes or enforce
business logic.
kshitijdhoble
Key Points
● Automation: Triggers are used to automate tasks and

enforce business rules.

● Execution Context: Triggers run in the context of the

Salesforce object they are associated with.

● Declarative Control: While triggers provide powerful

capabilities, they must be used carefully to avoid

unintended consequences, such as recursive triggers or

performance issues.

kshitijdhoble
Types of Triggers
● Before Triggers:

● A before trigger is a type of trigger in Apex that executes


its logic before a record is committed to the database.

● This means that any operations performed in a before


trigger take place before the data is saved or modified in
the database.

● Before triggers are primarily used for data validation,


modification, or setting default values before the data is
actually saved.

kshitijdhoble
Types of Triggers
● After Triggers:

● An after trigger is a type of trigger in Apex that executes its


logic after a record has been committed to the database.

● This means that any operations performed in an after


trigger take place after the data has already been saved or
modified in the database.

● After triggers are typically used when you need to perform


operations that depend on the record being committed,
such as working with related records or performing
additional processing.
kshitijdhoble
Use Cases - Before Triggers
● Data Validation: Check data validity before saving. For
example, ensuring mandatory fields are filled or values
meet criteria.

● Data Modification: Modify field values before saving. For


example, set default values based on conditions.

● Setting Relationships: Establish or modify record


relationships before saving.

● Preventing Operations: Block record insertion or updates


by throwing exceptions if conditions aren’t met.

kshitijdhoble
Use Cases - After Triggers
● Accessing System Fields: Use after triggers to access
fields like Id or CreatedDate that are available only after the
record is saved.
● Related Records: Create, update, or delete related records.
For instance, create a contact when an account is inserted.
● Callouts: Make callouts to external systems after a record is
saved, but do this cautiously to avoid performance issues.
● Complex Business Logic: Perform complex logic that
requires the record to be committed, such as aggregating
data based on new or updated records.

kshitijdhoble
Trigger Events
● Trigger events are specific database operations that cause
a trigger to fire in Salesforce.

● These events determine when and why the trigger's logic


is executed.

● Each trigger event corresponds to a type of operation


performed on a Salesforce object, such as inserting,
updating, or deleting records.

● Understanding trigger events helps in designing effective


triggers that respond appropriately to changes in the data.

kshitijdhoble
Trigger Events
● Before Insert executes before a new record is inserted.
Ideal for validating or modifying record values before they
are committed.
● Before Update executes before an existing record is
updated. Useful for checking and updating record values
before they are saved.
● Before Delete executes before an existing record is
deleted. Allows you to perform cleanup or validation tasks
before the record is removed.
● Before Merge executes after records have been merged
into a single record. Allows you to perform actions or
validations before the merge operation is finalized. This
event is used to handle scenarios where you need to
validate or adjust the records that will be merged.

kshitijdhoble
Trigger Events
● After Insert Executes after a new record is inserted.
Suitable for actions that require the record to be saved,
such as creating related records or making external system
callouts.

● After Update executes after an existing record is updated.


Ideal for actions that depend on the updated record being
saved, such as updating related records or aggregating
data.

● After Delete executes after an existing record is deleted.


Useful for cleanup tasks or updating related records that
depend on the deleted record.

kshitijdhoble
Trigger Events
● After Undelete executes after a record is recovered from
the Recycle Bin. Allows you to perform actions based on
records that have been restored, such as re-establishing
relationships or updating related records.

● After Merge executes after records have been merged into


a single record.Useful for actions that need to be taken
once the merge is complete. This event allows you to
perform tasks like updating related records, cleaning up
data, or aggregating information based on the merged
records.

kshitijdhoble
Before undelete
● The event before undelete is not available because:

● Before the record is undeleted, Salesforce does not provide


a way to intercept the operation before it happens.

● The undelete operation is effectively a restoration process


that occurs outside the usual transactional context where
you would need to intercept and modify the data before it
is saved.

● Therefore, only After Undelete is supported, allowing


developers to perform actions once the record has been
fully restored.
kshitijdhoble
After upsert
● The upsert operation is not available in after triggers for
these reasons:

● It could potentially create an infinite loop or it may lead to


unexpected behaviour.

● The upsert contains insert and update operations together.


So this event will either create new record if it not exists or
it will require a record that already exists to update it.

● It can be recursive, the trigger will be fired repeatedly.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 11
Apex Triggers (Part 2)
in

Apex
kshitijdhoble
Flow of Triggers
Initiate
Database Before Trigger
Operation

Database
After Trigger
Operation

kshitijdhoble
Flow of Triggers
● Initiate Database Operation: This is where the action
begins, typically from a user’s action in the Salesforce UI, a
code execution, or an external system.
● Before Trigger: Before the actual database operation is
committed, the before trigger executes. This is where you
can perform validation or set values before they are
committed to the database.
● Database Operation: After the before trigger completes
successfully, the database operation (like INSERT, UPDATE,
DELETE, UNDELETE) is executed.
● After Trigger: Once the database operation is completed,
the after trigger runs. This is typically used when you need
to make changes that rely on the database operation
having been completed
kshitijdhoble
Syntax
● A trigger in Salesforce has a specific structure. Here’s
the syntax breakdown:
trigger TriggerName on ObjectName(trigger_events)
{
// validations
// custom logic
// code to be executed
}
● trigger is the keyword used to declare a trigger.
● TriggerName could be any name for trigger.
● ‘on’ keyword binds the trigger to a specific Salesforce object.
● trigger_events are the specific DML events that will cause
the trigger to fire.

kshitijdhoble
Example
● Scenario: Write a trigger on the Account object that
automatically sets the Description field to "New Account"
whenever a new account record is inserted.

trigger AccountTrigger on Account (before insert)


{
for (Account acc : Trigger.new) {
acc.Description = 'New Account';
}
}

kshitijdhoble
Facts
● A single Apex trigger can handle multiple events, including
before and after events for insert, update, delete, merge,
upsert, and undelete. To specify multiple events, use a
comma-separated list in the trigger syntax.

● The maximum number of triggers you can have per object


is two: one 'before' trigger and one 'after' trigger. This
limitation ensures efficient execution and helps maintain
code clarity. However, within each trigger, you can
implement multiple operations and logic based on your
requirements.

kshitijdhoble
Order of Execution of Triggers
● The order of execution in Apex triggers is a defined
sequence that Salesforce follows when processing a record
in the database.
● Understanding this order is crucial for ensuring that your
code behaves as expected, especially when multiple
triggers, workflows, and validations are involved.
● Here’s the order of execution when a record is created,
updated, or deleted:
1. System Validation Rules: Basic checks like required fields
and data types are performed.
2. Before Triggers: Executes before saving the record, used
to validate or modify values.

kshitijdhoble
Order of Execution of Triggers
3. System Validation Rules (Again): Re-validates the record,
including custom rules.
4. Duplicate Rules: Checks for duplicates, potentially halting
the process.
5. Record Saved (Not Committed): The record is saved but
not yet committed.
6. After Triggers: Executes after saving the record, often used
for related operations.
7. Assignment Rules: Processes lead or case assignment
rules.
8. Auto-Response Rules: Processes auto-response rules for
leads and cases.
kshitijdhoble
Order of Execution of Triggers
9. System Validation Rules (Again): Re-validates the record,
including custom rules.
10. Workflow Rules: Evaluates and processes any triggered
workflow rules.
11. Escalation Rules: Processes escalation rules for cases.
12. Processes and Flows: Processes any triggered processes
or flows.
13. Entitlement Rules: Processes entitlement rules if
applicable.
14. Roll-Up Summary Fields: Recalculates parent roll-up
summary fields.

kshitijdhoble
Order of Execution of Triggers
15. Commit Transaction: Attempts to commit the transaction;
if errors occur, it rolls back.
16. Post-Commit Logic: Executes post-commit actions like
sending emails.
17. DML on Related Records: Repeats the process for any
related records affected.
18. Email Notifications: Sends out any triggered email
notifications.

kshitijdhoble
Trigger Context Variables
● Trigger context variables in Apex are special variables that
Salesforce automatically provides within a trigger.

● It allows developers to access the runtime context of any


trigger.

● These variables give you access to the records and


metadata that are being manipulated by the trigger,
allowing you to perform actions based on the state of
those records.

● These variables are contained in System.Trigger Class.

kshitijdhoble
Trigger Context Variables
● Trigger.new
○ It returns list of new version of sObject records that are
being inserted or updated.
○ Trigger.new is only available for insert, update, and
undelete operations, it’s not available in delete because
there’s no new version of records when they are
deleted.
● Trigger.old
○ It returns list of old version of sObject records that are
being updated or deleted.
○ Trigger.old is only available for update and delete
operations, it’s not available in insert triggers because
there are no old versions of the records.

kshitijdhoble
Trigger Context Variables
● Trigger.newMap
○ It returns a map of record IDs to the new versions of
the records. This is useful when you need to quickly
access a record by its ID.
○ Trigger.new is available for insert and update
operations and not available for delete operations.
● Trigger.oldMap
○ it returns a map of record IDs to the old versions of the
records. This is useful when you need to quickly access
a record by its ID.
○ Trigger.old is available for update and delete
operations and not available for insert operations.

kshitijdhoble
Trigger Context Variables
● Trigger.isInsert
○ Returns true if the trigger was fired due to an INSERT
operation. This is useful for performing actions only
when records are being inserted.
● Trigger.isUpdate
○ Returns true if the trigger was fired due to an UPDATE
operation. You can use this to handle logic specific to
record updates.
● Trigger.isDelete
○ Returns true if the trigger was fired due to a DELETE
operation. This is useful for actions that should occur
when records are deleted.

kshitijdhoble
Trigger Context Variables
● Trigger.isUndelete
○ Returns true if the trigger was fired due to an
UNDELETE operation. This is specifically used for
actions that should occur when records are restored
from the Recycle Bin.
● Trigger.isBefore
○ Returns true if the trigger was fired before any records
were saved to the database (i.e., BEFORE triggers). Use
this for validations or modifications to the records
before they are committed to the database.
● Trigger.isAfter
○ Returns true if the trigger was fired after the records
were saved to the database (i.e., AFTER triggers).
Typically used for actions that require the record to be
already committed.

kshitijdhoble
Trigger Context Variables
● Trigger.operationType
○ Returns the specific type of DML operation that caused
the trigger to fire. It can return values like insert,
update, delete, undelete.
● Trigger.size
○ Trigger.size returns the total number of records that
are part of the trigger invocation.
○ It is particularly useful when you want to check how
many records are being processed within a single
trigger context.

kshitijdhoble
Bulkifying Triggers
● A bulkified trigger is written to handle a large number of
records efficiently, rather than processing one record at a
time.

● The trigger is written in bulk design pattern which can


improve performance and reduce server side resource
consumption.

● This approach is crucial because Salesforce processes


triggers in bulk when multiple records are inserted,
updated, deleted, or undeleted in a single transaction.

kshitijdhoble
Why Bulkify Triggers?
● Avoid Hitting Governor Limits: Salesforce imposes limits
on the number of records processed and the number of
SOQL queries, DML operations, etc., per transaction.
Bulkified triggers help ensure that your code does not
exceed these limits.

● Improved Performance: Bulk processing is more efficient


and reduces the risk of hitting limits, leading to better
performance.

● Data Integrity: Ensures that all records are processed


consistently, maintaining data integrity.

kshitijdhoble
Why Bulkify Triggers?
● Non-bulkified triggers may work for small volume of data,
but it has some drawbacks.

○ It may hit SOQL query limit, if query is inside the loop.


This will occur when there are many records.

○ It may hit DML statement limit if DML is inside loop.

○ This may consume more resources and take longer to


execute (hitting governor limits).

kshitijdhoble
Trigger Helper Class
● Trigger Helper Class Design Pattern is the best practice
used when writing triggers. Using this pattern helps in
keeping trigger logic modular, reusable and maintainable.

● The helper class contains logic of trigger, this practice


separates logic from trigger. Therefore, in trigger, we just
need to call the logics/methods defined in helper class

● This helps in reusing the helper class for multiple triggers.

● This can be maintained easily without affecting the


triggers and reduce risk of bugs.

● We can test the program and can do unit testing


efficiently.
kshitijdhoble
Trigger Helper Class
● Example:
// Trigger: AccountTrigger
trigger AccountTrigger on Account (before insert){
if (Trigger.isBefore && Trigger.isInsert) {
TriggerHandler.handleInsert(Trigger.new);
}
}
// Helper Class
public class TriggerHandler {
public static void handleInsert(List<Account> newAcc){
for (Account acc : newAccounts) {
acc.Description = 'New Account';
}
}
}
kshitijdhoble
Trigger Helper Class
● Explanation:

● Trigger Logic: The trigger AccountTrigger checks if the


trigger event is before insert and then delegates the
processing to the AccountTriggerHandler class.

● Helper Class Logic: The AccountTriggerHandler class


contains a static method handleInsert that handles the
business logic. It updates the Description field for all
Account records in the Trigger.new list.

kshitijdhoble
Recursion in Triggers
● A trigger directly invokes itself. For example, if a trigger
performs a DML operation that causes the same trigger to
fire again, it results in direct recursion.

● This occurs when Trigger A causes a DML operation that


fires Trigger B, which in turn causes a DML operation that
fires Trigger A again.

● Recursion can quickly consume Salesforce governor limits


like CPU time, DML operations, and SOQL queries.

● Repeated execution can degrade performance and slow


down processing.

● Recursive triggers can lead to unexpected or inconsistent


data changes.
kshitijdhoble
Prevent Recursion
● Use Static Variables: To prevent recursion, use static
variables to track whether the trigger logic is already being
processed.
● Check Trigger Context: Ensure that your trigger logic is
designed to handle specific contexts and avoid
unnecessary DML operations.
● Avoid Complex Trigger Logic: Break down complex
trigger logic into smaller, manageable parts and use
helper classes to minimize the risk of recursion.
● Control DML Operations: Ensure that DML operations are
not inadvertently causing recursive trigger firing. Group
related updates into a single operation where possible.
● Use Custom Flags: Implement custom flags or fields on
the object to manage recursion and prevent repeated
processing.
kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 12
Governor Limits
in

Apex
kshitijdhoble
Governor Limits
● Governor limits are runtime limits enforced by Salesforce
to regulate the consumption of resources.
● These limits apply to Apex code execution, making sure
that a single transaction does not consume excessive
resources, which could impact the performance of the
entire Salesforce instance.
● These are some set of rules that restrict the use of cloud
resources by organizations that use Salesforce servers.
● These limits are enforced by the Apex runtime engine to
ensure that one client or process does not monopolize
shared resources on the Salesforce platform.
kshitijdhoble
Why Governor Limits Exists?
● Salesforce is a multi-tenant environment, meaning
multiple customers share the same underlying
infrastructure.
● To ensure fair usage and to prevent any single customer
from consuming too many resources (which could
degrade the performance for others), Salesforce enforces
governor limits. These limits help in:
○ Ensuring the stability and performance of the
Salesforce environment.
○ Preventing infinite loops or resource-heavy operations
from crashing the system.
○ Encouraging developers to write efficient, scalable
code.
kshitijdhoble
Types of Governor Limits
● Major Governor Limits:
○ Total number of SOSL queries issued in Salesforce: 20
○ DML Governor Limits in Salesforce (Total number of
statements issued per transaction): 150
○ Total number of records retrieved by a single SOSL
query: 2000
○ Total number of records retrieved by SOQL queries:
50000
○ Total number of records retrieved by
Database.getQueryLocator: 10000
○ Salesforce Governor Limits for heap size total: 6 MB
Synchronous, 12 MB Asynchronous

kshitijdhoble
Types of Governor Limits
● Per-transaction Certified Managed Package Limits:
○ The total number of SOQL queries issued: 1100
○ The total number of records retrieved by
Database.getQueryLocator: 110000
○ The total number of SOSL queries issued: 220
○ The total number of DML statements issued: 1650
○ The total number of callouts (either HTTP requests or
Web services calls) in a transaction: 1100
○ The total number of sendEmail methods allowed: 110

kshitijdhoble
Types of Governor Limits
● Static Apex Limits:
○ Default timeout of callouts (HTTP requests/Web
services calls) in a transaction: 10 seconds
○ Maximum size of the callout request or response : 6 MB
for synchronous,12 MB for asynchronous.
○ Maximum SOQL query runtime before Salesforce
cancels the transaction: 120 seconds
○ Maximum number of class and trigger code units in
the deployment of Apex: 5,000
○ Apex trigger batch size: 200
○ For loop list batch size: 200
○ Maximum number of records that are returned for a
Batch Apex query in Database.QueryLocator: 50 million

kshitijdhoble
Types of Governor Limits
● Per-transaction Apex Limits:
○ The total number of SOQL queries issued: 100
synchronous, 200 asynchronous
○ Number of records retrieved by SOQL queries: 50,000
○ Number of records retrieved by
Database.getQueryLocator: 10000
○ The total number of SOSL queries issued: 20
○ The total number of records retrieved by a single SOSL
query: 20000
○ The total number of DML statements issued: 150
○ Number of records processed as a result of DML
statements, Approval.process, or
database.emptyRecycleBin: 10000

kshitijdhoble
Types of Governor Limits
○ The total stack depth for any Apex invocation that
recursively fires triggers with insert, update, or delete
statements:16
○ The total number of callouts (either HTTP requests or
Web services calls) in a transaction: 100
○ The maximum cumulative timeout for all callouts
(either HTTP requests or Web services calls) in a
transaction: 120 seconds
○ The maximum number of methods with the future
annotation allowed per Apex invocation : 50 in
synchronous, 0 in batch and future contexts and 1 in
the queueable context

kshitijdhoble
Types of Governor Limits
○ The total number of sendEmail methods allowed: 10
○ The total heap size: 6 MB synchronous, 12 MB
asynchronous
○ The maximum CPU time on Salesforce servers: 10,000
milliseconds in synchronous, 60,000 milliseconds in
asynchronous
○ The maximum execution time for each Apex
transaction: 10 minutes
○ The maximum number of push notification method
calls allowed per Apex transaction: 10
○ The maximum number of push notifications that can
be sent through each push notification method call:
2000

kshitijdhoble
Types of Governor Limits
● Lightning Platform Apex Limits:
○ The maximum number of asynchronous Apex method
executions (Batch Apex, future methods, Queueable
Apex, and Scheduled Apex) per 24-hour period: Either
250,000 or the number of user licenses in the org
multiplied by 200, whichever is greater
○ The number of synchronous concurrent transactions
for long-running transactions, which last longer than 5
seconds for each org.: 10
○ The maximum number of Apex classes scheduled
concurrently: 100 In Developer Edition org, the limit is 5
○ The maximum number of Batch Apex jobs in the Apex
flex queue that is in the Holding status: 100

kshitijdhoble
Types of Governor Limits
○ The maximum number of Batch Apex jobs queued or
active concurrently: 5
○ The maximum number of Batch Apex job start
method concurrent executions: 1
○ The maximum number of batch jobs that can be
submitted in a running test:5
○ The maximum number of test classes that can be
queued in a 24-hour period (in Production org other
than Developer Edition): Either 500 or 10 multiplied
by the number of test classes in the org, whichever is
greater
kshitijdhoble
Types of Governor Limits
○ 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 Batch Apex execute and finish methods: 5

kshitijdhoble
Types of Governor Limits
● Specific Apex Limits:
○ Maximum number of characters in a class: 1 million
○ Maximum number of characters in a trigger: 1 million
○ Maximum amount of code used by all Apex codes in
org: 6 MB
○ The method size limit: 65,535 bytecode instructions in a
compiled form

kshitijdhoble
Monitoring Governor Limits
● Monitoring governor limits in Apex is crucial for ensuring
that our code adheres to Salesforce's execution constraints,
preventing runtime exceptions and improving
performance.

● Here's how we can monitor and manage governor limits:


1. Using Limits Class:
○ This class in Apex provides methods to check the
current consumption of various governor limits during
execution.
○ We can use these methods to monitor limits like CPU
time, queries, DML statements, etc.

kshitijdhoble
Monitoring Governor Limits
● Common methods of Limits Class:
○ SOQL Queries:
■ Limits.getQueries(): Returns the number of SOQL
queries executed.
■ Limits.getLimitQueries(): Returns the maximum
number of SOQL queries allowed (100 in a
synchronous, 200 in an asynchronous).
○ DML Statements:
■ Limits.getDMLStatements(): Returns the number
of DML statements executed.
■ Limits.getLimitDMLStatements(): Returns the
maximum number of DML statements allowed
(150 in a synchronous context, 150 in an
asynchronous context).
kshitijdhoble
Monitoring Governor Limits
○ CPU Time:
■ Limits.getCpuTime(): Returns the CPU time (in
milliseconds) consumed.
■ Limits.getLimitCpuTime(): Returns the maximum
CPU time allowed (10,000 ms).
○ Heap Size:
■ Limits.getHeapSize(): Returns the amount of heap
memory used.
■ Limits.getLimitHeapSize(): Returns the maximum
heap size allowed (6 MB for synchronous
transactions, 12 MB for asynchronous transactions).

kshitijdhoble
Monitoring Governor Limits
2. Using Apex Debug Logs:

○ Apex Debug Logs can be used to monitor governor


limits in real-time as your code executes.

○ By setting debug log levels, we can see detailed


information about limit usage in the log files.

○ When we execute Apex code, Salesforce logs


information about the usage of governor limits, such
as the number of SOQL queries, DML statements, CPU
time, and heap size.

○ These details are automatically recorded in the debug


logs, allowing you to track the consumption of these
resources in real time.
kshitijdhoble
Best Practices
● Developers can avoid hitting governor limits by
following best practices:
● Always process records in bulk to minimize the number of
DML statements and SOQL queries.
● Optimize SOQL queries to retrieve only the data you need.
● Offload heavy processing to asynchronous methods like
future methods, Batch Apex or Queueable Apex to avoid
hitting limits in synchronous transactions.
● Test methods have their own governor limits, which are
stricter than production code. This ensures that your code
is efficient and scalable.
● Instead of multiple DML operations, developers should use
collections to store and process records in bulk.
kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 13
Asynchronous Apex -
Batchable Interface in

Apex
kshitijdhoble
Asynchronous Apex
● Asynchronous Apex refers to processes that run in the
background, separate from the main thread, allowing
operations to continue without waiting for the process to
complete.

● Because it runs on a separate thread, asynchronous Apex


does not require the user to wait for the operation to
complete.

● The UI remains responsive, and users can continue


interacting with the system while the process is still
running.
kshitijdhoble
Why Asynchronous Apex?
● Here’s why we need to use Asynchronous Apex:
1. Handling Long-Running Operations:

■ Asynchronous Apex is ideal for tasks that may take


a long time to complete, such as processing large
datasets, integrating with external systems, or
performing complex calculations.

■ Running these operations asynchronously ensures


that the user interface (UI) remains responsive and
that users can continue their work without
interruption.
kshitijdhoble
Why Asynchronous Apex?
2. Managing System Limits:

■ Salesforce has various limits on CPU time, memory,


and database operations for synchronous
transactions.

■ Asynchronous Apex allows you to bypass some of


these limits by processing data in smaller chunks
over time.

■ This is particularly useful in batch processing


scenarios where large volumes of data need to be
handled efficiently.
kshitijdhoble
Why Asynchronous Apex?
3. Offloading Resource-Intensive Tasks:

■ Certain tasks, like sending emails, generating


reports, or updating many related records, can
consume significant system resources.

■ By using Asynchronous Apex, you can offload


these tasks to run in the background, freeing up
resources for more critical, real-time operations.

kshitijdhoble
Why Asynchronous Apex?
4. Improving User Experience:

■ Since asynchronous processes run independently


of the main thread, users don’t have to wait for
these operations to finish before continuing their
work.

■ This leads to a smoother and more responsive user


experience, as the UI is not blocked by background
tasks.

kshitijdhoble
Why Asynchronous Apex?
5. Scalable Processing:

■ Asynchronous Apex allows you to scale processing


by distributing tasks across multiple threads.

■ This is beneficial when working with large datasets


or when you need to perform multiple complex
operations simultaneously.

kshitijdhoble
Why Asynchronous Apex?
6. Handling External Integrations:

■ When integrating with external systems, response


times can be unpredictable.

■ Asynchronous Apex enables you to handle these


integrations without making the user wait, as the
process can complete in the background and
update the records later.

kshitijdhoble
Types of Asynchronous Apex
● Batch Apex: Use for processing large volumes of records,
such as updating all contacts in an organization or
recalculating all opportunities.

● Future Methods: Use for tasks that don’t need to be


completed immediately, like sending follow-up emails
after a transaction.

● Queueable Apex: Use for chaining jobs or when you need


more control over job execution order and process
management.

● Scheduled Apex: Use for operations that need to run at


specific intervals, like daily or weekly data cleanup tasks.

kshitijdhoble
What is Batch Apex?
● Batch Apex is a powerful feature in Salesforce that allows
you to process large volumes of data in smaller,
manageable chunks.

● It is particularly useful when you need to perform


operations on thousands or even millions of records
without hitting governor limits that are typically enforced
in Salesforce for synchronous transactions.

● Batch Apex breaks down large jobs into smaller batches,


each of which is processed separately.

● This approach helps in efficiently managing system


resources and avoiding timeouts or limits that could occur
if the entire operation were processed at once.

kshitijdhoble
Origin of Batch Apex
● Batch Apex was introduced by Salesforce as part of its
asynchronous processing capabilities to handle scenarios
where operations on large datasets are required.

● It is a built-in Apex class Database.Batchable that


developers can implement to perform large-scale data
processing in a scalable and efficient manner.

● Database.Batchable is an interface that allows users to


process large amounts of data by dividing it into
manageable batches and executing each batch separately.

kshitijdhoble
How Batch Apex Works?
● Batch Apex is implemented by writing a class that
implements the Database.Batchable interface. This
interface requires the implementation of 3 methods:
○ Start( ): The start method is used to collect the records
or data you want to process. It returns an Iterable or
Database.QueryLocator that Batch Apex will use to
retrieve the records in chunks.
○ Execute( ): The execute method is where the actual
processing of data happens. It takes in a context and a
list of records (or a scope) to process in each batch.
○ Finish( ): The finish method is executed after all
batches have been processed. It can be used for any
post-processing logic, such as sending a notification or
triggering another batch process.
kshitijdhoble
How Batch Apex Works?
● Why Batch Class is Global?

○ The global keyword makes the batch class accessible


across the entire Salesforce organization, including
other packages. This is necessary because batch jobs
are often scheduled or invoked from various contexts,
so the class must be globally accessible.

● What is Database.Batchable<SObject>

○ This is an interface provided by Salesforce that you


implement to define a batch job. SObject is a generic
type representing any Salesforce object. Implementing
Database.Batchable<SObject> allows the class to
process large datasets asynchronously in batches.

kshitijdhoble
How Batch Apex Works?
● What is Database.QueryLocator

○ It’s an object that holds a reference to the results of a


SOQL query. It allows Salesforce to fetch records in
smaller, manageable chunks (batches), making it ideal
for processing large volumes of data without hitting
governor limits.

● What is Database.BatchableContext

○ It’s an interface provided by Salesforce that passes


context information about the batch job to the start,
execute, and finish methods. It provides details like job
IDs and allows for the tracking and management of
the batch job's state.

kshitijdhoble
How Batch Apex Works?
● What is Database.getQueryLocator

○ It’s a method that takes a SOQL query string as input


and returns a Database.QueryLocator object. This
object can then be used to fetch records in batches,
enabling the batch job to process large datasets
efficiently..

kshitijdhoble
How Batch Apex Works?
● Example: Updating the status of all active accounts.
global class UpdateStatusBatch implements Database.Batchable<sObject>{
global Database.QueryLocator start(Database.BatchableContext BC){
String query = ‘SELECT Id, Name
FROM Account WHERE Status__c = \’Active\’’;
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Account> sc){
for(Account acc : sc){
acc.Status__c = ‘Inactive’;
} update scope;
}
global void finish((Database.BatchableContext BC){
// finishing tasks like sending success mails
}
} kshitijdhoble
Key Features of Batch Apex
● Batch Size: The default batch size is 200 records, but you
can specify a different batch size (between 1 and 2,000)
when invoking the batch.

● Governor Limits: Each execution of the execute method


runs in its own transaction, allowing you to work with
larger datasets without hitting governor limits.

● Asynchronous Execution: Batch Apex runs


asynchronously, meaning it does not block the user
interface and allows the platform to manage resource
usage efficiently.

● Stateful Batch Apex: By implementing the


Database.Stateful interface, you can maintain state across
batch transactions, allowing you to keep track of data or
aggregate results.
kshitijdhoble
Best Practices
● Bulkify Code: Ensure that your code within the execute
method is bulkified to handle large datasets efficiently.

● Error Handling: Implement robust error handling within


the execute method to manage any exceptions and ensure
the batch can continue processing other records.

● Monitor and Log: Use the finish method to log the results
of the batch job or send notifications to monitor the
success or failure of the job.

● Use Limits Wisely: Be mindful of limits like the total


number of batch jobs that can be run concurrently and the
maximum number of records processed by batch jobs.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 14
Schedulable Interface
in

Apex
kshitijdhoble
What is Scheduled Apex?
● Scheduled Apex is a feature in Salesforce that allows you
to execute Apex classes at specified times.

● This is particularly useful for automating repetitive tasks


that need to run on a regular schedule, such as nightly
data processing, periodic cleanup jobs, or sending out
reminders.

● When we schedule an Apex class, Salesforce's scheduler


executes it at the specified time. The class runs
asynchronously, meaning it does not interfere with the
user experience or other processes.

● We can schedule Apex to run once or at recurring intervals,


such as daily, weekly, or monthly.

kshitijdhoble
Origin of Scheduled Apex
● Scheduled Apex is another feature provided by Salesforce
as part of its asynchronous processing capabilities,
allowing developers to automate the execution of Apex
code at specific times or intervals.
● This is particularly useful for tasks that need to be run
regularly, such as nightly data processing, sending periodic
emails, or performing maintenance activities.
● In Scheduled Apex, developers implement the
Schedulable interface, which provides a method called
execute that contains the logic to be run.
● Once the Apex class is written, it can be scheduled to run
at a specified time using the System.schedule( ) method
or through the Salesforce user interface.
kshitijdhoble
Origin of Scheduled Apex
● The Schedulable interface makes it possible to trigger
Apex code according to a defined schedule, allowing for
greater automation and better resource management.

● For instance, you can schedule a Batch Apex job to run


every night at midnight, ensuring that large data
processing tasks do not interfere with day-to-day
operations.

● A class that implements the Schedulable interface must


include a execute( ) method, which is the entry point for
the scheduled execution.

kshitijdhoble
How Scheduled Apex Works?
● Here's a step-by-step breakdown of how it works:
1. Implementing the Schedulable Interface:
○ To create a class that can be scheduled, the class must
implement the Schedulable interface.
○ This interface requires you to define an execute
method that contains the code you want to run when
the job is triggered.
2. Scheduling a Job:
○ There are several ways to schedule an Apex job,
depending on the requirements and complexity.

Contd…

kshitijdhoble
How Scheduled Apex Works?
A. Using the Salesforce UI (Setup Menu): Steps to follow
○ Setup > Apex Classes > Schedule Apex > Select Class
○ Specify the frequency (daily, weekly, etc.), start date,
and preferred time. Then Save.

kshitijdhoble
How Scheduled Apex Works?
B. Using Corn Expressions (Programmatic Approach):

○ A cron expression is a string that specifies the exact


time, date, and frequency at which a job should
execute.

○ It provides flexibility to schedule jobs at various


intervals, such as daily, weekly, monthly, or even at
specific minutes of an hour. For a job to run every day
at 2:30 AM, the cron expression would be: "0 30 2 * * ?"

kshitijdhoble
How Scheduled Apex Works?
C. Using System.schedule( ) method:
○ The System.schedule() method is used to schedule a
class that implements the Schedulable interface.
○ This method allows us to specify a cron expression to
determine when the job should run.
○ We can schedule an Apex job directly from the
Developer Console by executing anonymous Apex
code.
D. Using scheduleJob( ) method:
○ When we want to schedule a job programmatically
from another class, we can use the ScheduleJob()
method, which internally uses the System.schedule
method.
kshitijdhoble
How Scheduled Apex Works?
3. Executing the Scheduled Job:
○ When the scheduled time arrives, Salesforce
automatically invokes the execute method of the
scheduled class. The code within this method runs
with the privileges of the user who scheduled the job.
○ If the scheduled class includes batch processing or
another scheduled job, those processes will be kicked
off as well.
4. Monitoring and Managing Scheduled Jobs:
○ We can monitor and manage your scheduled jobs in
Salesforce.
○ This includes checking the status, aborting jobs, and
even rescheduling them if necessary.

kshitijdhoble
How Scheduled Apex Works?
● What is SchedulableContext?
○ The SchedulableContext interface provides methods to
interact with the scheduled job when the execute
method of a Schedulable class runs. It allows you to
track information about the job execution and its
context.
○ SchedulableContext.getJobId( ) method Returns the
ID of the scheduled job, which can be used to track or
abort the job if needed.
● What is scheduleJob( ) method?
○ The scheduleJob method in the context provided is a
custom method that encapsulates the logic for
scheduling an Apex class to run at a specific time using
System.schedule( ) method.
kshitijdhoble
How Scheduled Apex Works?
● What is System.schedule( )?
○ The System.schedule method is used to schedule an
Apex class that implements the Schedulable interface
to run at a specific time in the future or on a recurring
basis.
○ Parameters:
■ jobName: A string that names the scheduled job
(e.g., "Daily Update Status Job").
■ cronExpression: A string that defines the schedule
using a cron expression.
■ schedulableClass: An instance of the class
implementing the Schedulable interface that you
want to run.
kshitijdhoble
How Scheduled Apex Works?
● What is a Corn Expression?

○ A Cron Expression is a string representing a schedule


that defines the specific times at which a scheduled
job should run.

○ In Salesforce, cron expressions are used with the


System.schedule method to set up scheduled Apex
jobs.

○ A cron expression consists of six or seven fields


separated by spaces, each representing a specific
aspect of the time and date.

kshitijdhoble
How Scheduled Apex Works?
● Structure of Corn Expression?

○ A standard cron expression in Salesforce has the


following serial wise format:

<sec> <mins> <hrs> <day-of-month> <month> <day-of-week> <year>

Field Breakdown:
<sec>: Seconds (0-59), <mins>: Minutes (0-59)
<hrs>: Hours (0-23), <day-of-month>: Day of the month (1-31)
<month>: Month (1-12 or JAN-DEC)
<day-of-week>: Day of the week (1-7 or SUN-SAT).
<year>: Optional Year (e.g., 2024)

kshitijdhoble
How Scheduled Apex Works?
● Example: Scheduling the batch for 2 AM everyday.
// implementing Scheculabe interface
global class ScheduleUpdateStatus implements Schedulable {
global void execute(SchedulableContext SC) {
// calling batch class (previous example in batch class)
UpdateStatusBatch batchJob = new UpdateStatusBatch();
Database.executeBatch(batchJob);
}
public static void scheduleJob() { // using scheduleJob() method
// Define the cron expression (every day at 2 AM)
String cronExp = '0 0 2 * * ?';
// scheduling job using System.schedule() method
System.schedule('Daily Update Status Job', cronExp,
new ScheduleUpdateStatus());
}
} kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 15
Future Method
in

Apex
kshitijdhoble
What is a Future Method ?
● A Future Method is an asynchronous process in Apex that

allows you to run a piece of code in the background,

typically after the main execution thread has completed.

● This is particularly useful for long-running operations that

don't need to be executed immediately, freeing up

resources and improving the performance of the main

transaction.

kshitijdhoble
Why We Use Future Method ?
Future methods are used in scenarios where we need to:

● Perform operations that are resource-intensive or


time-consuming.

● Make callouts to external web services after the main


transaction completes (since callouts are not allowed in
the main execution thread if the request is synchronous).

● Handle operations that do not require immediate


processing and can be deferred until system resources are
available.

kshitijdhoble
Key Features
● Asynchronous Execution: Future methods run in the
background, allowing the main thread to continue
processing without waiting for the future method to
complete.

● Governor Limits: Future methods have their own set of


governor limits, which are higher than synchronous Apex.
This allows for more CPU time and database queries.

● @future Annotation: Future methods are defined using


the @future annotation, which indicates that the method
should be executed asynchronously.
kshitijdhoble
Syntax & Structure
● Future methods in Apex are defined using the @future
annotation. Here’s the basic syntax and structure:
@future(callout = false)
public static void methodName(Type1 param1,
Type2 param2, ...) {
// Your asynchronous code here
}
● Breakdown of the Syntax:
● @future: This annotation tells the Apex runtime that the
method is to be run asynchronously.
● callout = true/false: Indicates whether the future method
will make an external HTTP callout or not.

kshitijdhoble
Syntax & Structure
● public: The method must be public so that it can be
accessed from other classes or triggers.
● static: The method must be static because it does not
depend on an instance of the class.
● void: Future methods cannot return a value, hence the
return type is void.
● Type1 param1, Type2 param2, ...: The method parameters.
These must be primitive data types, collections of
primitives, or sObject IDs. Future methods don’t accept
sObjects or complex data types as parameters.
● The body of the method contains the code that will be
executed asynchronously.
kshitijdhoble
Example
● Scenario: To send a welcome email asynchronously
when a new customer record is created
// Step 1: Creating the Future Method
public class CustomerService {
@future
public static void sendWelcomeEmail(Id customerId) {
// Fetch the customer record
Customer__c customer = [SELECT Name, Email__c
FROM Customer__c
WHERE Id = :customerId];

// Code for creating an email message


// Code for sending the email
}
}
kshitijdhoble
Example
// Step 2: Trigger the Future Method
trigger CustomerTrigger on Customer__c (after insert) {
for (Customer__c customer : Trigger.new) {
// Calling the future method
CustomerService.sendWelcomeEmail(customer.Id);
}
}
// How it works:
● When a new customer record is created, the
CustomerTrigger gets fired.
● The CustomerTrigger then calls the sendWelcomeEmail
future method.
● The future method runs in the background and sends
the welcome email without delaying the customer
record creation process.

kshitijdhoble
Use Cases
● Making Callouts: Future methods are often used when
making callouts to external web services, especially when
the callout needs to happen after some database
operations have completed.

● Deferred Processing: When you have operations that can


be deferred, such as complex calculations or bulk
processing that doesn’t need to be immediate, future
methods can be used to handle these operations in the
background.

kshitijdhoble
Key Points to Remember
● Future methods must be static. This is because they are
executed in a separate thread from the initiating code, so
they must not depend on instance-specific data.
● Future methods do not return any value. This is because
they are executed asynchronously and the result is not
available to the calling method.
● Future methods have higher limits than synchronous
methods. For example, we can perform up to 200 SOQL
queries or DML statements in a future method, compared
to 100 in synchronous.
● We cannot call a future method from another future
method. However, we can use Queueable Apex if you need
to chain asynchronous operations.

kshitijdhoble
Limitations
● Limited to One: You can only have one future method in a
single transaction.

● Order of Execution: Future methods do not guarantee the


order of execution. If you have multiple future methods,
they might not execute in the order they were called.

● No Chaining of Future Methods: As mentioned earlier,


you cannot call one future method from another future
method. If you need to chain operations, you should use
Queueable Apex.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 16
Queueable Interface
in

Apex
kshitijdhoble
What is Queueable Apex?
● Queueable Apex is another powerful feature in Salesforce
designed to handle asynchronous processing, similar to
Batch Apex but with some differences in functionality and
use cases.

● Queueable Apex allows us to add jobs to a queue that will


be processed asynchronously.

● This means that we can perform complex operations


without waiting for the job to complete, improving the
efficiency and responsiveness of your system.

kshitijdhoble
Origin of Queueable Apex
● Queueable Apex was introduced by Salesforce to offer a
flexible and easier alternative to traditional asynchronous
processing methods like future methods.

● It allows developers to run background processes with


complex logic and chain jobs sequentially.

● Queueable Apex is implemented by the Queueable


interface, providing additional capabilities over future
methods, such as monitoring jobs and passing complex
data types.

● It enables more control over job execution and is


particularly useful for scenarios that require both future
method functionality and the ability to chain jobs for
further processing.
kshitijdhoble
How Queueable Apex Works?
● Queueable Apex is implemented by writing a class that
implements the Queueable interface. This interface
requires the implementation of one method:

● execute(QueueableContext context):

○ The execute( ) method contains the logic that we


want to run asynchronously. It takes in a
QueueableContext object, which provides methods to
manage the job, such as retrieving the job ID.

● We can chain jobs by adding a new instance of the class to


the queue from within the execute method. This approach
is useful for complex processes that need to be broken into
smaller tasks.

kshitijdhoble
How Queueable Apex Works?
● Example: Updating the contact records with a specific
value for a custom field
// implementing queueable interface
public class UpdateContactsQueueable implements Queueable {
public void execute(QueueableContext context) {
// Query contacts to be updated
List<Contact> contactsToUpdate = [SELECT Id, Custom_Field__c
FROM Contact WHERE Custom_Field__c = NULL LIMIT 100];
for(Contact con : contactsToUpdate) { // updating custom field
con.Custom_Field__c = 'Updated Value';
}
// Perform the DML operation to update the records
if(!contactsToUpdate.isEmpty()) {
update contactsToUpdate;
}
} kshitijdhoble
}
How Queueable Apex Works?
● Enqueuing the job:

// Enqueue the job to run asynchronously


ID jobId = System.enqueueJob(new UpdateContactsQueueable());

● In this example, the UpdateContactsQueueable class


queries for contact records that have a Custom_Field__c
value of NULL, updates that field, and then performs the
update operation. The job is enqueued to run
asynchronously with System.enqueueJob.

kshitijdhoble
Key Features
● Asynchronous Execution: Queueable Apex allows us to
execute code asynchronously, meaning it runs in the
background without blocking the main transaction.

● Chaining Jobs: We can chain jobs by enqueuing a new job


from within the execute method. This is useful for breaking
down complex tasks into smaller, sequential jobs.

● More Complex Data Types: Unlike @future methods,


Queueable Apex allows us to pass more complex data
types, such as sObjects or collections, to the job.

kshitijdhoble
Key Features
● Job Monitoring: Queueable jobs can be monitored
through the Salesforce UI, where us can track the status
and progress of the queued jobs.
● Finer Control Over Execution: The QueueableContext
object provides methods to retrieve the job ID and
manage the job, offering finer control over the job's
execution compared to @future methods.
● Limits: Queueable Apex has higher governor limits
compared to synchronous code, similar to Batch Apex,
making it suitable for handling large data volumes.
However, it still has some limitations, such as a limit of 50
jobs that can be added to the queue per transaction.

kshitijdhoble
Use Cases
● Complex Calculations: When you need to perform long or
complex calculations without blocking other operations.
● Data Transformation: Converting or updating large
amounts of data in the background.
● External API Calls: Calling external web services or APIs
that may take time.
● Chaining Jobs: Running multiple jobs in sequence where
each job depends on the previous one.
● Handling Large Data Volumes: Processing large data sets
efficiently by breaking them into manageable pieces.
● Delayed Processing: Performing tasks that don’t need to
happen immediately but should be done asynchronously.
● Background Processing: Running tasks that don’t need to
be completed within same transaction as the user request.
Best Practices
● Use for Asynchronous Processing: Queueable Apex is
ideal for long-running or resource-intensive operations
that need to be processed in the background.
● Chain Jobs Carefully: You can chain Queueable jobs, but
avoid creating too many chained jobs to prevent hitting
governor limits.
● Limit Chaining Depth: Salesforce limits the depth of job
chaining. Keep it shallow to avoid hitting limits.
● Handle Exceptions: Implement proper exception handling
within the execute method to ensure that errors are
managed gracefully.

kshitijdhoble
Best Practices
● Optimize Resources: Avoid complex queries and
operations within execute to keep resource usage efficient.
● Test Thoroughly: Write test classes to cover your
Queueable Apex. Ensure that tests cover job execution and
handle possible exceptions.
● Consider Limits: Be mindful of Salesforce governor limits,
such as the maximum number of jobs in the queue and
the maximum execution time.
● Use Synchronous Jobs Sparingly: For short tasks or jobs
that must run immediately, consider using synchronous
methods like future methods or Batch Apex.

kshitijdhoble
Thank-You!
Stay Tuned & Follow

kshitijdhoble
Day 17
Apex Testing
in

Apex
kshitijdhoble
Apex Testing
● Apex testing involves writing and running unit tests to
ensure that the code behaves as expected.

● It’s crucial in Salesforce development as it ensures the


reliability and stability of production code.

● Salesforce requires at least 75% of our Apex code to be


covered by unit tests before us can deploy it to a
production environment.

● These tests are crucial for maintaining code quality and for
preventing future changes from breaking existing
functionality.
kshitijdhoble
Apex Testing
● The primary goal of writing Apex test code is to validate
that the production Apex classes and triggers behave as
expected under various conditions.

● By simulating real-world scenarios within a controlled


environment, test methods help identify and fix bugs
before deploying changes to production.

kshitijdhoble
Purpose of Apex Testing
● Apex tests are written in special test classes, which contain
methods that validate the logic in our Apex classes and
triggers.
● These tests simulate the execution of code in a controlled
environment, allowing us to check the expected outcomes
against actual results.
● The primary purpose of testing in Apex is to:
○ Ensures Code Quality: Testing helps in identifying
bugs or issues before they reach production.
○ Regression Testing: Automated tests ensure that new
changes don’t break existing functionality.

kshitijdhoble
Purpose of Apex Testing
○ Required by Salesforce: Salesforce mandates a
minimum of 75% code coverage for deployment to
production. This means that our test cases must cover
at least 75% of our Apex code.
○ Continuous Integration (CI): Tests are crucial for CI
pipelines, ensuring that code integrates smoothly.

kshitijdhoble
Key Concepts in Apex Testing
● Test Coverage:
○ Refers to the percentage of our code that is executed
during testing.
○ Higher coverage usually indicates more thorough
testing, but 100% coverage doesn't always mean that
all potential issues are addressed.
● Isolation:
○ Each test should be independent and should not affect
the results of other tests.
○ Salesforce provides a clean environment for each test
method, ensuring data created or modified during one
test doesn’t affect others.

kshitijdhoble
Key Concepts in Apex Testing
● Best Practices:

○ Writing meaningful tests that simulate real-world


scenarios, including edge cases, is crucial.

○ Also, make sure to test both positive and negative


scenarios.

kshitijdhoble
Code Coverage Considerations
● Positive Testing:

○ Positive tests ensure that our code works as expected


when given valid input and under normal conditions.

● Negative Testing:

○ Negative tests check how our code handles invalid


input, exceptions, or edge cases.

○ These tests are crucial for ensuring that our code fails
gracefully and does not break under unexpected
conditions.

kshitijdhoble
Code Coverage Considerations
● Edge Case Testing:

○ Edge cases are scenarios that occur at the extreme


ends of input ranges.

○ Testing edge cases ensures our code can handle


unusual or boundary conditions effectively.

● Bulk Testing:

○ Bulk testing simulates scenarios where the code must


handle large volumes of data, ensuring that it remains
efficient and within Salesforce's governor limits.

kshitijdhoble
Code Coverage Considerations
● Testing All Possible Branches:

○ Tests should cover all possible paths through our code,


including all if, else, switch, and loop statements.

○ This ensures that every logical branch has been tested.

kshitijdhoble
Apex Testing Framework
● The Apex testing framework is an integral part of the
Salesforce platform, allowing developers to write and
execute unit tests to ensure the reliability and performance
of their Apex code.

● This framework supports the Test-Driven Development


(TDD) methodology, where tests are written before the
actual code, ensuring that the code is robust and behaves
as expected.

kshitijdhoble
Key Components
a. Test Classes and Methods:
○ Test Class: A class in which us write test methods. It is
annotated with @isTest.
○ Test Method: A method inside a test class that is
responsible for testing a specific piece of functionality.
It is annotated with @isTest or the testMethod
keyword.
// Example
@isTest
public class MyApexTestClass {
@isTest
static void myTestMethod() {
// Test logic here
}
}
kshitijdhoble
Key Components
b. Test Data:
○ Test Data Creation: Salesforce recommends creating
test data within our test methods rather than relying
on existing data in the organization.
○ Test.loadData: Allows loading static test data from a
CSV file.
○ TestSetup Method: A method annotated with
@TestSetup is used to create common test data that
can be shared across multiple test methods in a class.
// Example
@TestSetup
static void setup() {
// Create common test data
}
kshitijdhoble
Key Components
c. Isolation of Test Context:
○ Governor Limits: Test methods have their own set of
governor limits, ensuring that tests do not interfere
with each other.
○ Test.startTest & Test.stopTest: These methods are
used to test asynchronous methods by resetting the
governor limits within a test.
// Example
Test.startTest();
// Execute code to test
Test.stopTest();

kshitijdhoble
Various Annotations & Methods
● In Apex, testing involves writing test classes and methods,
using specific annotations and methods to simulate
different scenarios.

● Here are some common annotations and methods:

Annotations

○ @isTest: Marks a class or a method as a test


class/method. Classes marked with @isTest do not
count against our organization’s code size limit.

○ @testSetup: Defines a method in a test class that will


run before any test method in the class. This method is
used to create test data that is shared among all test
methods in the class.
kshitijdhoble
Various Annotations & Methods
○ @TestVisible: Allows test methods to access private or
protected members of a class. This is useful for testing
private methods or variables.

○ @IsTest(SeeAllData=true): By default, test methods


do not have access to data in our organization. Using
SeeAllData=true allows the test method to access the
organization's data. However, it's generally
recommended to create our own test data rather than
rely on actual data.

kshitijdhoble
Various Annotations & Methods
Methods
○ Test.startTest() & Test.stopTest(): These methods
delineate the start and end of a test block. Any
asynchronous code called between them is executed
synchronously within the test context.
○ System.assert(): To verify conditions in test methods.
○ Test.setMock(): Sets a mock implementation for a
callout. Useful for testing HTTP callouts.
○ Test.isRunningTest(): Checks if the code is running in
a test context.
○ Test.loadData(): Loads data from CSV files into
SObjects for testing.
○ Test.getStandardPricebookId(): Retrieves standard
price book ID for testing.
kshitijdhoble
Running & Monitoring Tests
● Debugging: Use System.debug() statements within test
methods to trace execution and diagnose issues.

● Test Execution: us can execute tests individually or in bulk


through Developer Console, Setup, or Salesforce CLI.

● Test Results: The results show which tests passed or failed,


with detailed error messages for failed tests.

● Test History: Salesforce maintains a history of test


executions, allowing us to analyze trends and regressions.

kshitijdhoble
Example
● Here's a simple scenario for testing an Apex class related to
the Account object.
● Objective: Verify that an Account record is created with
the correct name, and ensure that the record count in the
system is as expected.
// let's assume an Apex class that creates an Account record.

public class Account {


public static Account createAccount(String accountName) {
Account acc = new Account(Name = accountName);
insert acc;
return acc;
}
}

kshitijdhoble
Example
// Now, we'll write a test class to ensure the createAccount
method in the AccountHandler class works as expected.

@isTest
private class AccountHandlerTest {

@isTest
static void testCreateAccount() {
// Starting a new test context
Test.startTest();

// Calling the method to create an account


Account acc =
AccountHandler.createAccount('Test Account');

kshitijdhoble
Example
Test.stopTest(); // Ending the test context

// Verifying the account was created


System.assertNotEquals(null, acc.Id, 'Account ID
should not be null after insertion');

// Verify the account name is correct


System.assertEquals('Test Account', acc.Name,
'Account name should be "Test Account"');

// Verify only one account exists in the system


Integer accountCount = [SELECT COUNT() FROM Account];
System.assertEquals(1, accountCount, 'There should be
exactly one account in the system');
}
}
kshitijdhoble
Explanation
● Test Class Declaration: The class AccountHandlerTest is
marked with @isTest, indicating it's a test class.
● Test Method testCreateAccount( ):
○ Test.startTest( ): This method marks the beginning of
the test. It resets governor limits, simulating a fresh
transaction.
○ Method Call: The createAccount method of the
AccountHandler class is called with the parameter
'Test Account'.
○ Test.stopTest( ): This marks the end of the test context.
It’s important for scenarios where asynchronous
processing or governor limits might be involved.

kshitijdhoble
Explanation
○ Assertions:
■ System.assertNotEquals(null, acc.Id): Ensures the
account was successfully inserted by checking that
the Id is not null.
■ System.assertEquals('Test Account', acc.Name):
Validates that the account name is as expected.
■ System.assertEquals(1, accountCount): Checks
that only one account exists in the database,
ensuring no other records were created.

kshitijdhoble
Explanation
● We can run this test class in our Salesforce org through the
Developer Console, Setup, or using a Continuous
Integration (CI) tool. The test should pass if the
createAccount method is working correctly.
● If the createAccount method behaves as intended, the test
will pass, confirming that the account creation logic is
functioning correctly. If any assertion fails, it indicates a
potential issue with the method implementation, which
will need to be addressed.

kshitijdhoble
Thank-us!
Stay Tuned & Follow

kshitijdhoble
Day 18

Apex
Security

kshitijdhoble
Apex Security
● Apex security is a critical aspect of developing secure and
robust applications on the Salesforce platform.

● Apex security involves implementing measures to protect


data and ensure that Apex code adheres to the security
model of the Salesforce platform.

● The goal is to prevent unauthorized access to sensitive


data, avoid vulnerabilities like SQL injection, and ensure
that user permissions are respected.

kshitijdhoble
Why do we need it?
● Apex security is essential for several reasons:

● Protection of Sensitive Data

○ Preventing Unauthorized Access: Salesforce


applications often handle sensitive customer data,
financial records, and other critical information. Apex
security ensures that only authorized users can access
or modify this data, protecting it from unauthorized
access.

○ Data Integrity: Ensuring that data is not only


protected but also accurate and consistent. Apex
security prevents malicious or accidental alterations to
the data, which could lead to significant issues.

kshitijdhoble
Why do we need it?
● Compliance With Regulations

○ Legal Requirements: Many organizations must


comply with data protection regulations like GDPR,
HIPAA, and others. Apex security helps ensure that
applications adhere to these regulations by enforcing
proper access controls, auditing, and data encryption.

○ Audit Trails: Security measures ensure that detailed


records of data access and modifications are
maintained, which is often a requirement for
compliance.

kshitijdhoble
Why do we need it?
● Prevention of Security Vulnerabilities

○ SQL Injection and Code Injection: Without proper


security in Apex, applications can become vulnerable
to injection attacks, where attackers manipulate SQL
or Apex code to gain unauthorized access or perform
harmful actions.

○ Cross-Site Scripting (XSS): Unsecured Apex code can


also be exploited through XSS attacks, where attackers
inject malicious scripts into web pages viewed by other
users.

kshitijdhoble
Why do we need it?
● Respecting User Permissions

○ Adhering to Salesforce's Security Model: Salesforce


has a robust security model that includes user profiles,
roles, permissions, and sharing rules. Apex security
ensures that custom code respects these built-in
security measures, so users can only perform actions
they're authorized to.

○ Field-Level Security (FLS) and CRUD Operations:


Apex security checks ensure that users cannot view or
modify fields or records they don’t have permission to
access, maintaining the integrity of the security model.

kshitijdhoble
Why do we need it?
● Preventing Data Breaches:

○ Minimizing Risk: Data breaches can have severe


consequences, including financial loss, legal penalties,
and damage to an organization’s reputation. Apex
security helps minimize the risk of data breaches by
implementing strong access controls, encryption, and
monitoring.

○ Confidentiality: Ensuring that confidential business


data remains secure and is only accessible to those
with appropriate permissions.

kshitijdhoble
Why do we need it?
● Ensuring Application Stability:

○ Preventing Denial of Service (DoS): Poorly secured


Apex code can lead to resource exhaustion attacks,
where malicious users exploit system limits to disrupt
service availability. Proper security practices in Apex
prevent such scenarios.

○ Safe Integration with Third-Party Services: Securely


managing integrations with external systems prevents
data leakage or unauthorized access through API calls.

kshitijdhoble
Why do we need it?
● Maintaining Trust with Users & Customers:

○ User Confidence: Users are more likely to trust and


use an application that demonstrably protects their
data. Strong Apex security helps maintain user
confidence by ensuring their data is secure.

○ Brand Reputation: A strong security posture helps


protect an organization’s brand and reputation by
preventing data breaches or security incidents that
could harm public perception.

kshitijdhoble
Why do we need it?
● Enabling Secure AppExchange Deployment:

○ Passing Security Reviews: If we are developing apps


for the Salesforce AppExchange, our app must pass a
rigorous security review. Implementing Apex security is
crucial to meet the requirements of this review and
ensure that your app can be deployed on the platform.

○ Mitigating Risks in Multi-Tenant Environments:


Salesforce is a multi-tenant environment, meaning
multiple organizations share the same infrastructure.
Apex security helps ensure that the code doesn’t
inadvertently expose your data to other tenants.

kshitijdhoble
Enforcing CRUD & FLS
● CRUD (Create, Read, Update, Delete):

○ When writing Apex code, it is essential to check


whether the current user has the necessary
permissions to perform CRUD operations on an object.

○ Failing to enforce these checks can lead to


unauthorized data access.

● Field-Level Security (FLS):

○ Similarly, FLS must be respected in Apex. This ensures


that the user can only view or edit fields they are
permitted to access.
kshitijdhoble
Enforcing CRUD & FLS
● How to enforce:
○ Use isAccessible(), isCreateable(), isUpdateable(), and
isDeleteable() methods on SObjectAccessDecision
for CRUD checks.
○ For FLS, use isAccessible() and isUpdateable()
methods on Schema.SObjectField. Example:
if (Schema.sObjectType.Account.fields.Name.isAccessible())
{
// Safe to read the field
String accountName = account.Name;
}
if (Schema.sObjectType.Account.isCreateable()) {
insert account;
} kshitijdhoble
Sharing Rules & Apex
● Sharing rules and Apex work together to control and
extend the visibility and access of records in Salesforce.

● Understanding how they interact is crucial for building


secure and well-functioning applications on the platform.

● As we know, Sharing rules are used to extend record access


beyond the standard object-level permissions.

● They are particularly useful in cases where you need to


grant additional access to records to specific users or
groups based on criteria or ownership.

kshitijdhoble
Sharing Rules & Apex
● Two major types of Sharing rules:
○ Criteria-based Sharing Rules: Grant access to records
based on the values of specific fields.
○ Owner-based Sharing Rules: Grant access to records
based on who owns the record.
● How Sharing Rules works:
○ Default Behavior: OWD settings determine the
baseline level of access to records Sharing rules are
then applied to extend access beyond these defaults.
○ Hierarchy: Sharing rules do not decrease access levels;
they only grant additional access.

kshitijdhoble
Sharing Rules & Apex
● With Sharing and Without Sharing: When writing Apex
classes, the keywords with sharing and without sharing
determine whether the Apex code respects the sharing
rules defined in Salesforce.
● With Sharing: The Apex code respects the sharing rules
and OWD settings of the current user. It ensures that the
code does not access records the user should not see.
● Without Sharing: The Apex code ignores sharing rules and
can access records regardless of the current user’s
permissions. This is typically used when we need to
perform operations that require full access to records, like
administrative tasks.

kshitijdhoble
Sharing Rules & Apex
● Example:

public with sharing class AccountService {


public List<Account> getAccountsForCurrentUser() {
return [SELECT Id, Name FROM Account];
}
}
// —------------------------------------------------------
public without sharing class AccountService {
public List<Account> getAccountsForCurrentUser() {
return [SELECT Id, Name FROM Account];
}
}

kshitijdhoble
SOQL Injection Prevention
● SOQL Injection is a security vulnerability that occurs when
an attacker manipulates the input to a SOQL query in such
a way that it alters the intended query logic.
● This can lead to unauthorized data access or even data
modification.
● SOQL injection occurs when untrusted user input is
directly used in a SOQL query without proper validation or
sanitization.
● This can allow an attacker to alter the query's structure and
execute unintended commands.
● To prevent SOQL injection, always use bind variables in
your SOQL queries, which safely incorporate user input.

kshitijdhoble
SOQL Injection Prevention
● In this example, the input provided by the user could
manipulate the query to return all Account records instead
of just the intended one.
// Vulnerable code
String userInput = 'test\' OR Name != null OR Name = \'';

String query = 'SELECT Id, Name


FROM Account
WHERE Name = \'' + userInput + '\'';

List<Account> accounts = Database.query(query);

kshitijdhoble
SOQL Injection Prevention
● Risks Associated with SOQL Injection:

● Unauthorized Data Access: Attackers can access data that


they should not be able to view by manipulating the query.

● Data Modification: In some cases, it might be possible to


inject SOQL in a way that modifies data.

● Denial of Service: A crafted query might also consume


excessive resources, potentially leading to a denial of
service (DoS).

kshitijdhoble
SOQL Injection Prevention
● Preventing SOQL Injections:
● Use Bind Variables: The most effective way to prevent
SOQL injection is by using bind variables. Bind variables
automatically handle user input safely by escaping any
special characters that could alter the query structure.
● In this example, :userInput is a bind variable, and Salesforce
ensures that the input is treated as a string literal in the
query.
// Secure code using bind variables
String userInput = 'test';
List<Account> accounts = [SELECT Id, Name
FROM Account
WHERE Name = :userInput];

kshitijdhoble
SOQL Injection Prevention
● Strict Input Validation: Ensure that user input is validated
before it is used in a SOQL query. This includes checking
that the input conforms to expected formats and lengths.
// Input validation
String userInput = 'test';
if (userInput.matches('[a-zA-Z0-9]+')) {
List<Account> accounts = [
SELECT Id, Name
FROM Account
WHERE Name = :userInput];
} else {// Handle invalid input}

kshitijdhoble
SOQL Injection Prevention
● Static Queries: Use static SOQL queries wherever possible,
as they are automatically protected against injection
attacks. Example:
// Secure static query
List<Account> accounts = [SELECT Id, Name
FROM Account WHERE Name = 'test'];

● Avoid Dynamic SOQL Where Possible: Dynamic SOQL


(where the query string is constructed at runtime) should
be avoided or used with extreme caution. If dynamic SOQL
is necessary, ensure that all user inputs are passed as bind
variables or thoroughly sanitized.

kshitijdhoble
SOQL Injection Prevention
● Use Escaping Functions: If dynamic queries are
unavoidable and bind variables cannot be used, use
escaping functions such as String.escapeSingleQuotes() to
sanitize the input. Example:
// Secure dynamic query with escaping
String userInput = 'test';
String safeInput =
String.escapeSingleQuotes(userInput);
String query = 'SELECT Id, Name
FROM Account
WHERE Name = \'' + safeInput + '\'';
List<Account> accounts = Database.query(query);

kshitijdhoble
Data Sanitization
● User Input:

○ Always sanitize and validate user input before


processing it in Apex.

○ This helps prevent cross-site scripting (XSS), SQL


injection, and other injection attacks.

● Sanitization Techniques:

○ Use String.escapeHtml4() for escaping HTML in strings.

○ Use regex patterns to validate expected input formats.

kshitijdhoble
Encryption
● Platform Encryption: Salesforce provides Shield Platform
Encryption for encrypting data at rest. Apex can interact
with encrypted fields, but it's essential to understand the
limitations, such as indexing and searching on encrypted
fields.

● Custom Encryption: If custom encryption is needed in


Apex, we can use the Crypto class, which provides
methods for encryption, decryption, signing, and more.
// Example
Blob key = Crypto.generateAesKey(128);
Blob data = Blob.valueOf('Sensitive Data');
Blob encryptedData =
Crypto.encryptWithManagedIV('AES128', key, data);

kshitijdhoble
Apex Class Security
● Public Access: Ensure that only authorized users or
processes can invoke the Apex classes. Avoid making
classes global unless necessary, as it opens the code to a
wider audience.

● APEX REST and SOAP: Secure your REST and SOAP


services by implementing authentication, ensuring that
only authorized users can access these endpoints. Use
session-based or OAuth-based authentication
mechanisms.

kshitijdhoble
Security Review for AppExchange
● If we are developing an app for the Salesforce
AppExchange, it must pass a security review. The review
checks for common vulnerabilities and adherence to
Salesforce's security best practices.

● Key Areas of Focus:

○ Apex security: CRUD/FLS enforcement, secure code.

○ Data storage and encryption: Handling of sensitive


data.

○ User access and authentication: Properly managed


user roles and permissions.

kshitijdhoble
Logging & Monitoring
● Security Monitoring:

○ Regularly monitor and log Apex transactions to detect


suspicious activity.

○ Use Salesforce's Event Monitoring feature for detailed


logs.

● Audit Trail:

○ Maintain an audit trail of critical changes and access to


sensitive data.

○ This helps in tracing unauthorized access and


mitigating potential breaches.

kshitijdhoble
Third Party Integrations
● Secure Integrations:

○ When integrating with third-party systems via Apex,


ensure that data is transmitted securely.

○ Use HTTPS for external calls and validate all incoming


data.

● OAuth:

○ Prefer OAuth for secure authentication in integrations,


ensuring that tokens are managed securely.

kshitijdhoble
Best Practices
● Enforce CRUD/FLS: Always check if the user has permission
to access or modify data before doing so in Apex.

● Use "With Sharing": Respect sharing rules to ensure users


only access the records they should.

● Prevent SOQL Injection: Use bind variables in queries to


avoid SQL injection risks.

● Limit Public Access: Avoid making classes global unless


necessary, and secure your REST/SOAP services.

● Sanitize Inputs: Validate and clean user inputs to prevent


injection attacks.

kshitijdhoble
Best Practices
● Use Encryption: Protect sensitive data using Platform
Encryption or the Crypto class.

● Respect Governor Limits: Write efficient, bulkified code to


stay within resource limits.

● Security Review: Follow Salesforce security guidelines,


especially for AppExchange apps.

● Use Managed Sharing: Programmatically share records


securely, respecting user access levels.

● Monitor and Log: Regularly log and monitor for suspicious


activity and maintain an audit trail.

kshitijdhoble
Best Practices
● Handle Errors Safely: Avoid exposing detailed error
messages; handle exceptions gracefully.

● Secure Integrations: Use HTTPS and OAuth for secure


third-party integrations.

● Follow Least Privilege: Grant only the permissions that are


absolutely necessary.

● Review Code Regularly: Periodically check your code for


vulnerabilities and stay updated on security patches.

kshitijdhoble
Thank-us!
Stay Tuned & Follow

kshitijdhoble

You might also like