|
|||||||
Перехват события ApplicationEvent
Время создания: 28.01.2021 13:48
Раздел: INFO - Development - CUBA
Запись: wwwlir/Tetra/master/base/1611812936d92kt78r8y/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
П ерехват события ApplicationEvent deployment Yernar Adilbekovshut.desert дек. 2017 Добрый день! Проблема: я отправляю событие через Events, но в перехватчик в ExtAppMainWindow ничего не приходит. Если тип события MsgEvent наследовать от UiEvent, то его уже я не увижу в сервисе. А он мне нужен именно в сервисе… Если вы опубликовали событие при помощи Events и оно не реализует интерфейс UiEvent, то ничего никуда прийти не должно было, только если вы не передали событие ещё как-то.
дек. 2017 янв. 2018 ответов просмотров пользователя симпатии ссылки Частые авторы 9 6 Популярные ссылки
15 ответов с предполагаемым временем прочтения около 5 минут. Юрий Артамоновartamonov Лидер дек. 2017 События в UI полностью отделены от глобальных событий, вам потребуется самостоятельно регистрировать слушатели UI в глобальном компоненте-бине. Например: Copy @Component public class MessageEventBroadcaster { public final List<WeakReference<Consumer<GlobalMessageEvent>>> subscriptions = new ArrayList<>(); @EventListener protected void onMessage(GlobalMessageEvent event) { synchronized (subscriptions) { Iterator<WeakReference<Consumer<GlobalMessageEvent>>> iterator = subscriptions.iterator(); while (iterator.hasNext()) { WeakReference<Consumer<GlobalMessageEvent>> reference = iterator.next(); Consumer<GlobalMessageEvent> eventConsumer = reference.get(); if (eventConsumer == null) { iterator.remove(); } else { eventConsumer.accept(event); } } } } public void subscribe(Consumer<GlobalMessageEvent> handler) { synchronized (subscriptions) { subscriptions.add(new WeakReference<>(handler)); } } } Это компонент, который хранит список подписок в виде слабых ссылок. Это нужно, чтобы не порождать утечки памяти. В расширенном главном окне, мы подписываемся на рассылку события: Copy public class ExtAppMainWindow extends AppMainWindow { @Inject private MessageEventBroadcaster broadcaster; @Inject private BackgroundWorker backgroundWorker; private Consumer<GlobalMessageEvent> messageHandler; @Override public void init(Map<String, Object> params) { super.init(params); UIAccessor uiAccessor = backgroundWorker.getUIAccessor(); // save reference to message handler messageHandler = event -> uiAccessor.access(() -> { showNotification(event.getMessage()); }); broadcaster.subscribe(messageHandler); } Здесь мы создаём подписку на рассылку и обеспечиваем доступ к состоянию UI при помощи UIAccessor. Это необходимо, поскольку рассылка выполняется из другого потока. Из блока access { } мы можем изменять состояние UI, например, показывать нотификации. Разослать событие можно при помощи бина Events: Copy @Inject private Events events; public void onSendBtnClick() { events.publish(new GlobalMessageEvent("Demo for all!")); } Я подготовил небольшой пример: https://github.com/cuba-labs/demo-broadcast-event 13 Обратите внимание, что в этом примере бин и экраны находятся в одном приложении - Web Client. Этот способ не подходит для отправки событий из core в Web Client. Yernar Adilbekovshut.desert дек. 2017 Отлично! Как можно отправить некое событие в виде Notification всем пользователям которые онлайн в системе или отправить только одному (по логину) Yernar Adilbekovshut.desert дек. 2017 Я так понимаю, это уже через сокет решается? Юрий Артамоновartamonov Лидер дек. 2017 Обработчик сработает у всех экземпляров ExtAppMainWindow, нужно будет в нём отфильтровать по текущему пользователю события, например добавив в сообщение поле “получатель”. Это всего лишь пример рассылки сообщений всем HTTP сессиям / открытым вкладкам браузера. Кроме того, здесь сейчас никак не обрабатываются ошибки, которые могут возникнуть. Юрий Артамоновartamonov Лидер shut.desert дек. 2017 Вызов ui.access() автоматически доставит изменения в браузер пользователя по WebSocket соединению, это не нужно реализовывать Yernar Adilbekovshut.desert дек. 2017 Спасибо большое, все работает! 20 дней спустя Yernar Adilbekovshut.desert дек. 2017 Можно ли как то событие перекинуть с core или global слоя на веб слой? Konstantin Krivopustovkrivopustov CUBA.platform янв. 2018 Пока “из коробки” такого способа нет. Есть тикет: https://youtrack.cuba-platform.com/issue/PL-9024 22 8 дней спустя Yernar Adilbekovshut.desert 1 янв. 2018 Подскажите пожалуйста, что то путаница в голове… Copy @EventListener private void messgeHandle(GlobalMessageEvent e){} То я ведь так же могу иметь доступ к ExtAppMainWindow и вызвать showNotification? Есть ли нужда создавать MessageEventBroadcaster? Юрий Артамоновartamonov Лидер янв. 2018 Да, вы можете в этом методе использовать showNotification, но глобальные события, опубликованные из бинов, не будут приходить в этот метод, пока вы сами их туда не отправите, как показано в примере с MessageEventBroadcaster. Yernar Adilbekovshut.desert янв. 2018 Если c какого либо контроллера страницы или с бина который находится в веб модуле, отправить событие GlobalMessageEvent, то все методы объявленные с аннотацией @EventListener(GlobalMessageEvent.class) в модуле web, получат это событие! Не так ведь? Объясните пожалуйста, запутался что то?) Или я что то не учитываю и ошибаюсь? Юрий Артамоновartamonov Лидер янв. 2018 Объекты экранов UI не являются бинами и хранятся в пользовательских сессиях. Поэтому для обработчиков событий в них это не выполняется. События обрабатываются в экранах UI, только если порождены в экранах / в рамках пользовательской сессии и реализуют интерфейс UiEvent. Yernar Adilbekovshut.desert янв. 2018 Ясно, спасибо! У меня получилось так, создал GlobalMessageEvent который наследует только ApplicationEvent. Написал @EventListener метод для GlobalMessageEvent в ExtAppMainWindow. И опубликовал это событие в TestEdit(стандартная форма редактирования сущности Test), и вуаля уведомление перехватил в ExtAppMainWindow. Это правильная реализация перехвата уведомлении? Юрий Артамоновartamonov Лидер янв. 2018 Если вы опубликовали событие при помощи Events и оно не реализует интерфейс UiEvent, то ничего никуда прийти не должно было, только если вы не передали событие ещё как-то. Вопрос решён |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|