У меня есть класс FileCreator, который реализует интерфейс StreamResourceWriter, и класс MainErrorHandler, который реализует ErrorHandler. Я использую класс MainErrorHandler
в качестве централизованного обработчика исключений в моем проекте, который в основном регистрирует исключение и показывает уведомление пользователю. Проблема заключается в том, что метод StreamResourceWriter.accept () выполняется в потоке, не являющемся пользовательским интерфейсом, и при возникновении исключения он направляется в ErrorHandler, который затем не может отобразить уведомление из-за " IllegalStateException : экземпляр пользовательского интерфейса не является имеется в наличии". Есть ли способ показать окно уведомления пользователю из MainErrorHandler, когда FileCreator выдает ошибку в методе accept()
?
Ниже фрагмента FileCreator.
public class FileCreator implements StreamResourceWriter {
@Override
public void accept(OutputStream stream, VaadinSession session) throws IOException {
// Run in a non ui thread.
// Writes to OutputStream but an Exception might be thrown during this process
}
}
Ниже фрагмента MainErrorHandler.
/**
* Centralized error handler
*/
public class MainErrorHandler implements ErrorHandler {
private static final Logger log = LoggerFactory.getLogger(MainErrorHandler.class);
@Override
public void error(ErrorEvent event) {
log.error("Error occurred", event.getThrowable());
//Cannot show a notification if ErrorEvent came from FileCreator.
//Will get an IllegalStateException: UI instance is not available.
Notification.show("Error occurred");
//Tried UI.getCurrent but it returns null if ErrorEvent came from FileCreator.
UI.getCurrent();
}
}
Использование Vaadin 13.0.1.
Редактировать
Одним из способов решения этой проблемы является непосредственная передача ссылки на пользовательский интерфейс в FileCreator. Ниже приведен пример.
public class FileCreator implements StreamResourceWriter {
private UI ui;
//Pass UI reference directly
public FileCreator(UI ui){
this.ui = ui;
}
@Override
public void accept(OutputStream stream, VaadinSession session) throws IOException {
try{
// Run in a non ui thread.
// Writes to OutputStream but an Exception might be thrown during this process
}catch(Exception e){
//I don't like this since have to catch all exceptions and have to call ErrorHandeler directly with a UI reference. Also what if somewhere in code ErrorHandler is changed and is not of type MainErrorHandler.
((MainErrorHandler)VaadinSession.getCurrent().getErrorHandler()).error(e, ui);
}
}
}
Как я уже говорил в комментариях, мне действительно не нравится этот подход, так как я вынужден перехватывать все исключения, должен приводить ErrorHandler к MainErrorHandler и вызывать его напрямую.