5.2.12.3. Обработчики исключений клиентского уровня
Необработанные исключения в блоках Web Client и Desktop Client, возникшие на клиентском уровне или переданные с Middleware, попадают в специальный механизм обработчиков. Этот механизм реализован в модуле gui и доступен обоим клиентам.
Собственные классы обработчиков можно создавать в корневом пакете модуля gui, web или desktop проекта. Обработчик должен быть управляемым бином, реализовывать интерфейс GenericExceptionHandler
, в методе handle()
которого производить обработку и возвращать true
, либо сразу возвращать false
, если данный обработчик не может обработать переданное ему исключение. Такое поведение позволяет организовать "цепочку ответственности" обработчиков.
Рекомендуется наследовать классы своих обработчиков от базового класса AbstractGenericExceptionHandler
, который умеет разбирать цепочку исключений (с учетом упакованных внутри RemoteException
) и реагировать на конкретные типы исключений. Типы исключений, для которых предназначен данный обработчик, указываются в массиве строк, передаваемом в конструкторе обработчика базовому конструктору. Каждая строка массива должна содержать одно полное имя класса обрабатываемого исключения, например:
@Component("sample_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractGenericExceptionHandler {
public ZeroBalanceExceptionHandler() {
super(ZeroBalanceException.class.getName());
}
...
Если класс исключения недоступен на клиенте, следует указывать его имя строковым литералом:
@Component("sample_ForeignKeyViolationExceptionHandler")
public class ForeignKeyViolationExceptionHandler extends AbstractGenericExceptionHandler {
public ForeignKeyViolationExceptionHandler() {
super("java.sql.SQLIntegrityConstraintViolationException");
}
...
В случае использования в качестве базового класса AbstractGenericExceptionHandler
логика обработки располагается в методе doHandle()
, и может выглядеть следующим образом:
@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, WindowManager windowManager) {
String msg = messages.getMainMessage("zeroBalance.message");
windowManager.showNotification(msg, IFrame.NotificationType.ERROR);
}
Если имени класса исключения недостаточно для того, чтобы принять решение о применимости данного обработчика к исключению, следует определить метод canHandle()
, получающий кроме прочего текст исключения. Метод должен вернуть true
, если данный обработчик применим для исключения. Например:
@Component("sample_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractGenericExceptionHandler {
public ZeroBalanceExceptionHandler() {
super(ZeroBalanceException.class.getName());
}
@Override
protected boolean canHandle(String className, String message, @Nullable Throwable throwable) {
return StringUtils.containsIgnoreCase(message, "Insufficient or zero funds in your account");
}
...
WindowManager
предоставляет метод showExceptionDialog()
для отображения диалогового окна с выброшенным исключением и его stacktrace. Метод принимает следующие параметры:
-
throwable
- экземплярThrowable
. -
caption
- заголовок диалога. Это необязательный параметр, если он не установлен, используется заголовок по умолчанию. -
message
- сообщение диалога. Это необязательный параметр, если он не установлен, используется сообщение по умолчанию.
Пример вызова диалога в обработчике исключения:
@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, WindowManager windowManager) {
if (throwable != null)
windowManager.showExceptionDialog(throwable, "Exception is thrown", message);
else
windowManager.showNotification(message, IFrame.NotificationType.ERROR);
}
Для локализации сообщений об ошибках нужно переопределить ключи для соответствующего обработчика в главном пакете сообщений. Ниже приведён пример ключей для RowLevelSecurityExceptionHandler
, обрабатывающего нарушения ограничений прав доступа (row-level security):
-
rowLevelSecurity.caption.User.create
- заголовок уведомления о конкретной сущности и операции, -
rowLevelSecurity.caption.Group
- заголовок уведомления о конкретной сущности, -
rowLevelSecurity.entityAndOperationMessage.User.create
- тело сообщения о конкретной сущности и операции, -
rowLevelSecurity.entityAndOperationMessage.Group
- тело сообщения о конкретной сущности.