Crie uma aplicação de acesso a dados com Primefaces e Hibernate

Veja neste artigo como desenvolver um CRUD usando Primefaces e Hibernate. As operações básicas de manipulação são apresentadas de forma pragmática, através de um exemplo que utilizará Eclipse para JEE, o banco de dados Postgres e o servidor Tomcat.

O Primefaces é um framework desenvolvido principalmente para a camada de apresentação em projetos baseados no padrão MVC. Seu código é uma extensão do JSF e esses dois frameworks convivem bem na criação de páginas Web. O Hibernate é aplicado exclusivamente na camada Model para facilitar a interação com informações armazenadas em banco de dados do tipo SQL.

O projeto exemplo desenvolvido para esse artigo simula o cadastro completo de clientes, que poderia ser parte de uma aplicação para CRM. A primeira providência é baixar o Eclipse do seu site (o tipo que vamos utilizar nesse artigo é a IDE para JEE). A instalação do Eclipse é muito simples: desempacote o arquivo baixado em qualquer pasta do seu computador. Com o Eclipse instalado, podemos baixar o Tomcat que é o servidor JEE da fundação Apache. Da mesma forma que o Eclipse, instale o Tomcat.

O próximo passo é configurar o Eclipse para que chame o Tomcat sempre que quisermos executar nosso projeto. Abra o Eclipse e, após escolher o diretório do seu workspace, acesse Window > Preferences. Na janela nova encontre a opção Server > Runtime Environments, na qual estão listados os servidores já disponíveis na IDE e o botão Add.., onde podemos adicionar um servidor novo. Conforme ilustrado na Figura 1, clicando nesse botão devemos escolher o Tomcat 8 e clicar em Next. Na próxima tela, devemos apontar o diretório raiz da instalação do Tomcat.

Figura 1. Instalar Tomcat

Com o Tomcat configurado, devemos criar um novo projeto do tipo Dynamic Web Project. Além disso, já que nesse artigo vamos utilizar o Maven para gerenciar as dependências, necessitamos instalar m2e, um plugin para Eclipse que facilita muito o desenvolvimento. Como em toda instalação de plugin, podemos ir em Help > Install New Software... e na tela de configuração adicionar a URL- http://download.eclipse.org/technology/m2e/releases. Se tudo foi realizado corretamente, podemos transformar nosso projeto em um projeto Maven, clicando no nome do projeto com o botão direito e escolhendo a opção Configure > Convert to Maven Project. Assim, podemos instalar as várias dependências necessárias para nosso projeto.

A Listagem 1 apresenta o arquivo pom.xml do projeto. Esse arquivo adiciona ao projeto as dependências dos seguintes frameworks: JSF, Primefaces, Hibernate e Log4j, além do driver JDBC do Postgres.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>exemplo-crud-jsf-hibernate</groupId> <artifactId>exemplo-crud-jsf-hibernate</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>4.0</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.2.0.Final</version> </dependency> <dependency> <groupId>org.hibernate.common</groupId> <artifactId>hibernate-commons-annotations</artifactId> <version>4.0.1.Final</version> <classifier>tests</classifier> </dependency> <dependency> <groupId>org.hibernate.javax.persistence</groupId> <artifactId>hibernate-jpa-2.0-api</artifactId> <version>1.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.0.1.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.1.0.CR2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.1-901-1.jdbc4</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
Listagem 1. Arquivo pom.xml

Com isso já poderíamos criar os códigos da aplicação, contudo, para testar ainda necessitamos instalar o Postgres, que pode ser obtido do seu site oficial. Para instalar o Postgres devemos simplesmente seguir as instruções do seu instalador. Para acessar seus dados, podemos usar a ferramenta gráfica PgAdmin, onde devemos criar uma base de dados, que nesse artigo vamos chamar de CRM.

Assim, adotando uma abordagem que vai da camada Model para a View, podemos criar o arquivo hibernate.cfg.xml que definirá como nossa aplicação acessa o Postgres. A Listagem 2 apresenta esse arquivo que tem três definições principais: as propriedades dialect e driver_class definem que usaremos o Postgres para armazenamento de dados; url, usarname e password definem como acessar o Postgres; e em mapping vamos dizer quais são os beans que serão persistidos.

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect </property> <property name="hibernate.connection.driver_class">org.postgresql.Drive </property> <property name="hibernate.connection.username">devmedia </property> <property name="hibernate.connection.password">devmedia </property> <property name="hibernate.connection.url"> jdbc:postgresql://localhost:5432/filiais</property> <property name="connection_pool_size">1</property> <property name="hbm2ddl.auto">update</property> <property name="show_sql">true</property> <mapping class="org.ecjfh.model.Empresa" /> <mapping class="org.ecjfh.model.Filial" /> <mapping class="org.ecjfh.model.Matriz" /> </session-factory> </hibernate-configuration>
Listagem 2. Arquivo hibernate.cfg.xml

A etapa seguinte será criar os beans que devemos persistir. No nosso exemplo, vamos criar a classe abstrata Empresa, que contém as propriedades das empresas que serão salvos na aplicação CRM, e as classes Matriz e Filial que herdaram da classe cliente as propriedades principais e adicionaram respectivamente propriedades para armazenar: nas filiais o objeto que representa a sua matriz; e na matriz sua lista de filiais. A Listagem 3 apresenta as três classes e é importante ressaltar que cada classe deve estar em um arquivo exclusivo, com o mesmo nome dessa classe.

O principal detalhe que devemos levar em conta entre essas três classes é o mapeamento da é o relacionamento um-para-muitos entre uma matriz e suas filiais. No Hibernate isso é implementado com as anotações @ManyToOne e @OneToMany, por uma decisão de projeto foi escolhido o FetchType.EAGER, que irá buscar e carregar os dados de todas filiais para cada matriz recuperada. Isso deve ser usado com muito cuidado, pois pode levar a problemas no uso de memória, rede e do próprio banco de dados. Em um exemplo, é aceitável.

package org.ecjfh.model; import javax.persistence.Entity; import javax.persistence.Id; @Entity public abstract class Empresa { @Id private String CNPJ; private String razaoSocial; private String logradouro; private Integer numero; private String complemento; private String municipio; private String uf; private String telefone; private String email; public String getRazaoSocial() { return razaoSocial; } public void setRazaoSocial(String razaoSocial) { this.razaoSocial = razaoSocial; } public String getCNPJ() { return CNPJ; } public void setCNPJ(String cNPJ) { CNPJ = cNPJ; } public String getLogradouro() { return logradouro; } public void setLogradouro(String logradouro) { this.logradouro = logradouro; } public Integer getNumero() { return numero; } public void setNumero(Integer numero) { this.numero = numero; } public String getComplemento() { return complemento; } public void setComplemento(String complemento) { this.complemento = complemento; } public String getMunicipio() { return municipio; } public void setMunicipio(String municipio) { this.municipio = municipio; } public String getUf() { return uf; } public void setUf(String uf) { this.uf = uf; } } package org.ecjfh.model; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table public class Filial extends Empresa { @ManyToOne(fetch = FetchType.EAGER) private Matriz matriz; public Matriz getMatriz() { return matriz; } public void setMatriz(Matriz matriz) { this.matriz = matriz; } } package org.ecjfh.model; import java.util.Set; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table public class Matriz extends Empresa { @OneToMany(fetch=FetchType.EAGER,mappedBy="matriz", orphanRemoval=true) private Set<Filial> filiais; public Set<Filial> getFiliais() { return filiais; } public void setFiliais(Set<Filial> filiais) { this.filiais = filiais; } }
Listagem 3. Beans persistidos

Para persistência dessas classes vamos criar uma outra classe que respeita o padrão DAO, chamada EmpresaDAO, que conterá as quatro operações. Para facilitar foi criada também a subclasse HibernateUtils, que cria a sessão do Hibernate. A Listagem 4 ilustra a classe EmpresaDAO.

package org.ecjfh.dao; import java.util.ArrayList; import java.util.List; import org.ecjfh.model.Empresa; import org.ecjfh.model.Filial; import org.ecjfh.model.Matriz; import org.ecjfh.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.Transaction; public class EmpresaDAO { public void createEmpresa(Empresa empresa) throws Exception{ Transaction trns = null; Session session = HibernateUtil.getSessionFactory().openSession(); try { trns = session.beginTransaction(); session.save(empresa); session.getTransaction().commit(); } catch (RuntimeException e) { if (trns != null) { trns.rollback(); } e.printStackTrace(); throw new Exception("Error ao criar empresa"); } finally { session.flush(); session.close(); } } public Empresa getEmpresa(String cnpj){ Empresa empresa = null; Session session = HibernateUtil.getSessionFactory().openSession(); try { empresa = (Empresa) session.get(Empresa.class, new String(cnpj)); } finally { session.flush(); session.close(); } return empresa; } public void deleteEmpresa(String empresaId) throws Exception{ Transaction trns = null; Session session = HibernateUtil.getSessionFactory().openSession(); try { trns = session.beginTransaction(); Empresa empresa = (Empresa) session.load(Empresa.class, new String(empresaId)); if(empresa instanceof Filial){ ((Filial) empresa).setMatriz(null); } session.delete(empresa); session.getTransaction().commit(); } catch (RuntimeException e) { if (trns != null) { trns.rollback(); } e.printStackTrace(); throw new Exception("Error ao excluir empresa"); } finally { session.flush(); session.close(); } } @SuppressWarnings("unchecked") public List<Empresa> listEmpresas(){ List<Empresa> empresas = new ArrayList<Empresa>(); Session session = HibernateUtil.getSessionFactory().openSession(); try { empresas = session.createQuery("from Empresa").list(); } catch (RuntimeException e) { e.printStackTrace(); } finally { session.flush(); session.close(); } return empresas; } @SuppressWarnings("unchecked") public List<Matriz> listMatrizes(){ List<Matriz> matrizes = new ArrayList<Matriz>(); Session session = HibernateUtil.getSessionFactory().openSession(); try { matrizes = session.createQuery("from Matriz").list(); } catch (RuntimeException e) { e.printStackTrace(); } finally { session.flush(); session.close(); } return matrizes; } public void updateEmpresa(Empresa empresa) throws Exception{ Transaction trns = null; Session session = HibernateUtil.getSessionFactory().openSession(); try { trns = session.beginTransaction(); session.update(empresa); session.getTransaction().commit(); } catch (RuntimeException e) { if (trns != null) { trns.rollback(); } e.printStackTrace(); throw new Exception("Error ao atualizar empresa"); } finally { session.flush(); session.close(); } } }
Listagem 4. Classe ClienteDAO

Nesse ponto, o ideal seria criar testes unitários para a classe EmpresaDAO, assim poderíamos garantir que a conexão, criação, recuperação, alteração e exclusão de dados estão sendo executadas corretamente.

Com o Hibernate configurado e suas classes já criadas, podemos avançar para a camada Controller. Para essa camada, devemos criar um Managed Bean, ou bean gerenciado, que terá como função controlar o uso dos dados entre a camada Model e a View. Para tal, devemos criar um arquivo chamada faces-config.xml, que deve estar contida na pasta WEB-INF do nosso projeto. Esse arquivo é apresentado na Listagem 5. Ele define um ManagedBean chamado EmpresaManagedBean, que será do tipo session, ou seja, os dados serão armazenados nesse bean durante todo o uso de um usuário especifico. Apenas quando o usuário fechar seu navegador e voltar a acessar essa aplicação, que essa sessão será reiniciada. Além disso, o faces-config define como a aplicação irá passar de uma página Web para outra.

<?xml version="1.0" encoding="UTF-8"?> <faces-configa xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> <managed-bean <managed-bean-name>empresa</managed-bean-name> <managed-bean-class>org.ecjfh.bo.EmpresaManagedBean </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id></from-view-id> <navigation-case> <from-outcome>index</from-outcome> <to-view-id>index.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>insert</from-outcome> <to-view-id>insert.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>update</from-outcome> <to-view-id>update.xhtml</to-view-id> </navigation-case> </navigation-rule> </faces-config>
Listagem 5. Arquivo faces-config.xml

Com isso, podemos criar a classe EmpresaManagedBean. Essa classe será utilizada como um background das páginas Web criadas posteriormente. Na Listagem 6 está ilustrada essa classe, que contém como principal elemento um objeto do tipo empresa, sobre o qual vamos realizar as operações de inserção, deleção, alteração e listagem, que foram definidas na camada DAO.

package org.ecjfh.bo; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.ecjfh.dao.EmpresaDAO; import org.ecjfh.model.Empresa; import org.ecjfh.model.Matriz; public class EmpresaManagedBean implements java.io.Serializable{ private static Logger log = Logger.getLogger(EmpresaManagedBean.class); private static final long serialVersionUID = 1L; private String selectedCNPJ; private Empresa empresa; private List<Empresa> empresas; private List<Matriz> matrizes; public Empresa getEmpresa() { return empresa; } public void setEmpresa(Empresa empresa) { this.empresa = empresa; } public List<Empresa> getEmpresas() { return empresas; } public void setEmpresas(List<Empresa> empresas) { this.empresas = empresas; } public List<Matriz> getMatrizes() { return matrizes; } public void setMatrizes(List<Matriz> matrizes) { this.matrizes = matrizes; } private String getSelectedCNPJ() { return selectedCNPJ; } private void setMsg(String message) { // TODO Auto-generated method stub } public void limparEmpresa() { log.info("Limpando empresa"); this.empresa.setRazaoSocial(""); this.empresa.setCNPJ(""); this.empresa.setComplemento(""); this.empresa.setLogradouro(""); this.empresa.setMunicipio(""); this.empresa.setUf(""); this.empresa.setNumero(null); } public String editEmpresa() { log.info("Editando empresa "+this.getSelectedCNPJ()); EmpresaDAO empresaDAO = new EmpresaDAO(); Empresa empresa = empresaDAO.getEmpresa(this.getSelectedCNPJ()); if(empresa!=null){ this.empresa.setCNPJ(empresa.getCNPJ()); this.empresa.setRazaoSocial(empresa.getRazaoSocial()); this.empresa.setMunicipio(empresa.getMunicipio()); this.empresa.setUf(empresa.getUf()); this.empresa.setLogradouro(empresa.getLogradouro()); this.empresa.setComplemento(empresa.getComplemento()); this.empresa.setNumero(empresa.getNumero()); }else{ this.setMsg("Empresa nao encontrada!"); log.error("Empresa nao encontrada!"); } return "update"; } public String createEmpresa() { String str = "index"; try{ EmpresaDAO empresaDAO = new EmpresaDAO(); empresaDAO.createEmpresa(this.empresa); limparEmpresa(); this.setMsg("Empresa cadastrada!"); }catch(Exception e){ this.setMsg(e.getMessage()); str = "insert"; log.error(e); } return str; } public String deleteEmpresa(){ log.info("Excluindo empresa "+this.getSelectedCNPJ()); String str = "index"; try{ EmpresaDAO empresaDAO = new EmpresaDAO(); empresaDAO.deleteEmpresa(this.getSelectedCNPJ()); limparEmpresa(); this.setMsg("Excluído com sucesso!"); }catch(Exception e){ this.setMsg(e.getMessage()); log.error(e); } return str; } public List<EmpresaManagedBean> getListaMatrizes(){ log.info("Listando matrizes"); List<EmpresaManagedBean> empresas = new ArrayList<EmpresaManagedBean>(); try{ EmpresaDAO empresaDAO = new EmpresaDAO(); for(Matriz matriz:empresaDAO.listMatrizes()){ EmpresaManagedBean bean = new EmpresaManagedBean(); bean.setEmpresa(matriz); empresas.add(bean); } }catch(Exception e){ this.setMsg(e.getMessage()); log.error(e); } return empresas; } public List<EmpresaManagedBean> getListaEmpresas(){ limparEmpresa(); log.info("Listando empresa"); List<EmpresaManagedBean> empresas = new ArrayList<EmpresaManagedBean>(); try{ EmpresaDAO empresaDAO = new EmpresaDAO(); for(Empresa empresa:empresaDAO.listEmpresas()){ EmpresaManagedBean bean = new EmpresaManagedBean(); bean.setEmpresa(empresa); empresas.add(bean); } }catch(Exception e){ this.setMsg(e.getMessage()); log.error(e); } return empresas; } public String updateEmpresa(){ String str = "index"; try{ EmpresaDAO empresaDAO = new EmpresaDAO(); empresaDAO.updateEmpresa(this.empresa); limparEmpresa(); this.setMsg("Atualizado com sucesso!"); }catch(Exception e){ this.setMsg(e.getMessage()); str = "deleteUpdate"; log.error(e); } return str; } }
Listagem 6. Arquivo faces-config.xml

O passo seguinte é criar os arquivos da camada View, que nesse exemplo consistem exclusivamente de documentos XHTML. O primeiro a ser criado é o insert.xhtml, que contém um formulário para cadastro de clientes na aplicação. Essa página tem os seguintes campos e requisitos de validação:

A Listagem 7 ilustra como criar esse formulário utilizando Primefaces, que é uma biblioteca de tags, cujo prefixo e o “p”. Para utilizá-la em uma página, adicione . Para implementar as regras de validação vamos adicionar a tag required="true" nos campos obrigatórios, e regras de validação usando expressões regulares. Para CNPJ esse tipo de regra deve ser implementada da seguinte forma:

<?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" xmlns:p="http://primefaces.org/ui"> <h:head> </h:head> <h:body> <p:outputLabel value="#{empresa.msg}" id="msg1" styleClass="msg" /> <h:form id="empresaForm" enctype="multipart/form-data" prependId="false"> <p:panelGrid id="panel1" columns="3" border="3" cellpadding="5" cellspacing="1"> <f:facet name="header"> <h:outputText value="Criar empresa" /> </f:facet> <p:outputLabel value="Tipo:" /> <p:selectOneRadio id="matrizFilial" value="#{empresa.matrizFilial}"> <f:selectItem itemValue="true" itemLabel="Matriz" /> <f:selectItem itemValue="false" itemLabel="Filial" /> <f:ajax event="change" execute="@this" render="panel1" /> </p:selectOneRadio> <p:message for="matrizFilial" /> <p:outputLabel value="Selecionar matriz:" rendered="#{empresa.matrizFilial eq 'false'}" /> <p:selectOneMenu id="matrizes" value="#{empresa.matriz}" rendered="#{empresa.matrizFilial eq 'false'}"> <f:selectItems value="#{empresa.listaMatrizes}" var="e" itemLabel="#{e.CNPJ}" itemValue="#{e.CNPJ}" /> </p:selectOneMenu> <p:message for="matrizes" rendered="#{empresa.matrizFilial eq 'false'}" /> <p:outputLabel value="Razao social:" /> <p:inputText value="#{empresa.razaoSocial}" id="razaoSocial" maxlength="100" required="true" requiredMessage="Campo obrigatório" /> <p:message for="razaoSocial" /> <p:outputLabel value="CNPJ:" /> <p:inputText value="#{empresa.CNPJ}" required="true" id="CNPJ" validatorMessage="CNPJ mal formatado" requiredMessage="Campo obrigatório"> <f:validateRegex pattern="^[0-9]{2,3}\.[0-9] \.[0-9]\/[0-9]-[0-9]$" /> </p:inputText> <p:message for="CNPJ" /> <p:outputLabel value="Logradouro:" required="true" /> <p:inputText value="#{empresa.logradouro}" id="logradouro" maxlength="150" required="true" requiredMessage="Campo obrigatório" /> <p:message for="logradouro" /> <p:outputLabel value="Número:" /> <p:inputText value="#{empresa.numero}" id="numero" required="true" requiredMessage="Campo obrigatório" maxlength="10"> <f:convertNumber integerOnly="true" type="number" /> </p:inputText> <p:message for="numero" /> <p:outputLabel value="Complemento:" /> <p:inputText value="#{empresa.complemento}" id="complemento" /> <p:message for="complemento" /> <p:outputLabel value="Município:" /> <p:inputText value="#{empresa.municipio}" id="municipio" maxlength="150" required="true" requiredMessage="Campo obrigatório" /> <p:message for="municipio" /> <p:outputLabel value="UF:" /> <p:inputText value="#{empresa.uf}" id="uf" maxlength="2" required="true" requiredMessage="Campo obrigatório" /> <p:message for="uf" /> <p:outputLabel value="Telefone:" /> <p:inputText value="#{empresa.telefone}" id="telefone1" required="true" requiredMessage="Campo obrigatório" validatorMessage="Telefone mal formatado. Ex. (99) 9999-9999"> </p:inputText> <p:message for="telefone" /> <p:outputLabel value="Telefone 2:" /> <p:inputText value="#{empresa.telefone2}" id="telefone2" validatorMessage="Telefone mal formatado. Ex. (99) 9999-9999"> <f:validateRegex pattern="^[+][9][0-9](\(11\) [9][0-9] -[0-9])|(\(1[2-9]\) [5-9][0-9]-[0-9])| (\([2-9][1-9]\) [5-9][0-9]-[0-9])$" /> </p:inputText> <p:message for="telefone2" /> <p:outputLabel value="Email" /> <p:inputText id="email" value="#{empresa.email}" label="email" size="40" validatorMessage="Email mal formatado"> <f:validateRegex pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)* @[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$" /> </p:inputText> <p:message for="email" /> <f:facet name="footer"> <h:commandButton value="Salvar" action="#{empresa.createEmpresa}" update="empresaForm"> </h:commandButton> </f:facet> </p:panelGrid> </h:form> </h:body> </html>
Listagem 7. Arquivo insert.xhtml

O próximo passo a ser criado é o index.xhtml, que contém uma tabela que lista todos clientes já cadastrados na aplicação. O principal comando dessa página é o p:dataTable, um dos componentes mais interessantes do Primefaces. Esse componente renderiza uma tabela HTML que contém também comandos para ordenar as colunas, ordenar os valores, editar e excluir seus valores, representados na Listagem 8. Por exemplo, para que o CNPJ possa ser ordenado e buscado, sortBy="#{e.CNPJ}"filterBy="#{e.CNPJ}". Além disso, essa tabela faz paginação automática, adicionando simplesmente o atributo paginator="true". Outro ponto importante são os botões para edição e exclusão. O primeiro chamará a página update.xhtml apresentada na sequência (usando o método editEmpresa) enquanto o segundo irá executar o código para exclusão da empresa de acordo com a linha selecionada (usando o método deleteEmpresa), esses dois métodos recebem como parâmetro o CNPJ da empresa selecionada.

<?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" xmlns:p="http://primefaces.org/ui"> <h:head> </h:head> <h:body> <p:outputLabel value="#{empresa.msg}" id="msg1" styleClass="msg" /> <p:dataTable emptyMessage="Não há empresas cadastradas" value="#{empresa.listaEmpresas}" var="e" styleClass="order-table" headerClass="order-table-header" rowClasses="order-table-odd-row,order-table-even-row" paginator="true" rows="20"> <p:column headerText="CNPJ" sortBy="#{e.CNPJ}" filterBy="#{e.CNPJ}" filterMatchMode="exact"> <h:outputText value="#{e.CNPJ}" /> </p:column> <p:column headerText="Razão Social" sortBy="#{e.razaoSocial}" filterBy="#{e.razaoSocial}" filterMatchMode="exact"> <h:outputText value="#{e.razaoSocial}" /> </p:column> <p:column headerText="UF" sortBy="#{e.uf}" filterBy="#{e.uf}" filterMatchMode="exact"> <h:outputText value="#{e.uf}" /> </p:column> <p:column headerText="Município" sortBy="#{e.municipio}" filterBy="#{e.municipio}" filterMatchMode="exact"> <h:outputText value="#{e.municipio}" /> </p:column> <p:column> <f:facet name="header"> Filial </f:facet> #{e.tipo} </p:column> <p:column> <h:form id="commandForm"> <h:commandButton value="Delete" styleClass="fs-button-portfolio" action="#{empresa.deleteEmpresa}" ajax="false"> <f:setPropertyActionListener target="#{empresa.selectedCNPJ}" value="#{e.CNPJ}" /> </h:commandButton> <h:commandButton value="Edit" styleClass="fs-button-portfolio" action="#{empresa.editEmpresa}" ajax="false"> <f:setPropertyActionListener target="#{empresa.selectedCNPJ}" value="#{e.CNPJ}" /> </h:commandButton> </h:form> </p:column> </p:dataTable> </h:body> </html>
Listagem 8. Arquivo index.xhtml

A última parte desse projeto é a página update.xhtml. Essa página é bastante parecida com o insert.xhtml. A principal diferença está no método chamado por seu commandButton, nesse caso updateEmpresa, conforme apresentado na Listagem 9.

<f:facet name="footer"> <h:commandButton value="Atualizar" update="empresaForm" action="#{empresa.updateEmpresa}"> <f:ajax render="razaoSocial CNPJ logradouro numero complemento municipio uf telefone1 telefone2 fax" execute="@form" /> </h:commandButton> </f:facet>
Listagem 9. Arquivo update.xhtml

Esse exemplo pode ser expandido as ferramentas já apresentadas. Além disso, a interface pode receber um tratamento mais fino em relação a usabilidade e estética. O código do exemplo está salvo como um projeto do Eclipse e disponível para download nesse post.

Artigos relacionados