Subscribe Changes in SessionData

In an application we’d like to use two browser windows to interact with each other.

  1. start on the first screen with some inputs.
  2. Depending on the input the second shows or filters some data
  3. select an item on the second screen (while checking data between both screens)
  4. commit an action on the second screen
  5. remove done item from first screen

We found the possibility to add objects to SessionData to get the information from one screen to the second if we understand that right. Is it possible to subscribe changes to some objects of this session data or is there another simple way to let the second screen know, that it should react to input of first screen?

Yes, use Spring ApplicationEvents.

Create the publisher bean:

import io.jmix.ui.App;
import io.jmix.ui.AppUI;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class CurrentSessionUiEventsPublisher {

    public void publishEvent(ApplicationEvent event) {
        // active app in this session
        App app = App.getInstance();

        // notify all opened web browser tabs
        List<AppUI> appUIs = app.getAppUIs();
        for (AppUI ui : appUIs) {
            if (!ui.isClosing()) {
                // work in context of UI
                ui.accessSynchronously(() -> {
                    ui.getUiEventsMulticaster().multicastEvent(event);
                });
            }
        }
    }
}

Create the event class:

import org.springframework.context.ApplicationEvent;

public class GreetingEvent extends ApplicationEvent {

    private final String greeting;

    public GreetingEvent(Object source, String greeting) {
        super(source);
        this.greeting = greeting;
    }

    public String getGreeting() {
        return greeting;
    }
}

In a sender screen, publish the event:

@Autowired
private CurrentSessionUiEventsPublisher currentSessionUiEventsPublisher;

@Subscribe("sendEvent")
public void onSendEventClick(Button.ClickEvent event) {
    currentSessionUiEventsPublisher.publishEvent(new GreetingEvent(this, "Hello!"));
}

Subscribe to the event in receiver screens:

@Autowired
private Notifications notifications;

@EventListener
public void onGreeting(GreetingEvent event) {
    notifications.create().withCaption(event.getGreeting()).show();
}

The event will be delivered to receiver screens in all browser tabs of the currently connected user.

See also this message for other options for sending events.

Regards,
Konstantin

2 Likes

My apologies for reopening the subject, but this solution applies equally if multitenancy is used, i.e. it is limited to notify one tenant and not all tenants.

Regards,

Nelson F.

Sorry, I didn’t get it.
This topic is about sending events to all screens of a user session. What does it have to do with tenants?