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.

Instalar 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:

  • Razão Social (input text, até 100 caracteres), preenchimento obrigatório;
  • CNPJ (utilizar máscara de validação), preenchimento obrigatório;
  • Logradouro (input text, até 150 caracteres), preenchimento obrigatório;
  • Número (input text, validação para números inteiros, até 10 caracteres), preenchimento obrigatório;
  • Complemento (input text, até 150 caracteres), preenchimento opcional
  • Município (input text, até 150 caracteres), preenchimento obrigatório;
  • UF (input text, até 2 caracteres), preenchimento obrigatório;
  • Matriz ou Filial (select box);
  • Se Filial, apresentar campo de consulta para selecionar uma empresa matriz pré-cadastrada, com consulta por razão social ou CNPJ;
  • Telefone de contato (máscara de telefone com DDI, DDD, Prefixo e Sufixo), preenchimento obrigatório;
  • E-mail (validação de máscara *@*.* ou *@*.*.*), preenchimento opcional.

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.