Conheça o Tyrus - sua implementação para WebSocket com backend em Node e Java

Conheça o Tyrus - sua implementação para WebSocket com backend em Node e Java
lacerdaph
lacerdaph

Compartilhe

Aqui na Caelum, adoramos destrinchar as tecnologias novas que entram na especificação da plataforma Java. No JavaEE 6, lançado em 10/12/2009, falamos muito sobre CDI, e talvez tenha sido a especificação mais proeminente da tecnologia. Ano passado (12/06/2013), foi lançado o JavaEE 7, e já começamos a discorrer sobre algumas melhorias que entraram na especificação, como o JMS 2.0 por exemplo.

O objetivo deste artigo é estudar um pouco mais a API de WebSocket. Já discutimos a especificação anteriormente, então a ideia aqui é tentar aprofundar um pouco mais. Talvez essa seja uma API tão discutida quanto foi o CDI,e ela nos faz rever alguns conceitos sobre REST também. Além disso, vários frameworks já estão suportando e sugerindo melhorias à especificação.

Para implementar o servidor vamos usar duas tecnologias: NodeJS e JavaEE 7 (GlassFish 4.0).

Server side - NODE

Node é uma implementação que permite executar JavaScript no lado do servidor. Ele utiliza um modelo orientado a eventos assíncrono. Possui vantagens em relação a um servidor Java e foram discutidas na revista MundoJ. Para trabalhar com WebSocket em NodeJS, existem várias implementações como Socket.IO e Socket.JS. Neste artigo vamos utilizar a segunda.

 var http = require('http'); var sockjs = require('sockjs'); var clients = {};

var sockjs\_echo = sockjs.createServer();

function broadcast (message, exclude) { console.log("mensagem a ser enviada: "+ message); for ( var i in clients ) { if ( i != exclude ) { console.log("Cliente selecionado para enviar mensagem"+ clients\[i\]); clients\[i\].write( message ); }

} }

sockjs\_echo.on('connection', function(conn) { //guarda cliente conectado clients```conn.id
 = conn;

//Quando receber uma mensagem, faz o broadcast conn.on('data', function(data) { broadcast(data); }); });

//criando um servidor http para ouvir o serviço var server = http.createServer();

//criando o canal de comunição websocket caelum sockjs\_echo.installHandlers(server, {prefix:'/caelum'});

server.listen(8082, '127.0.0.1'); 

Para executar esse código você precisa estar com o Node e o SocketJS instalado. Depois é só executar no terminal o comando: node .js

Server side - JavaEE (Glassfish 4.0)

Em Java, você deve criar um projeto JavaEE e ter o GlassFish 4.0 instalado.

O código é bem simples e auto-explicativo, basta utilizar anotações com @ServerEndpoint e anotações de callback como @OnMessage, @OnOpen.

 @ServerEndpoint("/caelum") public class CaelumServer { @OnOpen public void onOpen(Session cliente) { System.out.println("Novo cliente" + cliente); }

@OnClose public void onClose(Session cliente) { System.out.println("Cliente desconectado" + cliente); }

@OnMessage public void message(String message, Session client) throws IOException {

Set<Session> openSessions = client.getOpenSessions(); for (Session session : openSessions) { session.getBasicRemote().sendText(message); } } } 

O lado do servidor está pronto, temos o mesmo serviço WebSocket implementado por duas tecnologia diferentes e podendo ser acessado por um cliente JavaScript ou Java.

Conheça o Tyrus

O Projeto Tyrus é a implementação referência para a API de WebSocket. Assim como o Weld, o projeto possui implementações que podem ser utilizadas para um servlet container ou standalone.

Vamos implementar um cliente Tyrus para acessar os dois serviços que criamos. Para isso, crie um projeto maven e coloque a seguinte dependência.

 <dependency> <groupId>org.glassfish.tyrus.bundles</groupId> <artifactId>tyrus-standalone-client</artifactId> <version>1.4</version> </dependency> 

Vamos criar duas classes de Cliente. A primeira apenas recebe a mensagem, já a segunda envia e recebe também. Para isso basta utilizarmos a anotação @ClientEndPoint.

 @ClientEndpoint public class ChatClientReceiver { @OnOpen public void onOpen(Session session) { System.out.println("Client Receiver conectado: " + session); }

@OnMessage public void processMessage(String message) { System.out.println("Recebendo no Client Receiver: " + message); } }

@ClientEndpoint public class ChatClientSender { @OnOpen public void onOpen(Session session) { try { System.out.println("Client Sender conectado: " + session); session.getBasicRemote().sendText("Mensagem Enviada Via WebSocket"); } catch (IOException e) { e.printStackTrace(); } }

@OnMessage public void processMessage(String message) { System.out.println("Recebendo no Client Sender: "+ message); } } 

Agora vamos criar uma classe que usa a API do Tyrus para acionar os clientes

 public class TestClient { public static void main(String\[\] args) { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); String uri = "ws://127.0.0.1:8082/caelum/websocket"; // String uri = "ws://127.0.0.1:8080/WebSocket/caelum"; try { container.connectToServer(ChatClientReceiver.class, URI.create(uri)); Thread.sleep(5000); container.connectToServer(ChatClientSender.class, URI.create(uri)); } catch (DeploymentException | IOException | InterruptedException e) { e.printStackTrace(); } } } 

O código é bem simples, a única peculiaridade é que a primeira URI acessa o WebSocket Node.JS, já a segunda o Java. O sleep na Thread é só para dar um tempo e termos certeza que o primeiro CaelumClientReceiver conectou-se ao serviço.

Concluindo, um dos artigos mais legais que eu já li e que me motivou a fazer parte da equipe Caelum foi como montar um serviço JAX-WS sem servidor de aplicação, a ideia aqui é mostrar que com WebSocket também podemos fazer o mesmo. Também é importante salientar a integração entre tecnologias diferentes. No exemplo, trocamos uma simples mensagem, mas nada impediria de ser um JSON.

Veja outros artigos sobre Inovação & Gestão