Você está na página 1de 12

1/12

JSF com MyFaces e Tomahawk
Aprenda a utilizar os recursos do MyFaces
FRANCISCO CALAÇA XAVIER
Uma das implementações do JavaServer Faces mais utilizada atualmente é o MyFaces, um projeto 
da   Apache   Software   Foundation   que   vem   crescendo   rapidamente   e   hoje   vai   muito   além   da 
especificação   JSF.   Além   do   MyFaces   Core,   que   é   a   implementação   do   JSF   em   si,   há   vários 
subprojetos, que fornecem componentes adicionais, trazendo suporte a Ajax, vinculação com dados, 
entre outras funcionalidades importantes no desenvolvimento web. 
Neste   artigo   apresentaremos   o   Apache   MyFaces,   e   criaremos   um   exemplo   que   faz   uso   dos 
componentes JSF fornecidos pelo mais popular dos seus subprojetos, o Tomahawk.

Projetos do MyFaces

Muitas das funcionalidades que diferenciam o MyFaces estão nos seus subprojetos.
 Tomahawk – Principal e mais utilizado subprojeto do MyFaces. Possui uma grande quantidade 
de componentes visuais como editores html, menus, tabelas com ordenação etc. Já há versões 
estáveis disponíveis para uso em produção. 
 ADF Faces / Trinidad  – O ADF Faces é a implementação JSF  e conjunto de componentes 
desenvolvido originalmente pela Oracle e doado para o Projeto MyFaces. Possui suporte a Ajax 
e futuramente será chamado Trinidad.
 Tobago – Além de ser um conjunto de componentes JSF que funcionam sobre a implementação 
do MyFaces, o principal objetivo do Tobago é tornar o desenvolvimento de aplicações web mais 
ágil.   O   Tobago   fornece   um   gerenciador   de   layouts   que   organiza   automaticamente   os 
componentes na página, não sendo necessário o uso de tabelas para esse objetivo.
 Sandbox – O projeto Sandbox consiste em componentes de teste do MyFaces, ainda em fase de 
desenvolvimento  e que futuramente  podem fazer  parte do Tomahawk. Alguns componentes 
possuem suporte ao Ajax. Considerado instável pela Apache Software Foundation por se tratar 
de componentes de testes. 

A aplicação de exemplo
Para ilustrar o uso do MyFaces, construiremos uma agenda de contatos, conforme ilustrado na 
Figura 1. O exemplo utiliza vários componentes padrão do JSF (fornecidos pelo MyFaces Core) e 
também vários outros do Tomahawk. 
Observe que na inclusão de novos contatos,  é usado um componente de calendário para informar a 
data de aniversário, conforme mostra a  Figura 2. Note que usamos também um componente de 
menu.   Com   o   Tomahawk,   é   possível   construir   menus   com   submenus   de   forma   rápida.   Outra 
funcionalidade interessante é a ordenação de colunas. Através de cliques nos títulos das colunas da 
2/12

tabela de contatos é possível ordená­las conforme desejado. E à medida que um contato marcado 
como favorito é adicionado, este aparece no menu Favoritos.

Figura 1. A aplicação de exemplo em ação

Para mantermos o foco na programação JSF, não será feito acesso a banco de dados; todas as 
informações dos contatos permanecerão  na memória. Na  Listagem 1  está o código da entidade 
Contato.  Na  Listagem 2, temos  o código da classe  ContatoDao  que  é responsável pela 
inclusão e consulta de contatos. Observe que temos nessa classe o atributo List contatos que é 
static, para que todos os objetos criados a partir desta classe utilizem esta mesma lista (estamos 
aplicando o pattern Singleton). O método  consultarFavoritos()  retorna todos os contatos 
que possuem a propriedade  favoritos=true. O método  consultarAniversariantes()
retorna os contatos que fazem aniversário no dia e mês fornecidos como parâmetros. 
3/12

Figura 2. Inclusão de contatos

Adicionando suporte ao MyFaces Tomahawk


• Para   que   o   MyFaces   Tomahawk   funcione   adequadamente,   é   necessário   utilizar   uma 
implementação   JSF.   Em   nossos   exemplos   estaremos   utilizando   o   MyFaces   como 
implementação JSF. Nada impede ao leitor de utilizar os componentes do Tomahawk junto 
com a implementação de referência da Sun para o JSF. Até o momento de escrita deste 
artigo a versão do Tomahawk que fornece suporte a outras implementações era a 1.1.3. O 
leitor pode acompanhar isto no site myfaces.apache.org.

Deve­se   também   incluir   o   filtro 


org.apache.myfaces.component.html.util.ExtensionsFilter no web.xml: 
   <filter>
      <filter­name>extensionsFilter</filter­name>
      <filter­class>
         org.apache.myfaces.component.html.util.ExtensionsFilter
      </filter­class>
   </filter>
   <filter­mapping>
      <filter­name>extensionsFilter</filter­name>
      <url­pattern>*.faces</url­pattern>
   </filter­mapping>
   <filter­mapping>
      <filter­name>extensionsFilter</filter­name>
      <url­pattern>/faces/*</url­pattern>
   </filter­mapping>

O arquivo completo do web.xml pode ser verificado na Listagem 3. 

Para a utilização dos componentes do tomahawk é necessário também o uso da taglib:
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
4/12

Componentes web do exemplo


Descreveremos  agora  os   componentes  utilizados  em  nossa aplicação.   Veja  também   o  quadro 
“Mais componentes do Tomahawk”.
 
Menu
Para menus, utilizamos a tag  <t:jscookMenu>  com o atributo  layout="hbr". Isso faz 
com   que   o   menu   seja  renderizado   horizontalmente  (para   um  menu   vertical  utiliza­se  “vbr”). 
Usamos também  theme="ThemeOffice"  para que o menu pareça como os do Microsoft 
Office.   Os   temas   disponíveis   são  ThemeIE,  ThemeMiniBlack,  ThemeOffice  e 
ThemePanel.
Para criar um menu deve­se utilizar a tag <t:navigationMenuItem>, definindo o nome do 
menu no atributo  itemLabel.  Veja um exemplo na  Listagem 4,  os menus estão em negrito. 
Observe que os sub­menus são construídos aninhando as tags  <t:navigationMenuItem>. 
O resultado deste menu está Figura 3:

Figura 3. Exemplo de um menu gerado pelo Tomahawk.

Calendário
O   calendário   usado   no   exemplo   é   criado   com   a   tag  <t:inputCalendar>.   Fizemos 
renderAsPopup="true"  para   que   apareça   um   botão   que,   ao   ser   clicado,   mostra   o 
calendário,   e  renderPopupButtonAsImage="true"  para   que   esse   “botão   pop­up” 
possua  uma   imagem  indicativa  do  que será  mostrado.  A  aplicação   desta  tag  pode ser  vista  na 
Listagem 5 com destaque em negrito para a utilização desta tag.
Tabela ordenada
O Tomahawk possui uma versão da tag  <h:dataTable>  do JSF:  <t:dataTable>  que 
possui   mais   funcionalidades   que   a   tag   da   implementação   de   referencia   do   JSF.   Dentre   estas 
funcionalidades podemos citar: ordenação automática de colunas, suporte a eventos java script para 
as linhas, exibição de tabelas  em modo news paper (como um jornal) dentre outras. Em nosso 
exemplo,  para   que   seja   ativada   a   ordenação   automática,   foi   necessário   utilizar   o   atributo 
sortable="true".   Também   é   feita   a   substituição   das   tag’s  <h:column>  por 
<t:column>. O uso dessas tag’s é demonstrado na Listagem 6.

O restante do projeto
O   restante   dos   arquivos   do   nosso   projeto   de   exemplo   é  o   Managed   Bean,   denominado 
GerenciadorContato que se encontra na Listagem 7 e o faces­config.xml que se encontra na 
5/12

Listagem 8. A classe GerenciadorContato possui apenas uma novidade em relação ao JSF 
padrão: a utilização da classe  NavigationMenuItem, no método  getFavoritos(), para 
inclusão dinâmica de contatos no menu Favoritos. 

Conclusões
Como vimos neste e em vários outros artigos da Java Magazine, o uso de JavaServer Faces torna o 
desenvolvimento   web   mais   fácil   e   as   aplicações   mais   ricas   e   interativas   (por   exemplo,   veja   a 
segunda   parte   da   série   “Aplicação   Completa   Java   EE”,   na   Edição   45).   A   utilização   de 
implementações  como  o  Apache  MyFaces,  aliada  ao  uso de  projetos   como  o Tomahawk   ou   o 
Trinidad, completa esta facilidade. Estes projetos trazem para a programação JSF recursos que antes 
só eram possíveis no mundo das aplicações desktop. O Tomahawk, conforme vimos no exemplo, 
possui componentes sofisticados que aumentam a qualidade e a navegabilidade das aplicações web. 

Mais componentes do Tomahawk


Aqui exploramos alguns componentes e funcionalidades adicionais do Tomahawk.

Validação
Existem   vários   validadores   no   Tomahawk.   O   validador   de   endereços   de   e­mail 
(<t:validateEmail>)   verifica   se   um   texto   informado   é   um   e­mail   válido   ou   não   (a 
validade é apenas sintática). Não sendo válido, é enviada como mensagem de erro a 
string definida no  atributo  detailMessage. Veja  um exemplo, onde   o campo a ser 
validado é um <h:inputText>: 

<h:inputText>
<t:validateEmail detailMessage="Não é um email válido."/>
</h:inputText>

O validar de números de cartão de crédito verifica se a quantidade e a estrutura dos 
números informados para o cartão de credito é válida ou não. Veja um exemplo de uso: 

<h:inputText>
<t:validateCreditCard detailMessage='
#{"{0} Não é um cartão de crédito válido."}'/>
</h:inputText>

Não   existindo   um   validador   apropriado,   é   possível   utilizar   expressões   regulares   para 


definir a regra de validação desejada. Por exemplo: 

<h:inputText>
<t:validateRegExpr pattern='\d{5}'
detailMessage='#{"{0} Campo inválido." }'/>
</h:inputText>
6/12

Painel com abas


Os painéis com abas são úteis em formulários web com muitos campos de entrada de 
dados, conforme pode ser visto na Figura Q1.

Figura Q1. Exemplo de painel com abas

Para   a   definição   de   um   painel   com   abas   são   necessárias   duas   tags: 


<t:panelTabbedPane> para a criação da região onde serão renderizadas as abas e 
<t:panelTab label="Nome da aba"> para a aba. Por exemplo: 

<t:panelTabbedPane>
<t:panelTab label="Tab 1">
<! – conteúdo da aba Tab1 -->
</t:panelTab >
<t:panelTab label="Tab 2">
<! – conteúdo da aba Tab1 -->
</t:panelTab >
</t:panelTabbedPane>

Árvore
O Tomahawk possui também o recurso de árvore de dados ou data tree view, conforme 
ilustra   a  Figura Q2  que   foi   extraída   do   site   de   exemplos: 
irian.at/myfaces/tree2HideRoot.jsf.

Figura Q2. Exemplo de uma árvore de dados extraído do site
7/12

A   tag   <t:tree2  clientSideToggle="false"   value="#{managedBean.treeData}"> 


renderiza uma árvore e a Listagem 9 mostra o código do método getTreeData(), também 
extraído do site de exemplos. Este código é responsável por montar a estrutura de dados 
da árvore. Observe o uso da classe  TreeNodeBase. Esta classe possui um construtor 
que   recebe   três   parâmetros:   um   identificador   para   o   nodo,   o   nome   do   nodo   e   um 
booleano que indentifica se o nodo será renderizado como uma folha (true) ou como uma 
pasta (false).Note que estando o atributo  clienteSideToggle  da tag  <t:tree2>  ajustado 
como false a cada clique em um nó da arvore será feita uma nova requisição para busca 
dos dados pois os dados continuarão no servidor.  Estando este atributo ajustado como 
true toda a árvore é trazida para o cliente e a cada clique em um nó não será feita uma 
requisição, pois os dados já estão no cliente (note que isto não é AJAX. Apesar do AJAX 
não realizar requisições, neste caso os dados são trazidos para o browser e implica a não 
necessidade   de   consultas   ao   servidor).  O   site  wiki.apache.org/myfaces/Tree2  fornece 
mais informações sobre as opções possíveis para árvores. 

Html Editor
Um   dos   componentes   mais   interessantes   e   sofisticados   do   Tomahawk   é   o   editor   de 
HTML ilustrado na Figura Q3.

Figura Q3. Exemplo do componente HtmlEditor

O   editor   possui   recursos   dignos   de   qualquer   editor   de   texto   básico   como   negrito, 
sublinhado,   cores   de   fontes   etc.   O   seu   uso   é   bem   simples.   Basta   utilizar   a   tag 
<t:inputHtml> e será renderizado o editor de textos.

Outros componentes
Você   pode   obter   mais   informações   sobre   outros  componentes  do   Tomahawk  no   site 
irian.at/myfaces/home.jsf.  Trata­se de um site que hospeda os exemplos compilados do 
Tomahawk e do SandBox. Estes exemplos podem ser baixados, com o código fonte, a 
partir do site people.apache.org/builds/myfaces/nightly.
8/12

Listagem 1. Classe Contato


package br.com.jm.agenda;

import java.util.Date;

public class Contato implements Comparable<Contato> {

   private int codigo;
   private String nome;
   private String telefone;
   private Date aniversario;
   private boolean favorito;

  //... getters e setters omitidos ...

Listagem 2. Classe ContatoDao


package br.com.jm.agenda;

import java.util.*;

public class ContatoDao {

   private static List<Contato> contatos = new ArrayList<Contato>();

   public void incluir(Contato contato) {
      contatos.add(contato);
   }

   public List<Contato> consultar() {
      return contatos;
   }

   public List<Contato> consultarFavoritos() {
      List<Contato> resultado = new ArrayList<Contato>();
      for (Contato contato : contatos) {
         if (contato.isFavorito()) {
            resultado.add(contato);
         }
      }
      return resultado;
   }

   public List<Contato> consultarAniversanriantes(Date data) {
      Calendar cal = Calendar.getInstance();
      cal.setTime(data);
      int dia = cal.get(Calendar.DAY_OF_MONTH);
      int mes = cal.get(Calendar.MONTH);
      List<Contato> resultado = new ArrayList<Contato>();
      for (Contato cont : contatos) {
         Calendar calAniversario = Calendar.getInstance();
         calAniversario.setTime(cont.getAniversario());
         int diaAniversario = calAniversario.get(Calendar.DAY_OF_MONTH);
9/12

         int mesAniversario = calAniversario.get(Calendar.MONTH);
         if (diaAniversario == dia && mesAniversario == mes) {
            resultado.add(cont);
         }
      }
      return resultado;
   }
}

Listagem 3 web.xml completo


<web­app id="WebApp_ID">
   <display­name>agenda</display­name>

   <filter>
      <filter­name>extensionsFilter</filter­name>
      <filter­class>
         org.apache.myfaces.component.html.util.ExtensionsFilter
      </filter­class>
   </filter>
   <filter­mapping>
      <filter­name>extensionsFilter</filter­name>
      <url­pattern>*.faces</url­pattern>
   </filter­mapping>
   <filter­mapping>
      <filter­name>extensionsFilter</filter­name>
      <url­pattern>/faces/*</url­pattern>
   </filter­mapping>

   <servlet>
      <servlet­name>Faces Servlet</servlet­name>
      <servlet­class>javax.faces.webapp.FacesServlet</servlet­class>
      <load­on­startup>1</load­on­startup>
   </servlet>
   <servlet­mapping>
      <servlet­name>Faces Servlet</servlet­name>
      <url­pattern>*.faces</url­pattern>
   </servlet­mapping>

</web­app>

Listagem 4 menu.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>

<h:outputText styleClass="tituloAplicacao" value="Agenda de Contatos" />
<h:panelGrid width="500px" style="background­color: #cfc">
     <t:jscoo kM en u   layout=" hb r"  theme="T he me Of fi ce " >
          <t:navig at io nM en uI t em   itemLabel =" Ca da st r o" >
               <t:navig at io nM en uI t em   itemLabel =" In cl ui r   Contato"
                    action=" in cl ui r"   />
               <t:navig at io nM en uI t em   itemLabel =" Co ns ul t ar " >
                    <t:navig at io nM en uI t em   itemLabel =" Co ns ul t ar   Todos"
                           action="consultar" actionListener=
 
                  "#{gerenciadorContato.consultar}" />
            <t:navigationMenuItem
               itemLabel="Consultar Aniversariantes de Hoje"
               action="consultar" actionListener=
                  "#{gerenciadorContato.consultarAniversariantes}" />
         </t:navigationMenuItem>
      </t:navigationMenuItem>

      <t:navigationMenuItem itemLabel="Favoritos">
         <t:navigationMenuItems value="#{gerenciadorContato.favoritos}" />
      </t:navigationMenuItem>
   </t:jscookMenu>
10/12

</h:panelGrid>
<f:verbatim>
   <br /><br /><br />
</f:verbatim>

Listagem 5. incluir.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<link href="estilo.css" type="text/css" rel="stylesheet" />
<title></title>
</head>
<body bgcolor="#ffffff">

<f:view>
   <h:form>
      <%@ include file="menu.jsp"%>
      <h:outputText styleClass="titulo" value="Inclusão de Contatos:" />
      <h:panelGrid columns="2">
         <h:outputText value="Nome:" />
         <h:inputText value="#{gerenciadorContato.contato.nome}" />
         <h:outputText value="Telefone:" />
         <h:inputText value="#{gerenciadorContato.contato.telefone}" />
         <h:outputText value="Favorito:" />
         <h:selectBooleanCheckbox
            value="#{gerenciadorContato.contato.favorito}" />
         <h:outputText value="Aniversario:" />
               <t:input Ca le nd ar   renderAs Po pu p= "t r ue "
                    renderPo pu pB ut to nA s Im a ge = "t r ue "
                    value="# {g er en ci ad o rC o nt a to . co n ta t o. a ni v er s ar i o} "   />
         <h:commandButton actionListener="#{gerenciadorContato.incluir}"
            value="Incluir" />
      </h:panelGrid>
   </h:form>
</f:view>
</body>
</html>

Listagem 6. consultar.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<link href="estilo.css" type="text/css" rel="stylesheet" />
<title></title>
</head>
<body bgcolor="#ffffff">

<f:view>
   <h:form>
      <%@ include file="menu.jsp"%>
      <h:outputText styleClass="titulo" value="#{gerenciadorContato.tituloTela}" />
      <t:dataTable cellspacing="0" headerClass="tituloTabela"
         rowClasses="linha1, linha2"
         columnClasses="colE, colC, colC, colC" width="500px"
         sortable="true" value="#{gerenciadorContato.contatos}"
         var="contato">
         <t:column>
            <f:facet name="header">
               <h:outputText value="Nome" />
            </f:facet>
            <h:outputText value="#{contato.nome}" />
         </t:column>
         <t:column>
11/12

            <f:facet name="header">
               <h:outputText value="Telefone" />
            </f:facet>
            <h:outputText value="#{contato.telefone}" />
         </t:column>
         <t:column>
            <f:facet name="header">
               <h:outputText value="Favoritos" />
            </f:facet>
            <h:outputText rendered="#{contato.favorito}" value="sim" />
            <h:outputText rendered="#{!contato.favorito}" value="não" />
         </t:column>
         <t:column>
            <f:facet name="header">
               <h:outputText value="Aniversário" />
            </f:facet>
            <h:outputText value="#{contato.aniversario}">
               <f:convertDateTime pattern="dd/MM/yyyy" />
            </h:outputText>
         </t:column>
      </t:dataTable>
   </h:form>
</f:view>
</body>
</html>

Listagem 7. Classe GerenciadorContato


package br.com.jm.agenda;

import java.util.*;
import javax.faces.event.ActionEvent;
import javax.faces.model.*;
import org.apache.myfaces.custom.navmenu.NavigationMenuItem;

public class GerenciadorContato {
   private Contato contato = new Contato();
   private DataModel contatos;
   private String tituloTela;

   public List getFavoritos() {
      List resultado = new ArrayList();
      ContatoDao cDao = new ContatoDao();
      List<Contato> favoritos = cDao.consultarFavoritos();
      for (Contato cont : favoritos) {
         StringBuilder label = new StringBuilder(cont.getNome());
         label.append(": ");
         label.append(cont.getTelefone());
         resultado.add(new NavigationMenuItem(label.toString(), ""));
      }
      return resultado;
   }
   
   public void consultarAniversariantes(ActionEvent e){
      tituloTela = "Aniversariantes de Hoje";
      ContatoDao cDao = new ContatoDao();
      contatos = new ListDataModel(cDao.consultarAniversanriantes(new Date()));
   }

   public void consultar(ActionEvent e){
      tituloTela = "Contatos da Agenda";
      ContatoDao cDao = new ContatoDao();
      contatos = new ListDataModel(cDao.consultar());
   }

   public void incluir(ActionEvent e) {
      ContatoDao cDao = new ContatoDao();
      cDao.incluir(contato);
      contato = new Contato();
   }
12/12

  //... getters e setters omitidos
}

Listagem 8 faces-config.xml
<faces­config>
   <managed­bean>
      <managed­bean­name>gerenciadorContato</managed­bean­name>
      <managed­bean­class>
         br.com.jm.agenda.GerenciadorContato
      </managed­bean­class>
      <managed­bean­scope>session</managed­bean­scope>
   </managed­bean>

   <navigation­rule>
      <from­view­id>*</from­view­id>
      <navigation­case>
         <from­outcome>incluir</from­outcome>
         <to­view­id>/incluir.jsp</to­view­id>
      </navigation­case>
      <navigation­case>
         <from­outcome>consultar</from­outcome>
         <to­view­id>/consultar.jsp</to­view­id>
      </navigation­case>
   </navigation­rule>
</faces­config>

Listagem 9 exemplo do código Java necessário para montar uma tree


public TreeNode getTreeData() {
    TreeNode treeData = new TreeNodeBase();
    //adicionado a pasta Frank Foo
    TreeNodeBase personNode = new TreeNodeBase("", "Frank Foo", false);
    personNode.getChildren().add(new TreeNodeBase("", "Requires Foo", false));
    TreeNodeBase folderNode = new TreeNodeBase("", "Requires Foo Reviewer", false);
    personNode.getChildren().add(folderNode);
    personNode.getChildren().add(new TreeNodeBase("", "Requires Foo Recommendation", false));
    folderNode = new TreeNodeBase("", "Requires Foo Approval", false);
    personNode.getChildren().add(folderNode);
    folderNode = new TreeNodeBase("", "Requires Bar Processing", false);
    personNode.getChildren().add(folderNode);
    folderNode = new TreeNodeBase("", "Requires Bar Approval", false);
    personNode.getChildren().add(folderNode);

    treeData.getChildren().add(personNode);

    //adicionado a pasta Betty Bar
    personNode = new TreeNodeBase("", "Betty Bar", false);
    return treeData;
}    

Links
myfaces.apache.org
Página oficial do projeto MyFaces
irian.at/myfaces.jsf
Exemplos implementados de componentes do MyFaces

Você também pode gostar