3.2.12.3. Обработчики исключений клиентского уровня
Необработанные исключения, возникшие на клиентском уровне или переданные с Middleware, попадают в специальный механизм обработчиков блока Web Client.
Обработчик должен быть управляемым бином, реализовывать интерфейс UiExceptionHandler
, в методе handle()
которого производить обработку и возвращать true
, либо сразу возвращать false
, если данный обработчик не может обработать переданное ему исключение. Такое поведение позволяет организовать "цепочку ответственности" обработчиков.
Рекомендуется наследовать классы своих обработчиков от базового класса AbstractUiExceptionHandler
, который умеет разбирать цепочку исключений (с учетом упакованных внутри RemoteException
) и реагировать на конкретные типы исключений. Типы исключений, для которых предназначен данный обработчик, указываются в массиве строк, передаваемом в конструкторе обработчика базовому конструктору. Каждая строка массива должна содержать одно полное имя класса обрабатываемого исключения.
Предположим, имеется следующий класс исключения:
package com.company.demo.web;
public class ZeroBalanceException extends RuntimeException {
public ZeroBalanceException() {
super("Insufficient funds in your account");
}
}
Тогда обработчик должен иметь следующий конструктор:
@Component("demo_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractUiExceptionHandler {
public ZeroBalanceExceptionHandler() {
super(ZeroBalanceException.class.getName());
}
...
Если класс исключения недоступен на клиенте, следует указывать его имя строковым литералом:
@Component("sample_ForeignKeyViolationExceptionHandler")
public class ForeignKeyViolationExceptionHandler extends AbstractUiExceptionHandler {
public ForeignKeyViolationExceptionHandler() {
super("java.sql.SQLIntegrityConstraintViolationException");
}
...
В случае использования в качестве базового класса AbstractUiExceptionHandler
логика обработки располагается в методе doHandle()
, и может выглядеть следующим образом:
package com.company.demo.web;
import com.haulmont.cuba.gui.Notifications;
import com.haulmont.cuba.gui.exception.AbstractUiExceptionHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Nullable;
@Component("demo_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractUiExceptionHandler {
public ZeroBalanceExceptionHandler() {
super(ZeroBalanceException.class.getName());
}
@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, UiContext context) {
context.getNotifications().create(Notifications.NotificationType.ERROR)
.withCaption("Error")
.withDescription(message)
.show();
}
}
Если имени класса исключения недостаточно для того, чтобы принять решение о применимости данного обработчика к исключению, следует определить метод canHandle()
, получающий кроме прочего текст исключения. Метод должен вернуть true
, если данный обработчик применим для исключения. Например:
package com.company.demo.web.exceptions;
import com.haulmont.cuba.gui.Notifications;
import com.haulmont.cuba.gui.exception.AbstractUiExceptionHandler;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Nullable;
@Component("demo_ZeroBalanceExceptionHandler")
public class ZeroBalanceExceptionHandler extends AbstractUiExceptionHandler {
public ZeroBalanceExceptionHandler() {
super(ZeroBalanceException.class.getName());
}
@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, UiContext context) {
context.getNotifications().create(Notifications.NotificationType.ERROR)
.withCaption("Error")
.withDescription(message)
.show();
}
@Override
protected boolean canHandle(String className, String message, @Nullable Throwable throwable) {
return StringUtils.containsIgnoreCase(message, "Insufficient funds in your account");
}
}
Интерфейс Dialogs
, доступный через параметр UiContext
метода doHandle()
, предоставляет специальный диалог для отображения исключений, содержащий схлопываемое поле с полным stack trace исключения. Данный диалог используется в обработчике по умолчанию, но вы можете использовать его и для конкретных исключений:
@Override
protected void doHandle(String className, String message, @Nullable Throwable throwable, UiContext context) {
if (throwable != null) {
context.getDialogs().createExceptionDialog()
.withThrowable(throwable)
.withCaption("Error")
.withMessage(message)
.show();
} else {
context.getNotifications().create(Notifications.NotificationType.ERROR)
.withCaption("Error")
.withDescription(message)
.show();
}
}