Exception handling
While conditional statements are great for handling the running of
different code blocks, exception handling is used to deal with errors.
Statements like throw
, try...catch
, finally
, and retry
can be used to handle exceptions. An exception is a way for the code to
jump away from the runnable code when an error occurs.
The throw statement can be used to give an error exception. A throw statement can specify an exception enum value, but it is best practice to use the global error, info, or warning methods. This method allows you to use a label to display to the user in an Infolog, as shown in the following example:
throw error("This is an error.");
Here is what an error, warning, and info message looks like in the user interface:
Static methods on the Global class can be called without the Global::
prefix, so the Global::error
method can also be called as shown in the following example:
error("This is an error.");
You can also use a try...catch
statement to process some code in the
try block, and then use the catch block to handle an exception if it
occurs. In the following example, the try
block runs some code. If a
numeric exception occurs, the first catch
block gives an info
message to display: "Found a Numeric." The second catch
block
handles any other errors that might be found. You should only catch
exceptions that you know your code inside the try
block might throw. All other exceptions should rise to the next stack frame.
try
{
//Run some code that might throw a numeric or other type of exception.
}
catch (Exception::Numeric)
{
info('Found a Numeric exception.');
}
catch
{
info('Caught an exception');
retry;
}
finally
{
// Executed no matter how the try block exits.
}
A retry
can be written in a catch block to jump back to the first
line of code within the try block. This can be used if the issue in the
implementation can be fixed by code in the catch block. Then, the try block will run again to give it a second chance to succeed. Make sure that the retry does not cause an infinite loop. A finally
clause can be
added to a try...catch
statement. Statements in the finally
clause are run when the implementation of the code leaves the try
block. The statements in the finally
block will run no matter
how the try
block exits.
If an exception is not handled, then the call to the current method is unraveled and the exception will be handled, or not handled, in the caller's scope.
User messages
By using the Message() API, you can have more control over the lifecycle of a message, you can explicitly add and remove messages. This can be used if you need validation messages removed at times other than when a save boundary has been crossed, or for displaying an informational message about a specific aspect of the user’s experience that is directly related to data validation.
Let’s look at an example:
messageId = Message::Add(MessageSeverity::Informational, "The customer is marked as inactive");
In this example, the message can then be cleared when a new record is shown on the page.
In addition to using the Message() API, you can use the Message::AddAction()
method so you can embed an action within a message that is sent to the message bar. This method supports adding a single action that is associated with a display or action menu item, that can then be visualized as a Link button.
In the following example, a message is triggered for a system administrator letting them know that a batch job is not running and then exposes an action to go directly to the Batch jobs page.
MenuItemMessageAction actionData = new MenuItemMessageAction();
actionData.MenuItemName("BatchJob");
str jsonData = FormJsonSerializer::serializeClass(actionData);
int64 messageId = Message::AddAction(MessageSeverity::Informational, "The Test batch job is not currently running", "Go to Batch jobs", MessageActionType::DisplayMenuItem, jsonData);
Here is the output:
Exceptions inside transactions
If an exception is thrown inside a transaction, the transaction is
automatically aborted (a ttsAbort
operation occurs). This applies
for exceptions that are thrown manually and for exceptions that are thrown by the system.
When an exception is thrown inside a ttsBegin - ttsCommit
transaction block, no catch statement inside that transaction block can
process the exception. Instead, the innermost catch statements that are
outside the transaction block are the first catch statements to be
tested.