12
respostas

Promoção relâmpago não está sendo enviada

Eu estava fazendo a aula "Integrando a tela de promoções com Websocket" mas não estou recebendo a janela com a promoção depois que eu envio, seguem as classes: No index.xhtml:

<script>
    var canalDePromos = new WebSocket("ws://localhost:8080/#{request.contextPath}/canal/promos");
    canalDePromos.onmessage = function(message) {
        var novaPromo = JSON.parse(message.data);
        if(confirm("Que tal aproveitar a promoção relâmpago " 
                + novaPromo.titulo)) {
            document.location.href=
                "#{request.contextPath}/livro-detalhe.xhtml?id=" + novaPromo.livroId;
        }
    };
</script>

PromosEndPoint.java:

package br.com.casadocodigo.loja.websockets;

import java.io.IOException;
import java.util.List;

import javax.inject.Inject;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import br.com.casadocodigo.loja.models.Promo;

@ServerEndpoint(value = "/canal/promos")
public class PromosEndpoint {

    @Inject
    private UsuariosSession usuarios;

    @OnOpen
    public void onMessage(Session session) {
        usuarios.add(session);
    }

    public void send(Promo promo) {
        List<Session> sessions = usuarios.getUsuarios();

        for (Session session : sessions) {
            if(session.isOpen()) {
                try {
                    session.getBasicRemote().sendText(promo.toJson());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        usuarios.remove(session);
        System.out.println(closeReason.getCloseCode());
    }
}

UsuariosSession.java:

package br.com.casadocodigo.loja.websockets;

import java.util.ArrayList;
import java.util.List;

import javax.enterprise.context.ApplicationScoped;
import javax.websocket.Session;

@ApplicationScoped
public class UsuariosSession {

    private List<Session> sessions = new ArrayList<>();

    public void add(Session session) {
        sessions.add(session);
    }

    public List<Session> getUsuarios() {
        return sessions;
    }

    public void remove(Session session) {
        sessions.remove(session);
    }
}

Promo.java

package br.com.casadocodigo.loja.models;

import javax.json.Json;
import javax.json.JsonObjectBuilder;

public class Promo {

    private String titulo;
    private Livro livro = new Livro();

    public String toJson() {
        JsonObjectBuilder promo = Json.createObjectBuilder();
        promo.add("titulo", titulo)
            .add("livroId", livro.getId());

        return promo.build().toString();
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public Livro getLivro() {
        return livro;
    }

    public void setLivro(Livro livro) {
        this.livro = livro;
    }
}

AdminPromosBean.java

package br.com.casadocodigo.loja.beans;

import javax.enterprise.inject.Model;
import javax.inject.Inject;

import br.com.casadocodigo.loja.models.Promo;
import br.com.casadocodigo.loja.websockets.PromosEndpoint;

@Model
public class AdminPromosBean {

    private Promo promo = new Promo();

    @Inject
    private PromosEndpoint promos;

    public void enviar() {
        promos.send(promo);        
    }

    public Promo getPromo() {
        return promo;
    }

    public void setPromo(Promo promo) {
        this.promo = promo;
    }
}

promos.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

<ui:composition template="/templates/_admin_template.xhtml">

    <ui:param name="promos" value="active" />

    <ui:define name="body">

        <h1>Enviar Promoção Relâmpago</h1>

        <h:form enctype="multipart/form-data">

            <div class="form-group">
                <h:outputLabel value="Título da Promoção" />
                <h:inputText value="#{adminPromosBean.promo.titulo}"
                    required="true" id="titulo" styleClass="form-control" />
                <h:message for="titulo" />    
            </div>

            <div class="form-group">
                <h:outputLabel value="Livros" for="livros" />
                <h:selectOneMenu value="#{adminPromosBean.promo.livro.id}"
                    converter="javax.faces.Integer" id="livros" styleClass="form-control">
                    <f:selectItems value="#{adminListaLivrosBean.livros}" var="livro"
                        itemValue="#{livro.id}" itemLabel="#{livro.titulo}" />
                </h:selectOneMenu>
                <h:message for="livros" />
            </div>

            <h:commandButton value="Enviar Promoção" action="#{adminPromosBean.enviar}"
                styleClass="btn btn-primary" />

        </h:form>

    </ui:define>

</ui:composition>
</html>
12 respostas

Oi Marcos,

Peço desculpas, mas por um motivo deixamos a sua mensagem aberta. De qq forma, vc conseguiu resolver o problema?

abs

Ola Nicco. Não, ainda não consegui resolver.

Oi Marcos,

vou fazer algumas perguntas para tentar achar a causa do problema:

1) Vc consegue enviar uma promoção? quero dizer, ao enviar um "promoção relampago" é chamado o método send na classe PromosEndpoint? (teste isso com um syso)

2) Ao chamar a página com o JavaScript do WebSocket é chamado no servidor o método onMessage da classe PromosEndpoint? (teste isso com um syso)

3) Se 1 e 2 estão funcionando, verifique se a função JavaScript está sendo chamado para receber a promoção,aquele function(message) { ...}. Dentro da função coloque um console.log(message); .

abs, Nico

Nicco,

Ele está entrando no método send da classe PromosEndPoint, mas não está passando na verificação do

if(session.isOpen()) {

E não está entrando no método onMessage

Aparentemente o login está funcionando normalmente, pois quando logo como admin aparece no index.xhtml a barra de navegação Administração que só aparece quando eu logo como admin.

entendi, ele tbm passa pelo método:

@OnOpen
    public void onMessage(Session session) {
        usuarios.add(session);
    }

?

abs, Nico

Não entrou no método onMessage

Seria nesse ponto que ele chama o método e adiciona o usuário a sessão correto?

<script>
    var canalDePromos = new WebSocket("ws://localhost:8080/#{request.contextPath}/canal/promos");
    canalDePromos.onmessage = function(message) {
        var novaPromo = JSON.parse(message.data);
        if(confirm("Que tal aproveitar a promoção relâmpago " 
                + novaPromo.titulo)) {
            document.location.href=
                "#{request.contextPath}/livro-detalhe.xhtml?id=" + novaPromo.livroId;
        }
    };
</script>

Tem algo de errado no código?

Oi Marcos,

Vamos simplifica o codigo JavaScript e tbm tirar esse #{request.contextPath}, tente algo assim:

<script type="text/javascript">
const canal = new WebSocket('ws://localhost:8080/AQUI_O_NOME_DA_APP/canal/promos');

canal.addEventListener('message', function (message) {
    console.log('Mensagem ', message.data);
});
</script>

Só substitua o AQUI_O_NOME_DA_APPcom o nome da sua app na URL. Ai teste novamente e sempre verificando o console do navegador e o console do tomcat.

abs

Reparei que na index.xtml no console do navegador aparece uma mensagem assim:

Mensagem  {}

Mas continua na mesma, não aparece os syso do método OnMessage e não entra na verificação

            if(session.isOpen()) {

do método send.

estou ficando sem ideias ...

  • tente parar o servidor e limpá-lo (talvez o Tomcat recupere sessões antigas que não estão mais abertas).
  • tem como verificar quantas sessoes tem nessa lista sessions na classe PromosEndpoint?

abs

A lista de sessions

        List<Session> sessions = usuarios.getUsuarios();

está vazia, mesmo após o login.

Pelo que eu entendi, essa sessão não é a "sessão de login" e sim a "sessão de websocket". Ou seja, deve ter um objeto na lista quando vc chama a página com aquele JavaScript que cria o WebSocket. Tudo bem?

É alguma besteira que não estamos vendo ainda ....

abs