Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Problema para atualizar o autor

Estou na aula 9 Java e JSF I: Sua aplicação web com JSF2, concluindo o desafio de alterar e excluir um autor. Para excluir ocorreu corretamente, porem para alterar carrego os dados e quando clico em gravar não atualiza e sim cria um novo., pois o this.autor.getId() sempre vem null, mesmo com o autor carregado. Segue códigos abaixo.

<?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"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <ui:composition template="_template.xhtml">
        <ui:define name="titulo">
                Novo Autor
        </ui:define>

        <ui:define name="conteudo">
            <h:form id="autor">
                <fieldset>
                    <legend>Dados do Autor</legend>
                    <h:panelGrid columns="3">

                        <h:outputLabel value="Nome:" for="nome" />
                        <h:inputText id="nome" value="#{autorBean.autor.nome}"
                            required="true">
                            <f:validateLength minimum="5" />
                            <f:ajax event="blur" render="messageNome" />
                        </h:inputText>

                        <h:message for="nome" id="messageNome" />

                        <h:commandButton value="Gravar" action="#{autorBean.gravar}">
                            <f:ajax execute="@form" render="@form :formTabelaAutores:tabelaAutores"/>
                        </h:commandButton>

                    </h:panelGrid>
                </fieldset>
            </h:form>
            <h:form id="formTabelaAutores">

                <h:dataTable value="#{autorBean.autores}" var="autor" id="tabelaAutores">

                    <h:column>
                        <f:facet name="header">Nome</f:facet>
                        <h:outputText value="#{autor.nome}"/>
                    </h:column>

                    <h:column>
                        <f:facet name="header">Alterar</f:facet>
                        <h:commandLink value="altera" action="#{autorBean.carregar(autor)}"/>
                    </h:column>


                    <h:column>
                        <f:facet name="header">Excluir</f:facet>
                        <h:commandLink value="remove" action="#{autorBean.remover(autor)}"/>
                    </h:column>


                </h:dataTable>

            </h:form>
        </ui:define>

    </ui:composition>

</html>
package br.com.caelum.livraria.bean;

import java.util.List;

import javax.faces.bean.ManagedBean;

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

@ManagedBean
public class AutorBean {

    private Autor autor = new Autor();

    public Autor getAutor() {
        return autor;
    }

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

    public String gravar() {
        System.out.println("Gravando autor " + this.autor.getId());
        if(this.autor.getId() == null){
            new DAO<Autor>(Autor.class).adiciona(this.autor);
        }else {
            new DAO<Autor>(Autor.class).atualiza(this.autor);
        }



        this.autor = new Autor();

        return "livro?faces-redirect=true";
    }

    public void remover(Autor autor) {

        System.out.println("Removendo Autor....");
        new DAO<Autor>(Autor.class).remove(autor);
    }

    public void carregar(Autor autor) {
        this.autor = autor;
    }
}
7 respostas
solução!

Fala Rafael, tudo bem?

o problema é que na sua view não tem nenhum componente guardando o valor do Id. Como não queremos que o id seja um campo editável e talvez nem queiramos que o usuário veja o id, podemos usar um componente que tenha o comportamento de hidden do html.

Para isso dentro do h:form vamos colocar o componente: <h:inputHidden value="#{autorBean.autor.id}"/>em cima do componente do nome mesmo. Agora quando fizermos a edição o binding para id estará feito e dessa forma o nosso DAO entende que não queremos persistir nada e sim fazer um merge, já que o id do autor não é mais null.

ok, vou testar, mas sabe dizer pq no h:form do livro.xhtml não precisa colocar?

No livro vc está usando o setPropertyActionListener?

olá Samir, não estou usando não.

Funcionou perfeitamente Samir, porem ainda gostaria só de saber pq no livro funciona sem o id.

Fala Rafael!

No do livro ele está criando automaticamente esse inputHidden a partir do form de cadastro. Confesso que achei esse comportamento estranho e achei alguma coisa do JSF fazendo isso quando usamos o primefaces, o que não é o caso. Precisaria dar uma olhada na documentação para entender o motivo exatamente e quando acontece esse comportamento.

ok, Samir, muito obrigado pela ajuda.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software