Обработка ошибок StreamResourceWriter через интерфейс ErrorHandler - PullRequest
0 голосов
/ 19 марта 2019

У меня есть класс 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 и вызывать его напрямую.

1 Ответ

0 голосов
/ 22 марта 2019

Есть способ, но он не идеален.

Вы можете получить все экземпляры пользовательского интерфейса через VaadinSession.getCurrent().getUIs().

Чтобы отфильтровать неактивные / отключенные интерфейсы, вы можете проверить, если ui.getSession() возвращает VaadinSession (так, не ноль).JavaDoc getSession говорит:

Метод вернет значение NULL, если пользовательский интерфейс в данный момент не подключен к VaadinSession.

Затем вы можете вызвать accessметод на каждом из пользовательских интерфейсов и создайте и покажите уведомление внутри пользовательского интерфейса.

for(UI ui : VaadinSession.getCurrent().getUIs()) {
    // Filtering out detached/inactive UIs
    if (ui.getSession() != null) {
        ui.access(() -> {
            // create Notification here
        });
    }   

Я сказал, что это не идеально, потому что вы должны иметь в виду, что у пользователя может быть открыто несколько пользовательских интерфейсов одновременно.время (например, несколько вкладок).

...