CRUD Seam
1 – Introdução
Agora que já vimos o projeto rodando.
Vamos acrescentar algumas funcionalidades ao sistema de locação de carros (locar).
Basicamente, nós temos uma empresa de locação de veículos.
O sistema precisa fazer o seguinte:
- Cadastrar os veículos disponíveis nas cidades
- Buscar e reservar veículos em uma cidade
- Locação de um veículo
2 – Modelo
Crie uma classe que usaremos como ancestral para nossas entidades persistentes.
Selecione o projeto locar-ejb.
File -> New -> Class
Package: br.com.locar.entity
Name: AppEntity
Abstract: yes (marcado)
Interfaces: java.io.Serializable
Finish
Adicione 2 atributos:
- Long id
- int versao
Adicione as anotações de JPA:
- @Id @GeneratedValue
- @Version
A classe fica assim:
package br.com.locar.entity;
import java.io.Serializable;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
@MappedSuperclass
public abstract class AppEntity implements Serializable {
private static final long serialVersionUID = 3267491073682419272L;
private Long id;
private int versao;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Version
public int getVersao() {
return versao;
}
public void setVersao(int versao) {
this.versao = versao;
}
}
Crie uma classe Cidade.
Selecione o projeto locar-ejb.
File -> New -> Class
Package: br.com.locar.entity
Name: Cidade
Superclass: AppEntity
Finish
Adicione 1 atributo:
- nome : String
Adicione as anotações de JPA:
- @Entity
- @NotNull
- @Length(min = 3, max = 30)
Gere os get e set
Gere o serial version
A classe fica assim:
package br.com.locar.entity;
import javax.persistence.Entity;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
@Entity
public class Cidade extends AppEntity {
private static final long serialVersionUID = -4275579483864354167L;
private String nome;
@NotNull
@Length(min = 3, max = 30)
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
3 – Controle
Crie uma classe CidadeAction.
A classe CidadeAction terá uma cidade e uma lista de cidades.
O atributo cidade servirá para ligarmos aos campos de cadastro e edição de cidades na tela.
A lista de cidades servirá para montar uma tabela com as cidades na tela.
Usaremos um Entity Manager para trabalharmos com a persistencia.
E uma classe Log para gerarmos o log da aplicação.
Selecione o projeto locar-ejb.
File -> New -> Class
Package: br.com.locar.session
Name: CidadeAction
Finish
Adicione os atributos:
- cidade : Cidade
- cidades: List<cidade>
- cidadeSelecionada: Cidade
- log : Log
- entityManager : EntityManager
Adicione as anotações do Seam
- @Name(“cidadeAction”)
- @DataModel
- @DataModelSelection
- @Logger
- @In
A classe fica assim:
package br.com.locar.session;
import java.util.List;
import javax.persistence.EntityManager;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.log.Log;
import br.com.locar.entity.Cidade;
@Name("cidadeAction")
public class CidadeAction {
private Cidade cidade = new Cidade();
@DataModel
private List<cidade> cidades;
@DataModelSelection
private Cidade cidadeSelecionada;
@Logger
private Log log;
@In
private EntityManager entityManager;
public Cidade getCidade() {
return cidade;
}
@Factory("cidades")
public void inicializaCidades() {
log.info("Inicializa cidades");
this.cidades = entityManager.createQuery("from Cidade").getResultList();
}
public String salvar() {
log.info("Salver cidade nome = #", cidade);
entityManager.merge(cidade);
this.cidade = new Cidade();
inicializaCidades();
return "cidade.xhtml";
}
public String remover() {
log.info("Remover cidade id = #", cidadeSelecionada.getId());
entityManager.remove(cidadeSelecionada);
inicializaCidades();
return "cidade.xhtml";
}
public void editar() {
this.cidade = cidadeSelecionada;
}
}
4 – Visão
Vamos criar agora uma página para o cadastro e exibição das cidades.
Crie uma página xhtml.
Para vacilitar vamos copiar a home.xhtml e colar ela com o nome cidade.xhtml.
Remova o rich panel todo:
<rich:panel> até </rich:panel> (inclusive)
Coloque um formulário:
<h:form> </h:form>
Dentro do formulário coloque um grid com 3 colunas:
<h:panelgrid columns="”3”"> </h:panelgrid>
Dentro do grid insira um campo oculto com o id da cidade, um campo para o nome da cidade e um botão para salvar:
<h:inputhidden value="#{cidadeAction.cidade.id}">
<s:decorate template="/layout/edit.xhtml">
<ui:define name="label">Nome:</ui:define>
<h:inputtext value="#{cidadeAction.cidade.nome}" required="true">
</h:inputtext></s:decorate>
<h:commandbutton value="Salvar" actionlistener="#{cidadeAction.salvar}">
Aqui usamos um componente decorate apontando para o template edit.xhtml.
Depois falarei mais sobre o facelets e como criar componentes.
Mas vale a penda dar uma olhada nesse arquivo.
Ele é um componente formado por um label e um espaço para incluir o componente de entrada de dados.
Que facilita na criação de um componente de entra e nos estilos e validações.
Podemos observar que este componente tem estilo para quando marcado com required que é o nosso caso.
Ele faz a validação integrada com as nossas anotações no modelo.
Como podemos ver tentando cadastrar usando o campo nome em branco ou digitando menos de 3 caracteres.
E já exibe a mensagem de erro ao cliente.
Para verificarmos se o registro foi gravado vamos colocar em baixo na página uma tabela com as cidades gravadas no banco.
Usando o componente <rich:datatable> vamos recuperar as cidades.
<rich:datatable value="#{cidades}" var="c" style="width: 60%">
Preenchemos as colunas com o componente <rich:column>.
Colocamos um titulo na coluna usamos <f:face name="”header”">
<rich:column>
<f:facet name="header">ID</f:facet>
<h:outputtext value="#{c.id}">
</h:outputtext></rich:column>
E dois link, um para edição e outro para remoção do registro.
<rich:column>
<f:facet name="header">Editar</f:facet>
<h:commandlink action="#{cidadeAction.editar}">
<h:outputtext value="Editar">
</h:outputtext></h:commandlink>
</rich:column>
<rich:column>
<f:facet name="header">Remover</f:facet>
<h:commandlink action="#{cidadeAction.remover}">
<h:outputtext value="Remover">
</h:outputtext></h:commandlink>
</rich:column>
A pagina cidade.xhtml fica o seguinte:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" s="http://jboss.com/products/seam/taglib" ui="http://java.sun.com/jsf/facelets" f="http://java.sun.com/jsf/core" h="http://java.sun.com/jsf/html" rich="http://richfaces.org/rich" template="layout/template.xhtml">
<ui:define name="body">
<h1>Cidade</h1>
<h:form>
<h:panelgrid columns="3">
<h:inputhidden value="#{cidadeAction.cidade.id}">
<s:decorate template="/layout/edit.xhtml">
<ui:define name="label">Nome:</ui:define>
<h:inputtext value="#{cidadeAction.cidade.nome}" required="true">
</h:inputtext></s:decorate>
<h:commandbutton value="Salvar" actionlistener="#{cidadeAction.salvar}">
</h:commandbutton></h:inputhidden></h:panelgrid>
<rich:datatable value="#{cidades}" var="c" style="width: 60%">
<rich:column>
<f:facet name="header">ID</f:facet>
<h:outputtext value="#{c.id}">
</h:outputtext></rich:column>
<rich:column>
<f:facet name="header">Nome</f:facet>
<h:outputtext value="#{c.nome}">
</h:outputtext></rich:column>
<rich:column>
<f:facet name="header">Editar</f:facet>
<h:commandlink action="#{cidadeAction.editar}">
<h:outputtext value="Editar">
</h:outputtext></h:commandlink>
</rich:column>
<rich:column>
<f:facet name="header">Remover</f:facet>
<h:commandlink action="#{cidadeAction.remover}">
<h:outputtext value="Remover">
</h:outputtext></h:commandlink>
</rich:column>
</rich:datatable>
</h:form>
</ui:define>
</ui:composition>
E para completar vamos colocar um link para nossa página no menu.
Abra o arquivo menu.xhtml e acrescente um link para a nossa página.
<rich:toolbargroup>
<h:outputtext value="#{projectName}:">
<s:link id="menuHomeId" view="/home.xhtml" value="Home" propagation="none">
<s:link view="/cidade.xhtml" value="Cidade">
</s:link></s:link></h:outputtext></rich:toolbargroup>
5 – Testando
Vamos ver como reiniciar a aplicação sem precisar reiniciar todo o servidor.
Servers -> Jboss 5.1 -> Clean -> OK
Pronto a aplicação vai ser reiniciada.
Aguarde alguns segundos.
Abra o browser e acese:
http://localhost:8080/locar/
Clique no link Cidade no menu.
Pronto o primeiro CRUD com o Seam.</f:face></rich:column></rich:datatable></rich:datatable></h:commandbutton></h:inputhidden></cidade></cidade>
13 comments:
O arquivo cidade.xhtml não foi completamente postado ou postado com erro ou erro no Blog
O que impede o entendimento do mesmo
valor reveja o código xhtml postado no Blog!
Grato
Alex
Ao colocar o conteúdo do xhtml no site o site tira o codigo, não ficando legível o xhtml.
Quem tiver interesse no arquivo é só enviar um email.
Vou retirar os comentários com emails só para não gerar spam pra galera.
Valeu o acesso ai galera!!!
Caro Silvio,
Preciso do arquivo e do conteúdo que não aparece no site (na página)...sou iniciante e toda ajuda é necessária...rsrsr...josecojr@gmail.com brigadão.
Segui o tutorial que você escreveu, a pagina foi construida corretamente ....
Mas quando tento incluir um nome de cidade e clico no botão salvar ocorre o seguinte erro: javax.el.PropertyNotFoundException: /cidade.xhtml @18,56 value="#{cidadeAction.cidade.id}": Target Unreachable, identifier 'cidadeAction' resolved to null
Você sabe o que está ocorrendo?
Tem como me mostrar o código fonte para eu tirar algumas dúvidas?
Obs: estou usando mysql.
você anotou a classe CidadeAction com @Name("cidadeAction") e na declaração da variável cidade, você instanciou a mesma?
Sim ....
@Name("cidadeAction")
public class CidadeAction {
private Cidade cidade = new Cidade();
Aquino said...
Tem como me mostrar o código fonte para eu tirar algumas dúvidas?
Qual seria o arquivo que você quer?
O xhtml ou o .java?
Poderia passar o xhtml. willianmarcel@gmail.com
Silvio, o que fiz foi seguir rigorosamente o tutorial que você fez (mais de uma vez), ressalvo que eu uso o mysql (não deve ser este o problema), mas não creio que seja o problema, em "tese" o meu código deveria estar exatamente igual ao seu....
Isto posto gostaria que me enviasse o codigo fonte (se possivel WAR) para fazer a comparação e tentar ver o que deu errado.
Obs: Se você achar melhor envio o meu .....
Caro Silvio, consegui fazer funcionar...
Estava faltando a anotação de escopo..
@Name("cidadeAction")
@Scope(ScopeType.SESSION)
public class CidadeAction { ....
Valeu .....
Silvio, boa noite, será que você pode me passar por email o código da parte de apresentação? Obrigado.
meu Email: willianmarcel@gmail.com
Muito bom o post mas preciso do codigo completo, vc poderia mandar pra mim amcoelhoabreu@yahoo.com.br
Post a Comment