Home WebSockets em Jakarta EE
Post
Cancelar

WebSockets em Jakarta EE

Baseado nos cursos da Softblue

WebSockets

• Habilitam a comunicação de duas vias entre o cliente e o servidor

graph TD
    subgraph Tradicional
      A[fa:fa-desktop Cliente] -->|"requisição (HTTP)"| B[fa:fa-server Servidor]
      B -->|"resposta (HTTP)"| A
    end
    subgraph WebSockets
      C[fa:fa-desktop Cliente] <-->|"canal de comunicação (TCP)"| D[fa:fa-server Servidor]
      D <-->|"canal de comunicação (TCP)"| C
    end    

Servidor: Endpoint

• No Java EE, o servidor de um WebSocket é definido com a anotação @ServerEndpoint

• Métodos devem ser anotados e são chamados automaticamente durante o ciclo de vida da sessão do usuário

– @OnOpen

– @OnClose

– @OnError

– @OnMessage

1
2
3
4
5
6
7
8
9
10
11
@ServerEndpoint("/server")//URI
public class MyEndpoint {
  @OnOpen
  public void onOpen(Session session, EndpointConfig conf) { }
  @OnClose
  public void onClose(Session session, CloseReason reason) { }
  @OnError
  public void onError(Session session, Throwable t) { }
  @OnMessage
  public void onMessage(Session session, String message) { }
}

Os métodos podem ter qualquer nome

Existe uma instância do endpoint para cada sessão

Servidor: Enviando Mensagens

• O endpoint se comunica com o cliente através do objeto Session

1
2
3
4
@OnMessage
public void messageReceived(Session session, String message) {
  session.getBasicRemote().sendText("Alguma mensagem");
}

Servidor: Mensagens Binárias

• Além de mensagens de texto, é possível enviar mensagens binárias também

1
2
3
4
5
6
session.getBasicRemote().sendBinary(buffer);//ByteBuffer

@OnMessage
public void bytesMessage(Session session, ByteBuffer buffer) {
  ...
}

Path Parameters

• Permitem o uso de padrões de URI de WebSockets que podem sofrer variação

1
2
3
4
5
6
7
8
9
10
@ServerEndpoint("/server/{some-id}")
public class MyEndpoint {
  ...
}
//ws://localhost:8080/App/server/xyz
@OnOpen
public void open(Session session, EndpointConfig c, 
  @PathParam("some-id") String id) {//O valor xyz é passado como parâmetro
  ...
}

A Anotação @PathParam

• A anotação @PathParam suporta

– Classe String

– Tipos primitivos

– Classes wrappers

• Métodos que suportam o uso da anotação @PathParam

– @OnOpen

– @OnClose

– @OnMessage

Servidor: Encoders & Decoders

• Permitem converter os dados automaticamente quando chegam ou saem do servidor

graph LR
    subgraph .
      A(fa:fa-desktop Cliente) --- B[String]
      B -->|"send()"| C[String] --> D(fa:fa-server Servidor)
      D --> F[String] -->|"send()"| E[String] --- A
    end
    subgraph ..
      G(fa:fa-desktop Cliente) --- H[String]
      H -->|"send()"| I[String]
      subgraph Decoder
        M[ABC]
        N[ABC]
      end
      I --> M --> J(fa:fa-server Servidor)
      J --> N --> L[String] -->|"send()"| K[String] --- G
    end    

Servidor: Decoder

1
2
3
4
5
6
7
8
9
10
public class MessageDecoder implements Decoder.Text<Message> {//tipo customizado
  public void init(EndpointConfig ec) { }
  public void destroy() { }
  public Message decode(String string) throws DecodeException {//Converte para o tipo customizado
    ...
  }
  public boolean willDecode(String string) {
    ...
  }
}

Servidor: Encoder

1
2
3
4
5
6
7
public class MessageEncoder implements Encoder.Text<Message> {//tipo customizado
  public void init(EndpointConfig ec) { }
  public void destroy() { }
  public String encode(Message msg) throws EncodeException {//Converte para String
    ...
  }
}

Servidor: Configurando Encoders & Decoders

• Os encoders e decoders são configurados na anotação @ServerEndpoint

1
2
3
4
5
@ServerEndpoint(
  value = "/server",
  encoders = { MessageEncoder.class },
  decoders = { MessageDecoder.class }
)

• O método que recebe as mensagens deve ter a assinatura correspondente

1
2
3
4
@OnMessage
  public void onMessage(Session session, Message message) {//Quando o método for chamado, o decoder já entrou em áção
    ...
}

• O envio de mensagens é feito através do método sendObject()

1
2
3
Message msg = new Message();
...
session.getBasicRemote().sendObject(msg);

Servidor: Informações de Usuário

• Uma sessão pode armazenar informações específicas do usuário

1
2
3
session.getUserProperties().put("nome", "João");//Map<String, Object>

String nome = (String) session.getUserProperties().get("nome");

Cliente: JavaScript API

• Aplicações web podem usar a API do JavaScript de cliente de WebSocket

– Navegadores modernos com suporte à HTML5

1
2
3
4
5
6
7
8
9
10
var websocket = new WebSocket("ws://localhost:8080/app/server");//Inicia a conexão
websocket.onopen = function(event) {//Conexão estabelecida
  ...
};
websocket.onmessage = function(event) {//Mensagem recebida
  ...
};
websocket.onerror = function(event) {//Ocorreu um erro
  ...
};

Cliente: Enviando Mensagens

• O cliente pode enviar uma mensagem ao servidor

1
websocket.send("Minha mensagem");
Esta postagem está licenciada sob CC BY 4.0 pelo autor.