Java - Play2 - нужны ли актеры для внедрения WebSockets?

Я пытаюсь реализовать решение на базе WebSockets с Play2 и Java. В настоящее время я не использую Модель актера для управления concurrency. Вместо этого он просто обрабатывает WebSockets с помощью обратных вызовов.

Проблема заключается в том, что сервер не может "транслировать" сообщения через несколько клиентов. Например, мне нужно, чтобы все активные сеансы браузера получили простое уведомление после того, как действие было инициировано через клиента. Вместо этого я просто смогу имитировать это для одного сеанса клиента. По сути, он просто действует как обычный сценарий запроса/ответа Ajax.

Я предполагаю, что решение WebSockets с Play2 и Java с простыми обратными вызовами не может передавать сообщения всем подключенным клиентским браузерам.

Код сервера обратного вызова

public static WebSocket<String> heartUpdate() {
        return new WebSocket<String>() {
            public void onReady(final WebSocket.In<String> in,
                    WebSocket.Out<String> out) {
                in.onMessage(new Callback<String>() {
                    @Override
                    public void invoke(String event) throws Throwable {
                        Product product = Product.find.byId(Long.decode(event));
                        // Other business stuff
                        out.write(entity.id + " " + decimalValue);
                    }
                });
                in.onClose(new Callback0() {
                    @Override
                    public void invoke() throws Throwable {

                    }
                });
                out.write(DELIM_USERID_REP);
            }
        };
    }

Запись маршрутов

GET /repsocket   controllers.Application.heartUpdate

Клиентская сторона

<script>
    // Onto the WebSockets now
    var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket;
    var socket = new WS("@routes.Application.heartUpdate.webSocketURL(request)");

    var receiveEvent = function(event) {
        alert(event.data);
        // Notification badge visible with a common text
        $('#notify').text(event.data);
        $('#notify').addClass('visible');
    }
        $('#heart').click(function(e) {
            e.preventDefault();
            socket.send(@product.id);
        });
    socket.onmessage = receiveEvent;
    </script>

В приведенном выше случае клиент запускает действие, которое успешно получает сообщение с сервера, в то время как другие сеансы браузера не работают.

Мне не удалось найти документацию, совместимую с Play2 с Java и WebSockets, которая предполагает обязательное использование Актеров для поддержания согласованной связи со всеми подключенными активными клиентами.

Вопрос: Должны ли WebSockets в Play2 с Java быть реализованы с помощью модели Actor для трансляции сообщения на все активные сеансы клиента?

Edit: Снимок экрана ниже отражает 2 состояния браузеров, к которым я вошел, чтобы использовать 2 действительных учетных данных пользователя.

В идеале ответ WebSockets от сервера должен создавать одинаковые значки уведомлений в обоих браузерах.

введите описание изображения здесь

Ответ 1

Посмотрев на код, который вы опубликовали, кажется, что проблема заключается в том, что вы не сохраняете ссылку на каждое соединение, поэтому вы можете позже передавать сообщения. Что-то вроде этого:

// Just an example: does not deal with concurrency problems
private static final Set<WebSocket.Out<String>> SOCKETS = new HashSet<>();

public static WebSocket<String> heartUpdate() {
    return new WebSocket<String>() {
        public void onReady(final WebSocket.In<String> in,
                    final WebSocket.Out<String> out) {
            SOCKETS.add(out);
            in.onMessage(new Callback<String>() {
                @Override
                public void invoke(String event) throws Throwable {
                    for(WebSocket.Out<String> s: SOCKETS) {
                        s.write("SOME MESSAGE");    
                    }
                }
            });
            in.onClose(new Callback0() {
                @Override
                public void invoke() throws Throwable {
                    SOCKETS.remove(out);
                }
            });
        }
    };
}

Вы также можете использовать актеров для моделирования этой проблемы: наличие актера, ответственного за отслеживание соединений и связь с новым подключением/закрытием сокетов.

Если вы хотите использовать Akka, несколько шаблонов активаторов, чтобы начать работу.