Receive events fired with ComponentUtils.fireEvent() from another package in the MainLayout

Hi, guys!

In my MainLayout (extends AppLayout), I have a Grid inside a Dialog which can be opened/closed by a button placed on the header (with a click listener).

In another package i have a NotificationHandler class which can fire a custom event (named UpdateGridEvent) at UI level through a Form, something like this:

NotificationHandler.java:
private AppNotificationForm notificationForm = new AppNotificationForm(); [...] notificationForm.fireUpdateGridEvent();

AppNotificationForm.java:
` public void fireUpdateGridEvent() {
ComponentUtil.fireEvent(UI.getCurrent(), new AppNotificationForm.UpdateGridEvent(this));
}

public static abstract class AppNotificationFormEvent extends ComponentEvent<AppNotificationForm> {
    private final AppNotification notification;

    protected AppNotificationFormEvent(AppNotificationForm source, AppNotification notification) {
        super(source, false);
        this.notification = notification;
    }
    public AppNotification getNotification() {
        return notification;
    }
}

public static class UpdateGridEvent extends AppNotificationForm.AppNotificationFormEvent {
    UpdateGridEvent(AppNotificationForm source) {
        super(source, null);
    }
}`

I found a post on stackoverflow, where one guy said:

In the main view (AppLayout), you can register a listener for the custom event on the event bus. When the event is received, you can update […]

But I can’t figure how to do it. I tried to add a listener with a flow.shared.Registration object, in the MainView constructor:
registration = ComponentUtil.addListener( UI.getCurrent(), AppNotificationForm.UpdateGridEvent.class, event -> triggerUpdateNotificationsGrid() );
But this does not receive any event fired by the Form above.

Can you please assist me with this issue?

I also tried to do something similar to this example (https://cookbook.vaadin.com/ui-eventbus) but AppLayout does not have any onAttach, onDettach methods to override.

And sorry for the bad formatting.

AppLayout has those methods.

Indeed, I tried to override the methods inside a inner (wrong) block of MainLayout.
I now put the registration object inside onAttach in MainLayout and still dont receive any events tho. (I put a log inside the listener to execute but nothing)
The event seems to be fired.

Hard to say, just looking at the code snippets, it should work

Yes, and it works in some cases. I tried something else. Inside a view I put a button which executes something on buttonClickEvent, fires an UpdateGridEvent and updates view after finishing (example method):
private void updateView() { grid.setItems(service.findAllObjects(filterText.getValue())); }
So I stay on the view, press the button and when it updates the view, MainLayout receives the event and updates the grid in the Dialog.
The only difference between the first and this case is the 2nd case executes under a buttonClickListener. The 1st just fires the event on its own (no listener).

Wait… when you are firing the other event? From a background thread?

The 2nd one is fired from here (a method under the view):
reloadButton.setDisableOnClick(true); reloadButton.addClickListener(buttonClickEvent -> { // do some work in the back updateView(); Notification notification = Notification.show("reloaded"); reloadButton.setEnabled(true); });

The 1st is fired from a SerialPortDataListener (jSerialComm library), which is async.

No idea what that library is, but once I hear async - you need @Push and proper handling / passing of the current UI to the async code

https://vaadin.com/docs/latest/advanced/server-push

Using this, I have to pass UI.getCurrent() to the async thread when starting it, right?

Yeah there is also an example about it on the page linked

The feeder thread example

Got it, thank you