0% found this document useful (0 votes)
31 views

Exceptions

The document discusses various exceptions that can occur in Apex code along with examples to demonstrate each exception. It covers exceptions related to static methods, required fields, lists, null references, SOQL queries, SObjects, DML operations and governor limits.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views

Exceptions

The document discusses various exceptions that can occur in Apex code along with examples to demonstrate each exception. It covers exceptions related to static methods, required fields, lists, null references, SOQL queries, SObjects, DML operations and governor limits.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Exploring Salesforce Apex

Exceptions: Causes,
Implications, and Best Practices

Static method cannot be referenced from a


non-static context
public class ExceptionClass {
// Define a method to perform the DML operation
public static void insertContact() {
// Define a Contact object instance
Contact con = new Contact(FirstName='Sathya');

// Attempt to insert the Contact record


// Note: This will throw a DML Exception if there
are any issues with the insertion
insert con;
}
}
Anonymous Window

ExceptionClass obj=new ExceptionClass();


obj.insertContact();
The error "Static method cannot be referenced from a non-static context"
occurs because the insertContact() method in the ExceptionClass is not
static, but you are trying to call it using an object instance (obj).

In Java, when you call a non-static method, you must do it through an


instance of the class. However, if the method is static, it belongs to the
class itself and can be called without creating an instance of the class.

No need to Create Object Instance


REQUIRED_FIELD_MISSING
Now, execute the same code by modifying the contents of the Execute
Anonymous window.

ExceptionClass.insertContact();

The error message "REQUIRED_FIELD_MISSING, Required fields are


missing: [LastName]" indicates that the insert operation failed because the
LastName field of the Contact object is required, but it was not provided
during the object instantiation.
ListException
try {
List<String> strList = new List<String>();
strList.add('Apple');
strList.add('Banana');
String thirdElement = strList[2]; // Causes a
ListException
} catch(ListException le) {
System.debug('The following exception has occurred: ' +
le.getMessage());
}

In the given code, there's a list called strList containing two elements:
'Apple' and 'Banana'. The code tries to get the third element using strList[2],
but since lists start counting from 0, the index 2 refers to the third element.
However, because there are only two elements, there's nothing at index 2.
This causes an "IndexOutOfBoundsException" error because the code is
trying to access an element that doesn't exist in the list.
NullPointerException
try {
String s;
Boolean b = s.contains('abc'); // Causes a
NullPointerException
} catch(NullPointerException npe) {
System.debug('The following exception has occurred: ' +
npe.getMessage());
}

In the try block, a String variable 's' is declared but left uninitialized.
Subsequently, a call to the contains method on 's' is attempted. However,
as 's' is null, it results in a NullPointerException. This exception is caught in
the catch block, where a debug message is printed using System.debug,
conveying the occurrence of the exception.
QueryException
try {
// This statement doesn't cause an exception, even
though
// we don't have an account with name='XYZ'.
// The list will just be empty.
List<Account> accountList = [SELECT Name FROM Account
WHERE Name = 'XYZ'];
// accountList.size() is 0
System.debug(accountList.size());

// However, this statement causes a QueryException


because
// we're assigning the return value to an Account
object
// but no Account is returned.
Account singleAccount = [SELECT Name FROM Account WHERE
Name = 'XYZ' LIMIT 1];
} catch(QueryException qe) {
System.debug('The following exception has occurred: ' +
qe.getMessage());
}

Inside the try block, two SOQL queries are executed. The first query
retrieves a list of records meeting specific criteria. If no record matches the
criteria, the list will be empty, but it won't cause an exception. The second
query attempts to retrieve a single record using the LIMIT 1 clause. If no
record matches the criteria, it will cause a QueryException due to the
invalid assignment of a single record object when none are returned. In the
catch block, we handle the QueryException by printing a debug message
with the exception message using System.debug.

SObjectException
try {
// Querying for an Account record without retrieving
the Name field
Account acc = [SELECT Id FROM Account LIMIT 1];

// Attempting to access the Name field, which hasn't


been queried for
String accountName = acc.Name;
} catch (SObjectException se) {
System.debug('An SObjectException occurred: ' +
se.getMessage());
}

In the provided scenario, within the try block, a query is made to retrieve an
Account record, solely selecting the Id field while excluding the Name field.
Subsequently, an attempt is made to access the Name field of the queried
Account record. Due to the omission of the Name field in the query,
accessing it triggers an SObjectException. In response, the catch block
captures this exception and executes code to handle it appropriately. In this
case, a debug message is generated using System.debug(), conveying the
occurrence of the SObjectException along with its corresponding message.
This mechanism enables developers to identify and address issues
pertaining to the retrieval and manipulation of Salesforce SObject records
comprehensively.
Mixed Dml Exception
trigger MixedDMLTrigger on Account (after insert) {
// Attempting to update a User record (setup object)
and insert a Contact record (non-setup object) in the same
transaction
User u = new User(
LastName = 'Doe',
Alias = 'JD',
Email = '[email protected]',
Username = '[email protected]',
ProfileId = [SELECT Id FROM Profile WHERE Name =
'Standard User' LIMIT 1].Id
);
insert u;

Contact c = new Contact(


LastName = 'Smith',
Email = '[email protected]',
AccountId = Trigger.new[0].Id
);
insert c;
}
In this trigger context, we're attempting to insert an Account record
(non-setup object), and then, within the same transaction, we're trying to
insert a Contact record (another non-setup object) and also insert a User
record (a setup object). This mixture of DML operations on setup and
non-setup objects within the same transaction will result in a Mixed DML
Exception.
INVALID_FIELD_FOR_INSERT_UPDATE
trigger ContactTrigger on Contact (after insert) {
List<Contact> newContacts = new List<Contact>();

for (Contact newContact : Trigger.new) {


// Creating a new Contact record with the same Id
as the one being inserted
Contact duplicateContact = new Contact(
Id = newContact.Id, // Attempting to specify
the Id in an insert call
FirstName = newContact.FirstName,
LastName = newContact.LastName,
Email = newContact.Email
// Assuming other required fields are populated
);

newContacts.add(duplicateContact);
}

// Inserting the new Contact records


insert newContacts;
}
In straightforward terms, the trigger operates after new Contact entries are
made. Within the trigger, it attempts to duplicate these Contact records but
incorrectly includes the same ID for each duplicate. This action breaches
the rule that IDs cannot be specified when generating new records.
Consequently, when the trigger endeavors to save these duplicated
Contacts, it fails due to the violation regarding the IDs, resulting in the
mentioned exception.
System.FinalException: Record is read-only
trigger ContactTrigger on Contact (after insert, after
update) {
// This trigger fires after the Contact records are
inserted or updated
try {
// Attempting to edit records after the save point
for (Contact con : Trigger.new) {
con.LastName = 'NewLastName'; // This line
attempts to modify Contact record
}
update Trigger.new; // This line attempts to update
Contact records
} catch (Exception e) {
System.debug('An Exception occurred: ' +
e.getMessage());
}
}

The trigger "ContactTrigger" is designed to run after Contact records are


inserted or updated. Inside the trigger, an attempt is made to modify
Contact records by changing their Last Name. However, Salesforce
enforces a save point mechanism, meaning that once records are inserted
or updated, they become read-only within the same transaction. Therefore,
any attempt to modify these records after the save point will result in a
"System.FinalException" with the message "Record is read-only." This error
occurs because the trigger is trying to edit records that have already been
processed in the transaction. To resolve this, ensure that any modifications
to records occur before they are inserted or updated, typically within
"before" triggers or in the code that initiates the DML operation.
Limit Exception
Too Many SOQL Queries: 101
public class ExceptionClass {
public static void insertContact() {
try {
// Perform multiple SOQL queries within a loop
for (Integer i = 0; i < 101; i++) {
List<Account> accounts = [SELECT Id FROM
Account LIMIT 1];
}
System.debug('SOQL queries executed
successfully.');
} catch (Exception e) {
System.debug('An Exception occurred: ' +
e.getMessage());
}
}
}

In the provided code, we execute a loop iterating 101 times, each iteration
performing a SOQL query to retrieve one Account record. As the total
number of SOQL queries exceeds the governor limit of 100, it should
trigger the "Too Many SOQL Queries: 101" error. Upon encountering the
error, the code enters the catch block, where a debug message indicates
the occurrence of the error. This scenario accurately simulates the
condition where the code surpasses the allowed number of SOQL queries
within a single transaction, resulting in the expected error message.

Similarly, 'Too many DML statements: 151' occurs when the number of
Data Manipulation Language (DML) statements executed in a single
transaction exceeds the limit of 150 DML statements, leading to
performance issues and potential governor limit exceptions. Additionally,
'Too many query rows: 50001' indicates that a query returned more than
50,000 rows, surpassing the maximum number of rows returned by a single
query and potentially impacting application performance and stability."
Apex CPU Time Limit Exceeded
public class ExceptionClass {
public static void consumeCPUTime() {
// Perform a CPU-intensive operation
Long startTime = System.now().getTime();
while(System.now().getTime() - startTime < 10000)
{} // Loop for 10 seconds (intentionally CPU intensive)
}
}
The code defines a method named consumeCPUTime() within the
ExceptionClass class, which simulates a CPU-intensive operation by
entering a while loop that runs for 10 seconds. This loop continuously
checks the elapsed time and consumes CPU resources until the specified
duration is reached. Such CPU-intensive operations can lead to "Apex CPU
Time Limit Exceeded" errors if executed within a Salesforce transaction and
the cumulative CPU time exceeds the platform's limits, impacting various
operations like trigger execution or batch processing.
System.TypeException
public class QueryLimitExample {
public static void triggerException() {
try {
// Attempt to parse an invalid integer from a
string
Integer invalidInteger =
Integer.valueOf('abc');
} catch (System.StringException e) {
System.debug('An error occurred: ' +
e.getMessage());
}
}
}

The "System.TypeException: Invalid integer: abc" occurs when attempting


to convert a string into an integer using Apex's Integer.valueOf() method,
but the provided string ('abc') cannot be interpreted as a valid integer. This
exception signifies a failure in parsing the string as a numerical value due
to its non-numeric nature, resulting in the inability to convert it into an
integer.
UnexpectedException
The "UnexpectedException" typically represents an unexpected error that
occurred during the execution of Apex code. This exception is thrown when
an unexpected situation or condition arises that the Apex runtime cannot
handle. It serves as a catch-all for errors that cannot be classified under
specific exception types. When encountering an "UnexpectedException,"
it's crucial to review the surrounding code and the context of its execution
to identify any potential issues or anomalies that may have led to the
unexpected error. Additionally, reviewing debug logs and utilizing error
handling mechanisms can help diagnose and resolve the underlying cause
of the unexpected exception.

You might also like