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>