
Apex Try Catch – Exception Handling Guide
Whether you are new to apex development or are a seasoned developer, exception handling is a practice that should always be followed when writing logic to perform DML statements such as Insert, Update or Delete etc.
In this article, we will dive deep into why and how exceptions are handled in apex logic.
What is Exception Handling?
Exception handling is the term, used to specify statements, written to ensure code failures are handled gracefully.
The following three statements are used in apex to handle exceptions:
Try
Logic written within the TRY block signifies that the system will attempt to run the code and if an error occurs during execution it will either THROW a custom exception or CATCH a built-In exception. In the example below, a new case is inserted within the TRY block to ensure if any issues occur during insert of the Case record then it will rollback the execution.
try{
Case c = new Case();
c.Subject = 'This is a new Case.';
insert c;
}
Catch
Logic written within the TRY block that fails an execution is successfully handled by using the CATCH statement to deal with a particular type of exception. One TRY statement can have multiple CATCH blocks for different exception types. In the example below, when a case record is inserted using the try block and the insert failed due to a validation rule etc then the catch block will handle that as a DML Exception Type.
try{
Case c = new Case();
c.Subject = 'This is a new Case.';
insert c;
} catch (DMLException e) {
System.debug('The following exception has occurred: ' + e.getMessage());
}
Finally
Logic written in the FINALLY block is executed whether there is an exception caught or not. Each TRY block can only have one FINALLY block. Finally is mostly used to clean up the code.
try{
Case c = new Case();
c.Subject = 'This is a new Case.';
insert c;
} catch (DMLException e) {
System.debug('The following exception has occurred: ' + e.getMessage());
} finally {
//Insert clean up code here such as clearing up variables etc
}
Why is it important?
If exceptions are not handled properly then user experience is poor especially when Salesforce Built-In exception are thrown as the error message appears at the top of the page which users may not understand.
Example:
What are the different types of exception?
A developer may choose to use the built-in exceptions provided by Salesforce for majority of the executions that can occur or create their own specific exceptions that fit the use case of the logic.
Built-In Exceptions
Apex provides a number of built-in exception types that the runtime engine throws if errors are encountered during execution.
- DMLException: This exception occurs when an error occurs when trying to insert, update or delete a record in Salesforce.
- ListException: This exception occurs when there is an issue with a list of records. Either when a list is empty and is being referenced without checking first if it is empty or if list has n number of records and your code is looking for n+1th record.
- NullPointerException: This exception occurs when a variable contains no value and is being referenced in code.
- QueryException: This exception occurs when a SOQL query is written poorly and the returning values are not handled properly.
- sObjectException: This exception occurs when the logic in the try catch is attempting to update a field that is not queried first.
- Exception: This is a catch all exception type where if you don’t specify any of the above then this will still catch all exceptions above gracefully.
Example:
try { String s; Boolean b = s.contains('abc'); // Causes a NullPointerException } catch(DmlException e) { System.debug('DmlException caught: ' + e.getMessage()); } catch(SObjectException e) { System.debug('SObjectException caught: ' + e.getMessage()); } catch(Exception e) { System.debug('Exception caught: ' + e.getMessage()); }
Custom Exceptions
The THROW statement only works when using a custom exception and can only be written within the TRY block.
To create your custom exception class, extend the built-in Exception class and make sure your class name ends with the word Exception, such as “MyException” or “PurchaseException”. All exception classes extend the system-defined base class Exception, and therefore, inherits all common Exception methods.
public class ExceptionExample { public virtual class BaseException extends Exception {} public class OtherException extends BaseException {} public static void testExtendedException() { try { Integer i=0; // Your code here if (i < 5) throw new OtherException('This is bad'); } catch (BaseException e) { // This catches the OtherException System.debug(e.getMessage()); } } }
What can you print in the debug log?
There are multiple exception methods available that can be used to find the root cause of a problem. Here are descriptions of some useful methods:
- getCause: Returns the cause of the exception as an exception object.
- getLineNumber: Returns the line number from where the exception was thrown.
- getMessage: Returns the error message that displays for the user.
- getStackTraceString: Returns the stack trace of a thrown exception as a string.
- getTypeName: Returns the type of exception, such as DmlException, ListException, and so on.
Example: To find out what some of the common methods return, try running this example.
try { Case c = new Case(); c.Subject = 'This is a new Case.'; insert c; } catch(Exception e) { System.debug('Exception type caught: ' + e.getTypeName()); System.debug('Message: ' + e.getMessage()); System.debug('Cause: ' + e.getCause()); // returns null System.debug('Line number: ' + e.getLineNumber()); System.debug('Stack trace: ' + e.getStackTraceString()); }
Conclusion
It is considered as a best practice in the world of programming to wrap all executions in a try catch statement to ensure user experience is seamless even when code fails to run successfully.