Live Data

An example of simple data being live updated without input from the user. It is a pure server to client call.

Back to overview

Global Live Data

This illustrates a simple server to client call. Note that on the client side, there is nothing referring to this - there is no polling.

Here we show a global update, which is shared by all session. As such, if you'd open this page concurrently in two tabs, you'll see the shared number be the same across all tabs.

In this case, we send the update to all users who are on this page right now.

Global, shared (0.5-second delay between updates): 0
JDK22.0.2 w/ Medusa 0.9.6-SNAPSHOT

Client

Global, shared (0.5 second delay between updates):
<div class="sample-counter" th:text="${randomNumberShared}"></div>

Server

import io.getmedusa.medusa.core.annotation.UIEventPage;
import io.getmedusa.medusa.core.attributes.Attribute;
import io.getmedusa.medusa.core.bidirectional.ServerToClient;
import io.getmedusa.medusa.core.session.Session;
import io.getmedusa.medusa.core.session.StandardSessionTagKeys;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.List;
import java.util.Random;

@UIEventPage(path = "/detail/live-data", file = "/pages/live-data.html")
public class LiveStatisticController {

    private final ServerToClient serverToClient;
    public LiveStatisticController(ServerToClient serverToClient) {
        this.serverToClient = serverToClient;
    }

    public List<Attribute> setupAttributes(Session session) {
        return List.of(
                new Attribute("randomNumberShared", 0)
            );

    }

    //this process does not have to be a timer, but because timers run on a separate thread
    //outside of context like, this perfect to kick off the serverside call
    @Scheduled(fixedDelay = 500)
    public void someServerProcess() {
        serverToClient.sendAttributesToSessionTag(
                List.of(new Attribute("randomNumberShared", randomInt())),
                StandardSessionTagKeys.ROUTE,
                "/detail/live-data");
    }

    private int randomInt() {
        return new Random().nextInt(99999);
    }

}

Unique per session Live Data

Here, we demonstrate that we can send updates to specific sessions as well.

We can do this by creating a custom tag that identifies who we want to target, and then send the update to that tag.

In this case, we create that custom tag when you press the subscribe button. The scheduler then picks it up and sends you a unique random. We also do this at page load, to illustrate the Session is reachable in different areas.

Unique per session: 0

Client

Unique per session:
<div class="sample-counter" th:text="${randomNumberUniquePerSession}"></div>

<button m:click="subscribeViaID()">Subscribe to a sessionID update</button>

Server

import io.getmedusa.medusa.core.annotation.UIEventPage;
import io.getmedusa.medusa.core.attributes.Attribute;
import io.getmedusa.medusa.core.bidirectional.ServerToClient;
import io.getmedusa.medusa.core.session.Session;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@UIEventPage(path = "/detail/live-data", file = "/pages/live-data.html")
public class LiveStatisticController {

    private final ServerToClient serverToClient;

    private final List<String> uniqueSessionsIdSubscribedForARandom = new ArrayList<>();

    public LiveStatisticController(ServerToClient serverToClient) {
        this.serverToClient = serverToClient;
    }

    public List<Attribute> setupAttributes(Session session) {
        subscribeViaID(session);

        return List.of(
                new Attribute("randomNumberUniquePerSession", 0)
            );

    }

    public void subscribeViaID(Session session) {
        uniqueSessionsIdSubscribedForARandom.add(session.getId());
    }

    @Scheduled(fixedDelay = 500)
    public void someServerProcess() {
        for(String sessionId : new ArrayList<>(uniqueSessionsIdSubscribedForARandom)) {
            serverToClient.sendAttributesToSessionIDs(
                    List.of(new Attribute("randomNumberUniquePerSession", randomInt())),
                    List.of(sessionId)
            );
        }

        uniqueSessionsIdSubscribedForARandom.clear();
    }

    private int randomInt() {
        return new Random().nextInt(99999);
    }

}

Group Live Data

Finally, we also show that server to client pushes don't have to be all or nothing: You can send updates selectively to groups of users as well.

Unique per group: 0

Client

Unique per group:
<div class="sample-counter" th:text="${randomNumberUniquePerGroup}"></div>

<button m:click="subscribeTag()">Subscribe to tag update</button>

Server

import io.getmedusa.medusa.core.annotation.UIEventPage;
import io.getmedusa.medusa.core.attributes.Attribute;
import io.getmedusa.medusa.core.bidirectional.ServerToClient;
import io.getmedusa.medusa.core.session.Session;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

@UIEventPage(path = "/detail/live-data", file = "/pages/live-data.html")
public class LiveStatisticController {

    private final ServerToClient serverToClient;
    private final List<String> uniqueSessionsTagSubscribed = new ArrayList<>();

    public LiveStatisticController(ServerToClient serverToClient) {
        this.serverToClient = serverToClient;
    }

    public List<Attribute> setupAttributes(Session session) {
        subscribeTag(session);

        return List.of(
                new Attribute("randomNumberUniquePerGroup", 0)
            );
    }

    public void subscribeTag(Session session) {
        session.putTag("uniqueTag", UUID.randomUUID().toString());
        uniqueSessionsTagSubscribed.add(session.getTag("uniqueTag"));
    }

    @Scheduled(fixedDelay = 500)
    public void aServerProcess() {
        for(String subscriberTagValue : new ArrayList<>(uniqueSessionsTagSubscribed)) {
            serverToClient.sendAttributesToSessionTag(
                    List.of(new Attribute("randomNumberUniquePerGroup", randomInt())),
                    "uniqueTag",
                    subscriberTagValue);
        }

        uniqueSessionsTagSubscribed.clear();
    }

    private int randomInt() {
        return new Random().nextInt(99999);
    }

}