Pesquisar este blog

sábado, 8 de novembro de 2014

Acessando o Twitter Stream via PlayFramework

Introdução

Atualmente existem diversas ferramentas que distribuem conteúdos via streaming, o Twitter é uma delas. 
Streaming é um tipo de transmissão de dados onde o tamanho dos dados a serem transmitidos não é conhecido, e em alguns casos ele é contínuo.
Ao desenvolver um sistema de webservice rest, como mostrado aqui e aqui, as respostas as chamadas dos webservices contém um parâmetro chamado Content-Length definido no header da resposta. Este parâmetro define o tamanho do conteúdo daquela resposta. 
Isso não é feito explicitamente, como foi mostrado nos posts, mas o framework de MVC faz a inclusão deste parâmetro automaticamente.
Esta definição funciona muito bem nos casos onde sabe-se o tamanho exato da resposta, porém como deve-se lidar com casos em que você não sabe o tamanho da resposta? 
Uma das formas de se resolver este problema é usar uma resposta fragmentada (Chunked responses).

Resposta Fragmentada (Chunked response)

A grande vantagem deste tipo de resposta é que pode-se disponibilizar um conteúdo para o cliente, assim que ele fica disponível ao servidor de web. Uma desvantagem a ser citada é que não é possível calcular quanto daquela mensagem já foi carregada, uma vez que não se sabe o tamanho total dela.
O modo mais fácil de utilizar este tipo de resposta no playframework, no caso de haver um inputstream dinâmico é:
public static Result indice() {
  InputStream is = getInputStreamDinamico();
  return ok(is);
}
Uma instância de um InputStream pode ser utilizado como resposta a uma chamada, conforme realizado pelo ok(is).
A outra maneira de usar as respostas fragmentadas é implementar um builder de respostas fragmentadas.

public static indice() {
  // Prepare um stream de texto fragmentado
  Chunks<String> chunks = new StringChunks() {
    
    // Chamado quando o stream estiver pronto
    public void onReady(Chunks.Out<String> out) {
      metodoRegistroOut(out);
    }
    
  }
  
  // Serve este stream como um HTTP 200 OK
  ok(chunks);
}
public void metodoRegistroOut(Chunks.Out<String> out) {   out.write("Olá");                                    out.write("dsd");                             out.write("mensagem");                                              out.close();
} 
Neste caso cria-se um chunk, tipado como String usando o java Generics, este chunk tem um método onReady que é chamado assim que o stream estiver pronto para ser utilizado, no exemplo acima este método irá registrar a saída (out) em um outro método que irá enviar algumas mensagens para o cliente como resposta.

Sockets Comet

Os comets são uma outra forma de se particionar as mensagens enviadas aos clientes. Os sockets comet são mensagens chunks de texto html que contem apenas elementos <script>. Em cada parte da mensagem será enviado ao cliente um elemento <script> que ao ser executado pelo browser pode chamar uma função javascript e com isso conseguimos enviar eventos ao vivo para os clientes.
A criação de comets é bem simples, como mostrado abaixo:
public static Result index() {
  // Prepara a stream de uma resposta particionada
  Chunks<String> chunks = new StringChunks() {
    
    // Método chamado assim que a resposta particionada estiver        // pronta
    public void onReady(Chunks.Out<String> out) {
      out.write("<script>console.log('Olá')</script>");
      out.write("<script>console.log('dsd')</script>");
      out.write("<script>console.log('mensagem')</script>");
      out.close();
    }
    
  }
  
  response().setContentType("text/html");
  
  ok(chunks);
}
Até agora nada muito diferente do que já havia sido exposto na seção de mensagens particionadas, a não ser pelas tags <scripts> nas respostas enviadas.
A grande vantagem de enviar scripts é poder iteragir e executar operações no cliente em forma de javascript. Coisas como alterar a cor do fundo da tela, criar um botão, realizar chamadas a serviços de dados, ou qualquer lógica que o desenvolvedor ache necessário.

Biblioteca play.libs.Comet

Esta biblioteca server para ajudar no envio de mensagens do tipo comet aos clientes:
public static Result indice() {
  Comet comet = new Comet("console.log") {
    public void onConnected() {
      sendMessage("Olá");
      sendMessage("dsd");
      sendMessage("mensagem");
      close();
    }
  };
  
  ok(comet);
}
O código acima faz as mesmas operações realizadas pelo código mostrado na seção de comet, a grande diferença é que com ela podemos mandar mensagens tanto strings, quanto objetos em JSON.

Nenhum comentário:

Postar um comentário