Facelets uma forma mais ágil para construção de telas - Parte I

7 views
Skip to first unread message

Paulo Sérgio da Silva Pacheco

unread,
Apr 4, 2014, 2:37:37 PM4/4/14
to João Johanes, evolucao...@googlegroups.com

Facelets uma forma mais ágil para construção de telas – Parte I

A construção de telas ou camada de apresentação em um sistema MVC seja web ou desktop é uma tarefa complexa e de extrema importância. Nesse post vou comentar e mostrar algum exemplo do Facelets como solução para os desafios existentes nessa etapa especificamente para web.

Com a web cada vez mais presente em nosso dia-a-dia, um fato é que com isso nossos usuários tornam-se mais exigentes em relação a usabilidade, agilidade, performance ou de uma forma bem resumida “o usuário espera uma navegação simples e agradável aonde uma determinado tarefa possa ser concluída em poucos passos e em um curto espaço de tempo”.

Atender as expectativas em relação ao que o usuário espera com o que realmente ele precisa, definir uma estrutura flexível a mudanças sem engessar o desenvolvimento, acessibilidade, portabilidade em múltiplos navegadores, tudo isso e muito mais, num prazo que quase sempre é apertado. Um outro ponto fundamental é manter o time motivado e produtivo em um ambiente que favoreça a criatividade e evolução. Uma equação nada simples de resolver!

Ainda bem que no mundo Java temos varias opções de ferramentas e frameworks para tornar esse trabalho mais produtivo, qualitativo e prazeroso. Gosto muito da idéia de componentes visuais (User Interface Components) com o conceito RAD (Rapid Application Development), adquiri isso na época em que trabalhei com o Delphi, e é por isso que sou fã de carteirinha do JavaServer Faces (JSF), que incorpora isso. Melhor ainda eh usar JSF com Facelets.

Inicialmente podemos considerar o Facelets como outra opção de criação de telas com JSF, substituindo o antigo JSPpor xhtml. Nada contra o JSP, mas o Facelets é um mecanismo mais aderente ao formato de trabalho do JSF principalmente em relação a árvores de componentes e ciclo de requisição. O mais interessante do Facelets é a possibilidade de usar técnicas da Orientação a Objetos para a construção de telas.

Na sequência vou colocar um bocado de código focando na estrutura do Facelets e demonstrando um alternativa no uso de templates. Não me preocupo com configurações complementares de layout (css). 

O suporte a templates permite a definição de uma estrutura visual comum e reaproveitá-la em diversas telas, mantendo o esforço de customização em trechos particulares e específicos de cada tela. Imagine por exemplo um sistema compostos por vários cadastros, cada cadastro possui uma listagem aonde o usuário visualiza a listagem com os dados atuais podendo optar pela edição ou por um novo cadastro. Outra tela seria de formulário de preenchimento, uma vez que o usuário selecionou um item para edição ou então pediu por um novo cadastro essa tela seria carregada. Podemos definir um padrão visual para essas telas:














A definição desse template seria algo próximo ao conteúdo do cadastro.xhtml:
<!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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
  <body>
    <table>
      <tr>
        <td colspan="2">
          <ui:insert name="topo">
            <ui:include src="topo.xhtml"/>
          </ui:insert>  
        </td>
      </tr>

      <tr>
        <td>
          <ui:insert name="menu">
            <ui:include src="menu.xhtml"/>
          </ui:insert>
        </td>
        <td>  
          <ui:insert name="principal" />  
        </td>
      </tr>

      <tr>
        <td colspan="2">
          <ui:insert name="rodape">  
            <ui:include src="rodape.xhtml"/>
          </ui:insert>
        </td>
      </tr>
    </table>  
  </body>  
</html>
cadastro.xhtml

A tag ui:insert define um ponto de substituição no template. Ao utilizar esse template a tela poderia customizar 4 pedaços do cadastro.xhtml, sendo que três já possuem um comportamento default. A área do menu por exemplo, usa a tag ui:include para inserir um fragmento (pedaço) de tela relacionado ao Menu de Opções. A seguir um trecho do fragmento do menu, repare na tag ui:fragment:
<ui:fragment
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
  <h:form>  
    <ul>  
      <li>  
        <h:commandLink action="fornecedores">
          Fornecedores
        </h:commandLink>
      </li>
      ...
    </ul>
  </h:form>
</ui:fragment>
menu.xhtml

A seguir o exemplo de código para implementar a tela com formulário de fornecedores:
<ui:composition template="cadastro.xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
  <ui:define name="principal">
    <h:form>
      <h:inputHidden value="#{fornecedorMB.fornecedor.id}" id="idFornecedor" />
      <h:panelGrid columns="2">
        <h:outputLabel value="Nome" for="iNome" />
        <h:inputText value="#{fornecedorMB.fornecedor.nome}" id="iNome" />

        <h:outputLabel value="Cnpj" for="iCnpj" />
        <h:inputText value="#{fornecedorMB.fornecedor.cnpj}" id="iCnpj" />
      </h:panelGrid>

      <h:messages showDetail="true" showSummary="true" />

      <h:commandButton action="#{fornecedorMB.doSalvar}" value="Salvar" />
      <h:commandButton action="#{fornecedorMB.doExcluir}" value="Excluir" />
    </h:form>
  </ui:define>
</ui:composition>
formFornecedores.xhtml

A tela formFornecedores.xhtml usa a estrutura do cadastro.xhtml, a tag ui:composition define o relacionamento de composição entre a tela e o template. Nesse exemplo a única sobrescrita do template é a área principal, a tag ui:defineé utilizada para sobrepor a definição de ui:insert, no resto da tela as definições são mantidas.

Ok, fica faltando a listagem de fornecedores, o ponto de partida para o cadastro. Um detalhe interessante é que todas listagens tem o mesmo padrão visual, seguindo o seguinte formato:



Vamos definir um outro template, especifico para listagens:
<!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:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
  <body>
    <table>
      <tr>
        <td>
          <h:commandButton value="Novo" action="#{mbean[actionNovo]}" />
        </td>
        <td>
         <h:commandButton value="Pesquisar" action="#{mbean[actionPesquisa]}" />
        </td>
      </tr>

      <tr>
        <td colspan="2">
          <ui:insert name="filtros"/>
        </td>
      </tr>

      <tr>
        <td colspan="2">
          <ui:insert name="tabela"/>
        </td>
      </tr>
    </table>
  </body>
</html>
listagem.xhtml

Nesse template alem de definir o organização visual da tela de listagem, temos a definição de 2 botões, agora como vincular a chamada aos respectivos métodos java no managed bean? O template é utilizado por diversas telas em situações distintas! Pra resolver esse detalhe foram definidos 3 parâmetros que o template deve receber ao ser utilizado: mbeanactionNovo actionPesquisa.

Pra encerrar uma forma de implementação da listagem de fornecedores utilizando os templates cadastro.xhtml elistagem.xhtml:
<ui:composition template="cadastro.xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
  <ui:define name="principal">
    <h:form>
      <ui:decorate template="listagem.xhtml">
        <ui:param name="mbean" value="${fornecedorMB}" />
        <ui:param name="actionNovo" value="doNovoFornecedor" />
        <ui:param name="actionPesquisa" value="doPesquisarFornecedor" />

        <ui:define name="filtros">
          <h:panelGrid columns="2">
            <h:outputLabel value="Nome" for="iNome" />
            <h:inputText value="#{fornecedorMB.filtroNome}" id="iNome"/>
          </h:panelGrid>
        </ui:define>

        <ui:define name="table">
          <h:dataTable id="tableFornecedores"
             value="#{fornecedorMB.fornecedorDM}" var="f">
            <h:column>
              <f:facet name="header">Nome</f:facet>
              <h:commandLink action="#{fornecedorMB.doEditarFornecedor}">
                <h:outputText value="#{f.nome}" />
              </h:commandLink>
            </h:column>

            <h:column>
              <f:facet name="header">Cnpj</f:facet>
              <h:outputText value="#{f.cnpj}" />
            </h:column>
          </h:dataTable>  
        </ui:define>  
      </ui:decorate>  
    </h:form>  
  </ui:define>  
</ui:composition>
listFornecedores.xhtml

Repare que a tela define a composição com o template cadastro.xhtml, mas impõe também um relacionamento com o template listagem.xhtml via a tag ui:decorate. A diferença entre essas tags é que decorate considera o conteúdo xhtml externo aos limites da tag. As tags ui:param atribuem valores para os 3 parâmetros do template definindo assim o comportamento do botão de Novo (Fornecedor) e Pesquisar (Fornecedores).

Um diagrama de classes para representar o relacionamento das telas/fragmentos com os templates:



Bom vou deixar em aberto para outro post a composição de componentes e pedaços de tela, parte do facelets que eu mais gosto!

Para maiores informações sobre a tecnologia acesse o site do projeto: https://facelets.dev.java.net/

A Globalcode disponibiliza 2 mini-cursos que comentam sobre Facelets, acesse MC31 e MC45.

Eder Magalhães 
http://twitter.com/edermag
http://www.yaw.com.br
Postado há 23rd August 2009 por Eder Magalhaes
Marcadores: Eder Facelets JSF YaW
  


--
 
Saudações:
Nome...: PAULO PACHECO
Fixo...: 085 3086 6769
Celular: 085 8888 4498 OI
         085 9702 4498 TIM 
 

Reply all
Reply to author
Forward
0 new messages