Real time update the grid items without refreshing browser manually

Hi everybody , I am full of new for this forum if I made a mistake about opening new topic please warn me also teach me the correct way to get help and maybe one day to help others.

I am trying to learn how can I perform that scenario;

I have two different browser tabs (Vaadin UI instance) with different routes. One for responsible for adding entity to DB ( till here everything works fine) . On other page , responsible to monitor list of entities , I have grid , when I refresh the monitoring page
I can see updated list but I want to learn how can I make it without refreshing . Also I tried to solve using sources on Internet and Vaadin website , it is getting more confused day by day. After 3-4 days tried myself I open the topic. Have a nice day everybody !

@Component
public class EventBus {

    private final Set<EventListener> listeners = new HashSet<>();

    public void subscribe(EventListener listener) {
        listeners.add(listener);
    }

    public void unsubscribe(EventListener listener) {
        listeners.remove(listener);
    }

    public void notifyUpdate(Object update) {
        listeners.forEach(listener -> listener.onEvent(update));
    }
}
@Route("monitor")
public class MonitorUserUI extends VerticalLayout implements EventListener {

    private final UserService userService;
    private final EventBus eventBus;
    private final Grid<User> grid = new Grid<>(User.class);
    private final ListDataProvider<User> dataProvider;

    public MonitorUserUI(UserService userService, EventBus eventBus) {
        this.userService = userService;
        this.eventBus = eventBus;
        add(grid);

        // Create a ListDataProvider for the grid
        dataProvider = new ListDataProvider<>(userService.getAllUsers());
        grid.setDataProvider(dataProvider);
        eventBus.subscribe(this);
    }

    @Override
    public void onEvent(Object event) {

        if (event instanceof User) {
            UI.getCurrent().access(() -> {
                User newUser = (User) event;
                dataProvider.getItems().add(newUser);
                grid.getDataProvider().refreshAll();
            });
        }
    }

    @PreDestroy
    public void onDestroy() {

        eventBus.unsubscribe(this);
    }
}
@Route("add")
public class AddUserUI extends VerticalLayout {

    private final UserRepository userRepository;
    private final EventBus eventBus;

    public AddUserUI(UserRepository userRepository, EventBus eventBus) {
        this.userRepository = userRepository;
        this.eventBus = eventBus;

        TextField nameField = new TextField("Name");
        TextField emailField = new TextField("Email");

        Button addButton = new Button("Add", event -> {
            String name = nameField.getValue();
            String email = emailField.getValue();
            if (!name.isEmpty() && !email.isEmpty()) {
                User user = new User();
                user.setName(name);
                user.setEmail(email);
                userRepository.save(user);
                eventBus.notifyUpdate(user);

                Notification.show("User added successfully");
                nameField.clear();
                emailField.clear();
            } else {
                Notification.show("Please enter both name and email");
            }
        });

        FormLayout formLayout = new FormLayout();
        formLayout.add(nameField, emailField, addButton);

        add(formLayout);
    }
}

I would fix this a little, as your component knows in which UI it is attached, and also, it is not guaranteed that your UI is still attached when event happens.

@Override
public void onEvent(Object event) {

    if (event instanceof User) {
        getUI().ifPresent(ui -> ui.access(() -> {
            User newUser = (User) event;
            dataProvider.getItems().add(newUser);
            grid.getDataProvider().refreshAll();
        )});
    }
}

The other thing your are missing is the @Push annotation in AppShellConfigurator implementing class. That is the reason why ui.access(..) did not trigger actual Push to client in your case.

I am really really thankful to you to help me , from heart. I just wonder that, I didnt share my main class and how do you know that I have no @Push annotation ? again thank you !

Let’s just say that you’re not the first one who has forgotten to add the annotation :wink:

like your answer :D I will use maybe one day to mention myself :D