O Facelets é um subprojeto do JSF criado pela antiga Sun Microsystems e atualmente mantido pela Oracle, facilmente integrável com a tecnologia Java e que mudou toda a maneira de se implementar views nas páginas web ao parar de suportar JSPs como arquivos padrão para essa finalidade.

Nos primórdios do JSF, as integrações entre as páginas das aplicações eram sempre dificultadas pela grande quantidade de arquivos XML de configuração, bem como uso de diretivas JSP (<%@ %>) que feria o princípio fundamental do JSF: abstrair qualquer código Java diretamente na camada de visão através do uso de tags customizadas.

O Facelets surgiu como uma opção para solucionar esse problema não só eliminando todo o código explicito nas páginas, como também proporcionando a criação de templates reaproveitáveis e importáveis; e fornecendo recursos para operações básicas da lógica de programação como repetições, condições e manipulação de dados através da EL (Expression Language) do próprio JSF.

Dentre as principais características do Facelets, destacam-se:

  • Permite a integração entre diferentes versões do JSF 1.2 (a mais famosa) e 2.2 (a mais recente), além de atender por completo a especificação da Oracle e do Apache Myfaces.
  • Facilidade na criação de templates (por exemplo, você pode criar uma página Facelets para representar o cabeçalho da aplicação, outra para o rodapé, e pode importá-las facilmente em todas as demais páginas, sem necessitar usar as tags de include diretamente).
  • Tem um atributo chamado “jsfc” que permite incluir trechos de código JSF nas tags HTML (veremos mais detalhes adiante).
  • Elimina o sistema JSP Compiler to Servlet que é usado para compilar as páginas JSPs em Servlets antes de devolver a resposta ao browser. Isso basicamente aumenta em 30% a 50% a performance do sistema.
  • Facilidade para criar componentes reutilizáveis, usar os de terceiros ou criar os seus próprios.
  • Usa XHTML (HTML extensível) como tecnologia para as views do JSF, que por sua vez, é bem mais rígida que as JSPs e HTML básico ao não permitir erros de fechamento de tags, ou ausência de atributos obrigatórios, por exemplo.
  • Precisão para reportar erros, isto é, o sistema de mensagens de erro do Facelets é semelhante ao do Java, baseado em stack traces (pilhas de mensagens de exceções). Assim podemos rastrear e entender exatamente aonde o problema está no código.

A Figura 1 traz uma representação gráfica de como funciona o Facelets internamente. Veja que do lado esquerdo temos o arquivo de template, construído com as tags da API do Facelets interna à do JSF, que demarca as “regiões” da página, no caso três: cabeçalho, corpo e rodapé. Assim, é como se o Facelets marcasse aquele espaço com uma lacuna que deve ser preenchida pela página que implementar tal template. As páginas de resultado 1 e 2 ao lado direito representam o esqueleto comum a todas elas (arquivos de CSS, JS no cabeçalho e o rodapé), mais o conteúdo específico de cada uma (corpo e título do cabeçalho).

Arquitetura interna do Facelets
Figura 1. Arquitetura interna do Facelets

Instalando o Facelets

A instalação do Facelets é bem simples, mas para que consigamos executar um exemplo real, precisamos baixar algumas ferramentas (as URLs para download estão disponíveis na seção Links), a saber:

  • JDK 6 ou superior;
  • Eclipse para desenvolvedores JEE;
  • Tomcat 7 ou superior.

Para iniciar, abra o Eclipse, selecione um diretório para o workspace e assim que a janela de boas-vindas aparecer selecione a perspectiva Java EE no topo direito da IDE. Vamos adicionar agora o Tomcat ao Eclipse para que tenhamos todas as libs do JEE disponíveis quando formos criar o projeto. Logo, acesse a aba Servers na barra inferior, clique com o botão direito e selecione a opção New > Server. Selecione o servidor Apache > Tomcat v7.0 Server, clique em Next, informe o diretório onde você descompactou o zip do servidor e clique em Finish. Após isso ele estará instalado.

Vamos criar agora um novo projeto: Clique em File > New > Dynamic Web Project, dê o nome “facelets-devmedia” e marque as opções da janela, conforme exibido na Figura 2.

Criando novo projeto web no Eclipse
Figura 2. Criando novo projeto web no Eclipse

Atenção especial para a seção Configuration que exibe o tipo de configuração do projeto que será usada. O Eclipse JEE fornece uma opção específica para o JSF 2.2, que é a versão mais recente e que já traz consigo as bibliotecas do Facelets, logo não precisaremos usar nenhuma ferramenta para gerenciar as dependências como o Maven ou Gradle.

Clique em Next duas vezes, e na tela de definição do “Web Module” marque a checkbox Generate web.xml.... Next mais uma vez e a próxima tela nos trará as configurações específicas do JSF. Na combo Type selecione a opção User Library e após clique no botão de ícone Download library.... A janela da Figura 3 irá aparecer, logo, selecione a opção do JSF Mojarra, clique em Next, aceite os termos de condição e clique em Finish. Quando o Eclipse finalizar o download, clique novamente em Finish e o projeto será criado.

Tela de seleção do JSF 2.2 Mojarra
Figura 3. Tela de seleção do JSF 2.2 Mojarra

Isso será o suficiente para configurar o Facelets e o JSF 2.2 no seu projeto. Navegue até o diretório WebContent > WEB-INF e abra os arquivos faces-config.xml e web.xml. Veja que o próprio Eclipse já configura todas as tags XML do JSF para que possamos começar a usá-lo no projeto.

Criando Templates com o Facelets

A base do Facelets, como vimos, é a possibilidade de construir templates e customizá-los nas páginas implementadoras. Para entender melhor como isso funciona vamos implementar um exemplo simples de tela de login, que terá um cabeçalho e rodapé comuns a todas as páginas (inclusive a de boas-vindas quando ele logar com sucesso). Somente o corpo da página e o título do cabeçalho serão específicos e cada página irá sobrescrever seus conteúdos via template.

Vamos começar pelas páginas do template que serão três: header.xhtml, footer.xhtml e template.xhtml. Crie uma nova pasta no diretório WEB-INF chamada “template”. Em seguida, clique com o botão direito nela e selecione a opção New > HTML File, dê o nome template.xhtml e clique em Finish. No final, abra a página e adicione o conteúdo da Listagem 1 à mesma.


  01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  02           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  03 <html xmlns="http://www.w3.org/1999/xhtml"
  04       xmlns:ui="http://java.sun.com/jsf/facelets">
  05    <head>
  06          <title><ui:insert name="title">Facelets DevMedia</ui:insert></title>
  07          <style type="text/css">
  08                body, input {
  09                      font-family: Segoe UI;
  10                      font-size: 12pt;
  11                }
  12                input {
  13                      padding: 2px;
  14                      margin-top: 5px;
  15                }
  16                input[type='submit'] {
  17                      width: 235px;
  18                }
  19          </style>
  20    </head>
  21    
  22    <body>
  23          <div id="header">
  24              <ui:insert name="header">
  25                <!-- Import de página do cabeçalho -->
  26                <ui:include src="header.xhtml"/>
  27              </ui:insert>
  28          </div>
  29    
  30          <div id="content">
  31            <ui:insert name="content">
  32            </ui:insert>
  33          </div>
  34    
  35          <div id="footer">
  36            <ui:insert name="footer">
  37                <!-- Import de página do rodapé -->
  38                      <ui:include src="footer.xhtml"/> 
  39            </ui:insert>
  40          </div>
  41    </body>
  42 </html>
Listagem 1. Código XHTML da página de template

No início do arquivo temos a importação da biblioteca do Facelets (linha 4) diretamente na tag html. O prefixo ui é padrão para essa biblioteca e, portanto, deve ser seguido. O cabeçalho, definido pela tag head, é igual ao das páginas HTML comuns, porém para que o título seja injetado dinamicamente fazemos uso da tag configurando no atributo name o nome do componente injetável naquele local. O mesmo vale para o a div de corpo da página (linha 30).

Já em relação ao uso dessa mesma tag nas linhas 24 e 36, em vez do atributo name, estamos usando o src, que configura o local do arquivo a ser importado naquela região. Neste caso, o uso desse atributo caracteriza que o conteúdo dos arquivos será sempre estático e igual para todas as páginas que importarem o template e exatamente o que queremos para o restante do cabeçalho e para o rodapé.

Agora já podemos criar os dois outros arquivos que completam o template: header.xhtml e footer.xhtml. Veja nas Listagens 2 e 3 o conteúdo para os mesmos, respectivamente.


  01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  02           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  03 <html xmlns="http://www.w3.org/1999/xhtml">
  04    <style type="text/css">
  05          .header {
  06                width: 99%;
  07                background-color: #302f31;
  08                height: 52px;
  09                padding: 10px;
  10                margin: 10px 0;
  11                margin-right: 2%;
  12          }
  13          .header a {
  14            float: left;
  15            margin-bottom: -10px;
  16          }
  17    </style>
  18    <body>
  19          <div class="header">
  20                <a href="//www.devmedia.com.br/" target="_blank">
  21                      <img src="//www.devmedia.com.br/Imagens/2013/logo.png" 
                          alt="DevMedia" title="DevMedia" />
  22                </a>
  23          </div>
  24    </body>
  25 </html>
Listagem 2. Código XHTML do template de cabeçalho

  01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  02           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  03 <html xmlns="http://www.w3.org/1999/xhtml">
  04    <style type="text/css">
  05          .footer {
  06                background-color: #49c5bf;
  07                width: 99%;
  08                color: white;
  09                height: 22px;
  10                padding: 5px;
  11                margin: 10px 0;
  12          }
  13    </style>
  14    <body>
  15          <div class="footer">
  16                Todos os direitos reservados.
  17          </div>
  18    </body>
  19 </html>
Listagem 3. Código XHTML do template de rodapé

Em ambas as listagens temos código HTML simples apenas para fornecer estilo e estrutura básicos paras divs de cabeçalho e rodapé. O leitor pode executar as páginas diretamente num navegador e verá como eles ficarão no modelo final, junto com o template.

Agora precisamos apenas da página de login que usaremos para implementar esse template. Crie uma nova página XHTML diretamente no diretório WebContent e dê o nome de login.xhtml. Adicione o conteúdo da Listagem 4.


  01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  02           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  03 <html xmlns="http://www.w3.org/1999/xhtml"
  04       xmlns:ui="http://java.sun.com/jsf/facelets"
  05       xmlns:f="http://java.sun.com/jsf/core"
  06       xmlns:h="http://java.sun.com/jsf/html">
  07    <ui:composition template="/WEB-INF/template/template.xhtml">
  08          <ui:define name="content">
  09                <h:form>
  10                      <h:panelGrid columns="2">
  11                           <h:outputText value="Email"/>
  12                           <h:inputText id="email" />
  13                           
  14                           <h:outputText value="Senha"/>
  15                           <h:inputSecret id="senha" />
  16                      </h:panelGrid>
  17                      <h:commandButton value="Logar"/>
  18                </h:form>
  19          </ui:define>
  20    </ui:composition>
  21 </html>
Listagem 4. Código XHTML da página de login

Para informar que estamos utilizando um template incluímos a tag com o seu atributotemplateque define o caminho relativo do diretório onde está o template. Utilizando a tag definimos o que vai preencher o “espaço” do template, no caso apenas o conteúdo do corpo da página. O valor do atributo name deve ser igual ao definido no arquivo de template, senão o Facelets imprimirá uma mensagem de erro de arquivo não encontrado. O restante da listagem é apenas o resto do formulário básico de login.

Pronto, agora é só adicionar a aplicação ao Tomcat, iniciar o servidor e digitar a seguinte URL no browser:


http://localhost:8080/facelets-devmedia/faces/login.xhtml

O resultado pode ser visualizado na Figura 4.

Tela final da aplicação com Facelets
Figura 4. Tela final da aplicação com Facelets

O Atributo jsfc

O Facelets disponibiliza um atributo chamado jsfc que, essencialmente, consegue converter HTML em código JSF. Por exemplo, suponha que você tem um campo simples de texto:


<input type="text" .../>

Com o jsfc você pode facilmente converter esse campo em um equivalente do JSF:


<input type="text" jsfc="h:inputText" .../>

Que é a mesma coisa que criar o campo usando as tags do JSF:


<h:inputText .../>

Esse atributo também pode ser usado para “mapear” componentes do Facelets. Por exemplo, se desejar remover uma parte do código HTML dinamicamente usando a tag do Facelets, pode fazer algo como:


<span jsfc="ui:remove">
  Isso tudo será removido: <h:outputText value="#{pessoa.nome}"/>
</span>

Ou ainda iterar sobre os elementos de uma lista para exibi-los dinamicamente numa tabela HTML via tag , tal como demostrado na Listagem 5.


<table>
  <tr jsfc="ui:repeat" value="#{pessoas}" var="p">
     <td>#{p.nome}</td>
     <td>#{p.sobrenome}</td>
  </tr>
</table>
Listagem 5. Iterando sobre uma lista de valores com ui:repeat e jsfc

O Facelets é uma tecnologia tão poderosa e flexível para criar páginas JSFs e customização de componentes que foi selecionada como a linguagem padrão para criar toda e qualquer página web no JSF 2.2, seja ela baseada em componentes ou não. O nicho de tags disponíveis é pequeno, e por isso torna a absorção do aprendizado mais rápida em comparação com o antigo método: baseado em JSPs. Além disso, inúmeros frameworks e bibliotecas de componentes ricos em JSF, como o Richfaces, Primefaces ou JBoss Seam, implementam a especificação do Facelets por padrão no núcleo de suas APIs, o que a fez atingir a tamanha aceitação que tem hoje.

Na seção Links, o leitor encontra ainda referências para o site oficial da tecnologia, bem como a página de tutoriais oficial da Oracle recheada com inúmeros exemplos e conceitos mais aprofundados sobre o Facelets e seus diversos componentes.