Notificar somente usuários específicos através do WebSockets, quando algo for modificado no banco de dados
Para notificar todos os usuários através do WebSockets, quando algo é modificado em entidades JPA selecionadas, eu uso a seguinte abordagem básica.
@ServerEndpoint("/Push")
public class Push {
private static final Set<Session> sessions = new LinkedHashSet<Session>();
@OnOpen
public void onOpen(Session session) {
sessions.add(session);
}
@OnClose
public void onClose(Session session) {
sessions.remove(session);
}
private static JsonObject createJsonMessage(String message) {
return JsonProvider.provider().createObjectBuilder().add("jsonMessage", message).build();
}
public static void sendAll(String text) {
synchronized (sessions) {
String message = createJsonMessage(text).toString();
for (Session session : sessions) {
if (session.isOpen()) {
session.getAsyncRemote().sendText(message);
}
}
}
}
}
Quando uma entidade JPA selecionada é modificada, é gerado um evento CDI apropriado que deve ser observado pelo observador CDI a seguir.
@Typed
public final class EventObserver {
private EventObserver() {}
public void onEntityChange(@Observes EntityChangeEvent event) {
Push.sendAll("updateModel");
}
}
O observador / consumidor chama o método estáticoPush#sendAll()
definido no terminal WebSockets que envia uma mensagem JSON como uma notificação para todos os usuários / conexões associados.
A lógica dentro dosendAll()
O método precisa ser modificado de alguma forma, quando apenas usuários selecionados devem ser notificados.
Quando um aperto de mão inicial é estabelecido,HttpSession
pode ser acessado como indicado emesta resposta, mas ainda é insuficiente para realizar as tarefas mencionadas acima por duas marcações. Como está disponível quando a primeira solicitação de handshake é feita, qualquer atributo configurado para essa sessão posteriormente não estará disponível no terminal do servidor, ou seja, em outras palavras, qualquer atributo de sessão definido após o estabelecimento de um handshake não estará disponível.
Qual é a maneira mais aceitável / canônica de notificar apenas usuários selecionados, como mencionado acima? Algumas declarações condicionais nosendAll()
método ou qualquer outra coisa em algum lugar é necessário. Parece que ele tem que fazer algo diferente do que apenas o usuárioHttpSession
.
Eu uso o GlassFish Server 4.1 / Java EE 7.