Solucionado (ver solução)

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!

Solucionado
(ver solução)
13
respostas

Botão gravar livro, não executa o ajax e no console so exibe o log do hibernate

Não entendi por que não executa nada e solta o log do hibernate??

    <h:commandButton value="Gravar Livro" action="#{livroBean.gravar}">
            <f:ajax execute="@form" render="@form :tabelaLivros" />
        </h:commandButton>
    </h:form>
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select autor0_.id as id1_, autor0_.nome as nome1_ from Autor autor0_
Hibernate: select autor0_.id as id1_, autor0_.nome as nome1_ from Autor autor0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select autor0_.id as id1_, autor0_.nome as nome1_ from Autor autor0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.isbn as isbn0_, livro0_.preco as preco0_, livro0_.titulo as titulo0_ from Livro livro0_
Hibernate: select livro0_.id as id0_, livro0_.dataLancamento as dataLanc2_0_, livro0_.
13 respostas

Oi David, tudo bem?

você pode passar o código da sua página inteira?

<?xml version="1.0" encoding="UTF-8" ?>
<!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://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

<h:head />

<h:body>
    <h1>Novo Livro</h1>

    <h:messages id="messages" />

    <h:form>
        <fieldset>
            <legend>Dados do Livro</legend>
            <h:panelGrid columns="2">

                <h:outputLabel value="Titulo:" for="titulo" />
                <h:inputText id="titulo" value="#{livroBean.livro.titulo}"
                    required="true" requiredMessage="Título obrigatório"
                    validatorMessage="o comprimento é maior do que o máximo permitido de 40">
                    <f:validateLength maximum="40" />
                    <f:ajax event="blur" render=":messages" />
                </h:inputText>

                <h:outputLabel value="ISBN:" for="isbn" />
                <h:inputText id="isbn" value="#{livroBean.livro.isbn}"
                    validator="#{livroBean.comecaComDigitoUm}" />

                <h:outputLabel value="Preço:" for="preco" />
                <h:inputText id="preco" value="#{livroBean.livro.preco}"
                    validatorMessage="o atributo especificado não está entre os valores esperados de 1 e 1.000.">
                    <f:validateDoubleRange maximum="1000" minimum="1" />
                </h:inputText>

                <h:outputLabel value="Data de Lançamento:" for="dataLancamento" />
                <h:inputText id="dataLancamento"
                    value="#{livroBean.livro.dataLancamento.time}">
                    <f:convertDateTime pattern="dd/MM/yy HH:mm"
                        timeZone="America/Sao_Paulo" />
                </h:inputText>

            </h:panelGrid>
        </fieldset>

        <fieldset>
            <legend>Dados do Autor</legend>
            <h:panelGrid columns="2">
                <h:outputLabel value="Selecione o Autor:" for="autor" />
                <h:selectOneMenu value="#{livroBean.autorId}" id="autor">
                    <f:selectItems value="#{livroBean.autores}" var="autor"
                        itemLabel="#{autor.nome}" itemValue="#{autor.id}" />
                </h:selectOneMenu>
                <h:commandButton value="Gravar autor"
                    action="#{livroBean.gravarAutor}">
                    <f:ajax execute="autor" render="tabelaAutores" />
                </h:commandButton>
                <h:dataTable value="#{livroBean.autoresDoLivro}" var="autor"
                    id="tabelaAutores">
                    <h:column>
                        <h:outputText value="#{autor.nome}" />
                    </h:column>
                </h:dataTable>
            </h:panelGrid>
        </fieldset>

        <h:commandButton value="Gravar Livro" action="#{livroBean.gravar}">
            <f:ajax execute="@form" render="@form :tabelaLivros" />
        </h:commandButton>
    </h:form>

    <h:dataTable value="#{livroBean.livros}" var="livro" id="tabelaLivros">
        <h:column>
            <f:facet name="header">Título</f:facet>
            <h:outputText value="#{livro.titulo}" />
        </h:column>
        <h:column>
            <f:facet name="header">ISBN</f:facet>
            <h:outputText value="#{livro.isbn}" />
        </h:column>
        <h:column>
            <f:facet name="header">Preço</f:facet>
            <h:outputText value="#{livro.preco}" />
        </h:column>
        <h:column>
            <f:facet name="header">Data de Lançamento</f:facet>
            <h:outputText value="#{livro.dataLancamento.time}">
                <f:convertDateTime pattern="dd/MM/yy HH:mm" />
            </h:outputText>
        </h:column>
    </h:dataTable>
</h:body>

</html>

Samir, obrigado pela ajuda!

Fala David, aqui deu certo com o seu código. Conseguiu resolver?

Pior que não consegui, estou achando estranho, pois é disparado algum evento... por que o hibernate responde! só não sei como não é chamado os validadores ou a função gravar :(

Manda o seu livroBean. Deve ter alguma coisa no método gravar que não ta deixando ele gravar.

Este é o código do livroBean, vlwwww pela ajuda

package br.com.caelum.livraria.bean;

import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import br.com.caelum.livraria.dao.DAO;
import br.com.caelum.livraria.modelo.Autor;
import br.com.caelum.livraria.modelo.Livro;

@ManagedBean
@ViewScoped
public class LivroBean {

    private Livro livro = new Livro();
    private Integer autorId;

    public List<Livro> getLivros(){
        return new DAO<Livro>(Livro.class).listaTodos();
    }

    public Integer getAutorId() {
        return autorId;
    }

    public void setAutorId(Integer autorId) {
        this.autorId = autorId;
    }

    public Livro getLivro() {
        return livro;
    }

    public List<Autor> getAutoresDoLivro(){
        return livro.getAutores();
    }

    public List<Autor> getAutores() {
        return new DAO<Autor>(Autor.class).listaTodos();
    }

    public void gravarAutor(){
        System.out.println("GRAVANDO AUTOR");
        System.out.println("Id do autor: " + autorId);
        Autor autor = new DAO<Autor>(Autor.class).buscaPorId(autorId);
        livro.adicionaAutor(autor);
        System.out.println("Nome do autor: " + autor.getNome());
    }

    public void gravar() {
        System.out.println("GRAVANDO LIVRO");
        System.out.println("Gravando livro " + this.livro.getTitulo());

        if (livro.getAutores().isEmpty()) {
            //throw new RuntimeException("Livro deve ter pelo menos um Autor.");
            FacesContext.getCurrentInstance().addMessage("autor", new FacesMessage("Livro deve ter pelo menos um Autor."));
            return;
        }

        new DAO<Livro>(Livro.class).adiciona(this.livro);
    }

    public void comecaComDigitoUm(FacesContext fc, UIComponent c, Object o) throws ValidatorException {
        String valor = o.toString();
        if(!valor.startsWith("1")){
            throw new ValidatorException(new FacesMessage("Deveria começar com 1"));
        }
    }

}

Acabei de fazer mais um teste, subi o servidor em Debug, coloquei o break no método gravar livro, e quando clico no botão gravar livro, não chama o método, masssss quando eu comento esta linha da pagina.

<h:commandButton value="Gravar Livro" action="#{livroBean.gravar}">
<!--             <f:ajax execute="@form" render="@form :tabelaLivros" /> -->
        </h:commandButton>

Ai funciona, mas não limpa a tela quando termina de persistir.

Tenta assim:

<h:commandButton value="Gravar" action="#{livroBean.gravar}">
         <f:ajax execute="@form" render="@form :formTabelaLivros:tabelaLivros" />
    </h:commandButton>

Parece que você não colocou essa parte dentro do form. Tenta colocando desse jeito:

<h:form id="formTabelaLivros">
<h:dataTable value="#{livroBean.livros}" var="livro" id="tabelaLivros">
        <h:column>
            <f:facet name="header">Título</f:facet>
            <h:outputText value="#{livro.titulo}" />
        </h:column>
        <h:column>
            <f:facet name="header">ISBN</f:facet>
            <h:outputText value="#{livro.isbn}" />
        </h:column>
        <h:column>
            <f:facet name="header">Preço</f:facet>
            <h:outputText value="#{livro.preco}" />
        </h:column>
        <h:column>
            <f:facet name="header">Data de Lançamento</f:facet>
            <h:outputText value="#{livro.dataLancamento.time}">
                <f:convertDateTime pattern="dd/MM/yy HH:mm" />
            </h:outputText>
        </h:column>
    </h:dataTable>
</h:form>

David, o estranho é que eu copiei o seu bean e o seu xhtml e ta funcionando. Tenta fazer o que o Anderson falou de colocar a tabela dentro de um form.

Se mesmo assim não funcionar, remove o projeto do seu servidor, da um clean nele com ele rodando e adiciona o projeto novamente.

solução!

Eu fiz as seguintes alterações e funcionou! revi o vídeo da aula. O h:messages estava fora do form e por isso não estava funcionando.

<h:messages id="messages" />

Mas ai me surgiu outra duvida, isso interfere tanto assim? por que eu estava referenciando o h:messages usando os ":" de path absoluto, e vocês testaram e funcionou, vocês sabem por que isto interferiu no meu caso?

E o form não estava limpando pois esqueci de zerar o livro dentro do bean apos salvar.

public void gravar() {
        System.out.println("GRAVANDO LIVRO");
        System.out.println("Gravando livro " + this.livro.getTitulo());

        if (livro.getAutores().isEmpty()) {
            //throw new RuntimeException("Livro deve ter pelo menos um Autor.");
            FacesContext.getCurrentInstance().addMessage("autor", new FacesMessage("Livro deve ter pelo menos um Autor."));
            return;
        }

        new DAO<Livro>(Livro.class).adiciona(this.livro);
        // AQUIIIIIIIIII!
        livro = new Livro();
    }

Boa David! Esse negócio de limpar o objeto é importante por conta do JSF ser Stateful, então precisa dar new nos objetos.

Agora a questão do ajax, faz sentido ele não funcionar só por causa do form... tem vezes que ele só consegue acessar um componente referenciando o form que ele esta primeiro. Da pra referenciar só pelo id se os componentes estiverem no mesmo form, se não tem que ter referencia do form em que ele esta.

O estranho é que aqui pra mim funcionou com o seu código... Não mostrou a msg no h:messages mas renderizou a página certinho.

Bem ficamos com o mistério da informática! "em algumas maquinas funcionam", mas bem consegui resolver meu problema! grato pelas ajudas!!! muito obrigado!!