DEV Community

aristides villarreal
aristides villarreal

Posted on • Edited on

Jakarta WebSocket enviando mensajes

Enviar mensajes a todos los usuarios

Para utilizar WebSocket en nuestras aplicaciones Jakarta EE, seguimos los siguientes pasos:

  • Configurar el archivo web.xml

<context-param>
 <param-name>jakarta.faces.ENABLE_CDI_RESOLVER_CHAIN</param-name>
     <param-value>true</param-value>
</context-param>
<context-param>
 <param-name>jakarta.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name>
   <param-value>true</param-value>
</context-param> 
Enter fullscreen mode Exit fullscreen mode

En el archivo template.xhtml
Image description

agregar dos commandButton

<p:commandButton id="sendMessageAll" 
 action="#{webSocketDomain.sendMessageAll('all','user')}" 
 value="sendMessageUserAll">
  <f:ajax />
</p:commandButton>

<p:commandButton id="sendMessageProyecto" 
action="#{webSocketDomain.sendMessageProyecto('proyecto ',loginFaces.userLogged)}" value="sendMessageProyecto">
 <f:ajax />
</p:commandButton>

Enter fullscreen mode Exit fullscreen mode

El primero se usará para enviar un mensaje a todos los usuarios y el segundo para enviar un mensaje a un usuario en específico.

Image description

Al presionar el primer botón todos los usuarios recibirán un mensaje como el siguiente

Image description

Cree la interface

public interface WebSocketPlantilla {

    public void sendMessageAll(String message, String scoped);

    public void sendMessageProyecto(String message, User user);

    public void sendMessageProyectoMultiple(String message, List<User> userList);

    public void sendMessageSprint(String message, User user);


    public void sendMessageSprintMultiple(String message, List<User> userList) ;

    public void sendMessageTablero(String message, User user);

    public void sendMessageTableroMultiple(String message, List<User> userList);

    public Collection<Long> collectionOfUserList(List<User> userList);
}


Enter fullscreen mode Exit fullscreen mode

Ahora es necesario crear una clase que denominaremos a modo de ejemplo como WebSocketController.
En esta clase utilizaremos PushContext para enviar los mensajes mediante WebSocket.

@ViewScoped
@Named
public class WebSocketController implements Serializable, WebSocketPlantilla {

    @Inject
    @Push
    private PushContext proyectoChannel;

    @Inject
    @Push
    private PushContext sprintChannel;

    @Inject
    @Push
    private PushContext tableroChannel;

    @Inject
    @Push
    PushContext allChannel;

    /**
     *
     * @param message
     * @param user
     */
    @Override
    public void sendMessageProyecto(String message, User user) {
        proyectoChannel.send(message, user.getIduser());

    }

    /**
     * *
     * Envia mensaje a muchos usuarios
     *
     * @param message
     * @param userList
     */
    @Override
    public void sendMessageProyectoMultiple(String message, List<User> userList) {
        proyectoChannel.send(message, collectionOfUserList(userList));
    }

    /**
     *
     * @param message
     * @param user
     */
    @Override
    public void sendMessageSprint(String message, User user) {
        sprintChannel.send(message, user.getIduser());

    }

    /**
     * *
     * Envia mensaje a muchos usuarios
     *
     * @param message
     * @param userList
     */
    @Override
    public void sendMessageSprintMultiple(String message, List<User> userList) {

        sprintChannel.send(message, collectionOfUserList(userList));
    }

    /**
     *
     * @param message
     * @param user
     */
    @Override
    public void sendMessageTablero(String message, User user) {

        tableroChannel.send(message, user.getIduser());

    }

    /**
     * *
     * Envia mensaje a muchos usuarios
     *
     * @param message
     * @param userList
     */
    @Override
    public void sendMessageTableroMultiple(String message, List<User> userList) {

        tableroChannel.send(message, collectionOfUserList(userList));
    }

    @Override
    public void sendMessageAll(String message, String scoped) {
       allChannel.send(message, "user");
    }

    @Override
    public Collection<Long> collectionOfUserList(List<User> userList) {
        Collection<Long> result = new ArrayList<>();
        try {
            userList.forEach(u -> {
                result.add(u.getIduser());
            });
        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return result;
    }

}

Enter fullscreen mode Exit fullscreen mode

En el archivo template.xhtml añada

 <script>
            function handleMessageAllChannel(message, channelName, event) {
                alert('[handleMessageAllUser]: ' + message );

                remoteCommandWebSocketAll();

            }
            function handleMessageProyectoChannel(message, channelName, event) {
                alert('[handleMessageProyecto]: ' + message);


            }

</script>

Enter fullscreen mode Exit fullscreen mode

Añada un f:websocket para escuchar en el canal allChannel y un p:remoteCommnad para invocar métodos al recibir la notificación.

Observe que se utiliza user="user".

  <f:websocket channel="allChannel"  user="user" onmessage="handleMessageAllChannel" />

 <p:remoteCommand name="remoteCommandWebSocketAll" action="#{loginFaces.webSocketListenerMethod}" 
                                 update="template_growl_timesession" />
Enter fullscreen mode Exit fullscreen mode

En la clase LoginFaces añada

 // <editor-fold defaultstate="collapsed" desc="String websocketListenerMethod()">
    public String webSocketListenerMethod() {
        try {

            FacesUtil.successMessage("desde el websocket");

        } catch (Exception e) {
            FacesUtil.errorMessage(FacesUtil.nameOfClassAndMethod() + " " + e.getLocalizedMessage());
        }
        return "";
    }

Enter fullscreen mode Exit fullscreen mode

Que enviara un mensaje mediante un p:growl de Primefaces

Image description

Enviar un mensaje a un usuario específico

Edite otra pagina que se habilite luego de autentificarse en el sistema, en este ejemplo: dashboard.xhtml

Image description

Añada un websocket, observe que se usa el canal proyectoChannel y el usuario que ingreso al sistema que se almacena en loginFaces.userLogged.iduser.

<f:websocket channel="proyectoChannel" user="#{loginFaces.userLogged.iduser}" onmessage="handleMessageProyectoChannel"/>                
Enter fullscreen mode Exit fullscreen mode

De esta manera se envía una notificación solo al usuario especificado en el parámetro user.

Image description

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

AWS GenAI Live!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️