Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

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