How to choose the best cloud platform for AI
Explore a strategy that shows you how to choose a cloud platform for your AI goals. Use Avenga’s Cloud Companion to speed up your decision-making.
Unpredicted behavior in a custom code. Can we eliminate it?
The ability to customize your Salesforce org code is not just a “nice to have.” It greatly increases the capability and flexibility of Salesforce.
However, custom code can also be tricky to use. It would be great if we could detect unpredicted behavior in our custom code through functionality, such as catching and logging exceptions.
There is no problem with logging exceptions in Lightning Components. JavaScript code can be surrounded in a try catch block. As a result we can easily track any type of client side exceptions:
doSomething: function(component) {
try {
unexistingMethod(); // ReferenceError here
} catch(e) {
// log exception here
}
}
It is up to you what to do with such errors. It can be JavaScript console output:
console.error(e);
or Lightning notification to user:
var toastEvent = $A.get("e.force:showToast");
toastEvent.setParams({
"title": e.name,
"message": e.message,
"mode": "sticky",
"type": "Error"
});
toastEvent.fire();
In the case where some exceptions happen at a server Apex controller, we are also on a safe side through the use of a special type of exception – AuraHandledException
. We can convert any exception into an AuraHandledException
and send it to Lightning Component as a response:
@AuraEnabled
public static String serverMethod(String name) {
try {
// some Apex code
} catch(DMLException ex) {
throw new AuraHandledException('Unable to save record');
}
}
Please, note, AuraHandledException
supports String
argument only. This class is not extensible. If you need to send some data to client side use the following approach:
→ Migrate from Aura to Lightning Web Components to Increase Performance
The situation with a pure Apex code is slightly more complicated. We can set up an Apex Exception Email that will send an unhandled exception to an Administrator’s mailbox. However, in many cases this is not enough. Here are some of the disadvantages,
Let’s overview the tools we can use in Salesforce to resolve it.
→ Get 100% Code Coverage for Salesforce Custom Metadata Based Decisions
Salesforce has a unique feature to commit any transaction to a database automatically. The System will persist changes after the execution context is finished if no unhandled exception occurs.
This approach is handy, and in most cases it is exactly what you want. But if an unhandled exception occurs, it rolls back everything, not only DML operations. Scheduled jobs, future methods, batches, queueable jobs, emails will not be run or sent. That is why the following piece of code will never work:
public void someMethod() {
try {
// some Apex code
} catch(Exception ex) {
// log exception here
throw ex;
// rethrow exception again
}
}
By rethrowing an exception, you add an unhandled exception into the execution context.
The simple answer is no. For example, you are doing a complex validation in an Apex trigger. Any call of addError()
method is a DMLException
. We are not interested in catching such exceptions.
The best practice is to catch exceptions in a top level component, e.g., Web service, controller of Visualforce page, server side controller of Lightning Component, etc. In other words, in any place where an execution context will start.
Adding a try .. catch
block to all of your methods can ruin the readability of your code. It also increases the complexity of writing unit tests.
What is more important, by catching exceptions you are braking the logic of your application. You are forcing low level components to be responsible for decisions, e.g., what to do in a critical situation.
From time to time you can also get an exception you would never expect. For example, while your code is sending email to Contact, the following is received:
System.EmailException: INVALID_EMAIL_ADDRESS, email address has bounced
Such things are really hard to predict, and the reason we must be able to log exceptions.
Let’s imagine we want to log an exception in a custom Apex code. For this purpose we can use a custom object to store such exceptions. Let’s say ErrorLog__c
object. Look at the code below:
public static void someMethod(String name)
try {
// Apex code here
} catch(Exception ex) {
ErrorLog__c log = new ErrorLog__c(
Description__c = 'Error: ' + ex.getMessage()
);
insert log;
}
}
This code will work if the execution context is clean, i.e., when there is no unhandled exception. However, if this code is a part in a chain of the execution context, it might not work. Look at the diagram below:
If an exception occurs after inserting the error log record into a database, the entire transaction will be rolled back. Your ErrorLog__c
record will not be saved.
The situation has totally changed with Platform Events. It is a new feature generally available since the Summer ’17 release (API version 40.0). Platform Event is a bus to send read only messages. When the message is sent, you are not able to return it. We will use this feature in the error logging system.
The idea is simple. When you need to save a new ErrorLog__c
record, publish a Platform Event. Later, you can subscribe to this event and save the ErrorLog__c
record in the database:
Please, note that the Platform Event trigger runs under the Automated Process entity. This is a system user. In order to see which user has sent the event, have a look at CreatedBy field on the Platform Event record.
What is more important, we are not limited in logging the exception. We can react to it. For example, we can run the Apex method to repeat the failed operation as well as many more uses.
Platform Events is a great tool for an event-driven software architecture. They extend programming functionalities in Apex, and can be used even in an execution context with an unhandled exception.
Avenga is here to help our clients and partners actualize the Salesforce® investment into quality deployment, ecosystem integration, timely project implementation.
* US and Canada, exceptions apply
Ready to innovate your business?
We are! Let’s kick-off our journey to success!