Estás viendo una versión antigua de esta página. Ve a la versión actual.

Comparar con el actual Ver el historial de la página

« Anterior Versión 8 Siguiente »

EN CONSTTRUCCIÓN ...

<fw:socket> es un componente UI que abre una conexión push basada en websocket unidireccional (de servidor a cliente) en el lado del cliente a la que se puede acceder desde el lado del servidor a través de la interfaz PushContext inyectada mediante la anotación @Push.

Configuración

Primero hay que activar los websockets mediante el siguiente parámetro de contexto booleano en web.xml:

<context-param>
    <param-name>es.um.atica.fundeweb.SOCKET_ENDPOINT_ENABLED</param-name>
    <param-value>true</param-value>
</context-param>

Lo que registrara un SocketEndpoint en el servidor.


Utilización en el Cliente

Declare la etiqueta <fw:socket> en la vista (página) con al menos un nombre de canal (channel) y una función JavaScript llamada onmessage. El nombre del canal no puede ser una expresión EL y solo puede contener caracteres alfanuméricos, guiones, guiones bajos y puntos. Aquí hay un ejemplo que hace referencia a una función de escucha de JavaScript existente (¡no incluya los paréntesis!).

<fw:socket channel="someChannel" onmessage="socketListener" />
function socketListener(message, channel, event) {
    console.log(message);
}

También se puede añadir la función JavaScript en el propio componente:

<fw:socket channel="someChannel" onmessage="function(message) { console.log(message); }" />

La función JavaScript onmessage, se invocará con tres argumentos:

  • menssage: el mensaje push como objeto JSON.
  • channel: el nombre del canal, útil en caso de que pretenda tener un oyente global o desee controlar manualmente el cierre.
  • event: la instancia sin procesar de MessageEvent, útil en caso de que desee inspeccionarla.


En caso de que su servidor esté configurado para ejecutar el contenedor WS en un puerto TCP diferente al contenedor HTTP, puede usar el atributo de puerto opcional para especificar explícitamente el puerto.

<fw:socket port="8000" ... />


Cuando se conecta correctamente, el websocket está abierto de forma predeterminada siempre que el documento esté abierto, y se volverá a conectar automáticamente a intervalos cada vez mayores cuando la conexión se cierre o se cancele como resultado de, por ejemplo, un error. un error de red o reinicio del servidor. No se volverá a conectar automáticamente cuando el primer intento de conexión ya falle. El websocket se cerrará implícitamente una vez que se descargue el documento (por ejemplo, al navegar, cerrar la ventana/pestaña del navegador, etc.). Para volver a conectarse con éxito después de reiniciar el servidor o al cambiar a un nuevo nodo de servidor, debe asegurarse de que la persistencia de la sesión esté habilitada en el servidor.


Utilización en el Servidor

En el backend, se puede inyectar una instancia de PushContext a través de la anotación @Push, junto con el nombre del canal en cualquier componente Seam, donde se necesite enviar un mensaje push. Para enviar el mensaje, se invoca al método PushContext.send(Object) con cualquier objeto Java que represente el mensaje.

@Push
private PushContext someChannel;

public void sendMessage(Object message) {
    someChannel.send(message);
}


Por defecto, el nombre del canal se toma del nombre de la variable en la que se realiza la inyección. También se puede especificar opcionalmente mediante el atributo channel de la anotación @Push. El siguiente ejemplo se inyecta el contexto push del canal foo en la variable bar.

@Push(channel="foo")
private PushContext bar;


El mensaje se codificará como JSON y se entregará como parámetro a la función JavaScript onmessage asociada con el nombre del canal. Puede ser cualquier objeto, desde un String a colección o un mapa e incluso un POJO (JAVABEAN). Para conocer los tipos de parámetros admitidos (y descendientes) por Json.encode(Object) son: Boolean, Number, CharSequence, Date, Enum, Temporal, Collections, Map; Si el tipo de objeto no coincide con ninguno de ellos, entonces se inspeccionara el objeto como un POJO (JAVABEAN), donde las propiedades públicas (con getter público) se codificarán como un objeto JS. Los objetos de las clases Date y Temporal, cumples el estándar RFC 1123, por lo que, si es necesario, puedes usar new Date() en JavaScript.

Aunque los websockets admiten la comunicación bidireccional, el envío de <fw:socket> está diseñado para la comunicación unidireccional, de servidor a cliente. En caso de que desee enviar datos de cliente a servidor, contina realizando peticiones Faces AJAX como se hace de manera habitual. Si es necesario hacerlo desde JavaScript, puedes usar <p:remoteCommand>. De esa forma se mantiene el estado de vista de Faces, la sesión HTTP y, lo que es más importante, todas las restricciones de seguridad especificada para los servicios. Es decir, esas restricciones de seguridad no están disponibles durante un mensaje de websockets. Véase también. WS spec issue 238.


Ámbitos (Scopes) y Usuarios

Por defecto, los websockets tienen ámbito aplicación (application scope), es decir,  cualquier vista/sesión de la aplicación web, teniendo el mismo canal websocket abierto, recibirá el mismo mensaje push. El mensaje push puede ser enviado por cualquier usuario o por la propia aplicación. Está característica es útil para recibir notificaciones globales a nivel de aplicación lanzados por ella y que permiten actualizar una página concreta de esta, ejemplo: estadísticas del sitio web, listas top100, actualización de stock, etc.


El atributo opcional scope puede establecerse con el valor session, para restringir los mensajes push a todas las vistas de la sesión actual del usuario. El mensaje solo puede ser enviado por el usuario y no por la aplicación. Está característica es útil para recibir notificaciones a nivel de sesión sobre vistas lanzadas por el mismo usuario, ejemplo: el resultado de una tarea asíncrona lanzada por una acción del usuario).

<fw:socket channel="someChannel" scope="session" ... />


El atributo opcional scope puede establecerse con el valor session, para restringir los mensajes push sólo a la vista actual. Los mensajee push no son vistos por otras vistas en la misma sesión, incluso si son la misma URL. El mensaje solo puede ser enviado por el usuario y no por la aplicación. Está característica es útil para recibir notificaciones a nivel de vista (página) lanzadas por el mismo usuario, ejemplo: una barra de progreso sobre una acción especifica en la vista (página) actual).

<fw:socket channel="someChannel" scope="view" ... />


Los valores permitidos en el atributo scope son: application, session y view; (en minúsculas) y NO se permiten expresiones EL.


Además, el atributo opcional user puede establecerse con un identificador único, que hace referencia al usuario autenticado. Pude ser el nombre del usuario o un ID calculado. De esta forma, un mensaje push puede ser enviado a un usuario especifico y puede ser enviado por cualquier usuario o por la propia aplicación.  El valor el atributo user tiene que implementar la interface Serializable y debe gastar poca memoria, por lo que la entidad que representa al usuario como la clase org.umu.atica.servicios.gesper.gente.entity.Persona o org.jboss.seam.security.Identity (y descendientes) no son recomendables. Podemos generar identificadores únicos mediante la clase java.util.UUID. Ejemplo de uso con el username:

<fw:socket channel="someChannel" user="#{credentials.username}" ... />


Cuando especificamos el atributo user  el ámbito por defecto se establece en session y no se puede establecer en application. Puede establecerse con view, pero es inusual y solo debe utilizarse si el usuario autenticado representado por el valor user, tiene un ciclo de vida más corto que la sesión HTTP, ejemplo: cuando la aplicación permite cambiar entre usuarios autenticados durante la misma sesión HTTP sin invalidar al anterior usuario, que es un muy mala práctica de seguridad. Si en el caso, de reutilizar un socket de ámbito sesión, se pueden producir comportamientos indeseados cuando se envía un mensaje push dirigido a un usuario determinado. Este puede ser enviado a un usuario anterior. Este problema se resuelve estableciendo el ámbito a view, recomendando realizar una invalidación de la sesión HTTP del usuario.


Cuando el atributo user es establecido mediante una expresión EL, y este cambia durante un petición AJAX, entonces el usuario del socket también se actualizará, incluso si ninguna petición AJAX cubre la definición del <fw:socket>. Hay  que asegurarse de que el valor esta ligado al menos a una propiedad de la vista en caso de querer controlarlo durante el ámbito de la vista.

En el lado del servidor, el mensaje push puede ser dirigido al usuario especificado en el atributo user mediante PushContext.send(Object, Serializable). El mensaje push puede ser enviado por todos los usuarios o por la propia aplicación. Es útil para notificar a un usuario determinado por otros usuarios, por ejemplo: chat, mensajes por parte del administrador, etc.; o por tareas en segundo plano de la aplicación como por ejemplo: notificaciones, listeners, etc..

@Push
private PushContext someChannel;

public void sendMessage(Object message, User recipientUser) {
    Long recipientUserId = recipientUser.getId();
    someChannel.send(message, recipientUserId);
}














  • Sin etiquetas