Artigo no estilo: Curso

Do que se trata o artigo:

Este artigo abordará alguns recursos bastante interessantes e úteis do JavaServer Faces. Ao longo do texto, estudaremos em detalhes o suporte do JSF a internacionalização, a construção de páginas web baseadas em templates e a interceptação e tratamento, fase a fase, de uma requisição de usuário, dentro de seu ciclo de vida padrão.


Em que situação o tema é útil:

O tema deste artigo é útil para os desenvolvedores web que buscam entender melhor os conceitos que compõem a tecnologia JavaServer Faces. O objetivo é dar solidez de conceito através da aplicaçao prática de todos os fundamentos essenciais da tecnologia, e eliminar com isto uma série de dúvidas ou inseguranças sobre seu real funcionamento, nos bastidores.

JSF e o PrimeFaces – Parte 2:

Este artigo trata de temas muito importantes dentro do desevolvimento de aplicações em Java para a Web. O tratamento das fases de uma requisição web nos dá uma grande flexibilidade no desenvolvimento de soluções web, pois podemos assim interceptar e tratar cada momento particular de uma requisição de usuário, desde sua chegada até a finalização de seu processamento, que resultará em uma resposta. Ao mesmo tempo, a internacionalização é um poderoso recurso que nos possibilita ampliar o número de usuários de nossos sistemas, através da sua disponibilização em diversos idiomas. Por fim, o uso de templates reduz consideravelmente a replicação de código, tornando o design e o desenvolvimento de soluções web mais organizado, enxuto e legível.

No artigo anterior, falamos sobre boa parte dos principais conceitos do JavaServer Faces, além da própria preparação do ambiente de desenvolvimento. Abordamos desde a construção das páginas web até a comunicação destas com entidades específicas da tecnologia JSF, denominadas beans gerenciados. Em detalhes, estudamos estas unidades de código, que representam a ligação entre páginas e o restante do sistema. Estudamos também seu ciclo de vida e entendemos a razão do termo “gerenciado” que os classifica, dado que toda a existência desses objetos em memória é controlada exclusivamente pelo container web – ou servidor de aplicações.

O primeiro artigo também nos deu detalhes sobre o comportamento de cada requisição de usuário, desde que chega ao sistema até o momento em que tem seu processamento finalizado e, então, uma resposta correspondente, a ser enviada de volta para o navegador web de onde a requisição se originou.

Abordamos ainda as estratégias disponíveis para estabelecer o fluxo entre as páginas de um sistema, apresentando a estratégia de mapeamento através de regras de navegação, a partir de outcomes (saídas) pré-definidas.

Finalizamos o artigo com uma breve introdução à API do JSF, que nos permite recuperar o contexto de cada requisição de usuário e, a partir dela, de objetos fundamentais dentro da arquitetura, como aquele que representa a aplicação, os próprios beans gerenciados, a raiz da árvore de componentes de cada página, dentre outros.

Neste artigo, estudaremos outros conceitos elementares deste poderoso framework. Começaremos ilustrando o suporte a internacionalização, principalmente mostrando o quanto é simples e direto trabalhar com este importante recurso em projetos baseados em JSF. Então, passaremos para o tratamento de fases de uma requisição de usuário, levantando e detalhando tudo o que precisamos fazer para que sejamos capazes de interceptar uma requisição em diversos momentos de sua existência na memória. Por fim, apresentaremos o uso de templates, um recurso fundamental no desenho da interface com o usuário em soluções web baseadas em Java. Ao longo de todo o texto, rechearemos o código com componentes da biblioteca PrimeFaces, comentando a respeito de algumas dessas estruturas.

Internacionalização

Um recurso bem interessante do JSF é o suporte a internacionalização. De uma forma bastante direta e simples, o JSF permite que atendamos mais de um idioma em nossas soluções web, e mostraremos como fazê-lo a partir de agora.

O primeiro passo para isso é criarmos arquivos de propriedades que conterão os rótulos que a aplicação exibirá. Assim como nos arquivos de DRM (Data Resource Mapping) em plataformas operacionais móveis como Symbian, ou ainda nos arquivos de recursos de outras mais modernas, como o Android, a estratégia em Java para a Web se repete: através de uma chave única, representamos um mesmo rótulo em idiomas diversos.

Observe a Listagem 1. Nela, observamos o conteúdo de um arquivo de propriedades de nome messages_pt.properties. Esses arquivos guardam elementos do tipo chave-valor, que são carregados em instâncias de mapas (como java.util.HashMap) em tempo de execução. Veja a Listagem 1 e observe o valor guardado pelo identificador “login_username”. Trata-se do texto “Usuário”. Em nossas páginas web, sempre utilizaremos os identificadores definidos nesses arquivos de propriedades ao invés do texto direto que desejamos ver impresso, deixando a recuperação do valor correspondente delegada ao framework.

Listagem 1. Arquivo de linguagem para português (messages_pt.properties).


  # Página de login
  login_usename=Usuário
  login_passwd=Senha
  login_action_go=Entrar
  login_action_clean=Limpar
   
  #Login outcomes
  OUTCOME_LOGIN_SUCCESS=loginSuccess
  OUTCOME_LOGIN_FAILURE=loginFailed

Listagem 2. Arquivo de linguagem para inglês (messages_en.properties).


  # Login page
  login_usename=Username
  login_passwd=Password
  login_action_go=Login
  login_action_clean=Clean
   
  #Login outcomes
  OUTCOME_LOGIN_SUCCESS=loginSuccess
  OUTCOME_LOGIN_FAILURE=loginFailed

Na Listagem 2, observamos outro arquivo de propriedades em que os mesmos rótulos encontrados na Listagem 1 recebem, agora, outros valores, traduzidos desta vez para a língua inglesa. O arquivo, neste caso, é nomeado como messages_en.properties. O leitor atento deve ter identificado que existe uma nomenclatura padrão para nomear estes arquivos de linguagem. Através do sufixo apropriado, identificamos a linguagem para a qual os rótulos de uma aplicação serão traduzidos naquele arquivo. De maneira geral, o formato a ser respeitado é o que se segue:


  <nome do arquivo>_<idioma>.properties

Neste formato, o <idioma> deve ser representado através de duas letras. A Tabela 1 exibe alguns dos identificadores de idiomas que podem ser utilizados.

Linguagem

Identificador

Português

pt

Inglês

en

Alemão

de

Francês

fr

Italiano

it

Japonês

ja

Coreano

ko

Espanhol

es

Sueco

sv

Tabela 1. Identificadores de localização.

Uma vez criados os arquivos de linguagem, o próximo passo é configurarmos o suporte a múltiplos idiomas em nossa solução. Esta é uma característica do JavaServer Faces e deve ser, portanto, mapeada no arquivo de configuração do framework (faces-config.xml). Examinemos a Listagem 3.

Observe o marcador resource-bundle. Nele, definimos um pacote de recursos e o identificamos pela variável labels. Esta variável será usada para acessar todos os rótulos definidos no arquivo de linguagem selecionado pela aplicação, tanto no código-fonte quanto nas páginas web da aplicação.

Foi definida, também, a base do nome dos arquivos de linguagem. Como o próprio nome sugere, este texto corresponderá ao prefixo do nome completo do arquivo, e o seu sufixo será determinado de acordo com a configuração da máquina que hospeda o navegador que está acessando a aplicação. Em configurações regionais norte-americanas, por exemplo, o nome do arquivo de linguagem será uma combinação do nome-base com o sufixo _en, resultando no arquivo br.com.devmedia.jm.messages_en.properties.

Ainda sobre arquivos de linguagem, definimos também a localização padrão e todas aquelas que devem ser suportadas dentro da aplicação. Na Listagem 3, podemos observar esta configuração através dos marcadores locale-config, default-locale e supported-locale. Uma solução web pode ter uma localização padrão e quantas localizações adicionais (suportadas) forem necessárias.

Além de contar com a própria plataforma para, automaticamente, selecionar o arquivo de linguagens correto de acordo com a configuração da máquina cliente, podemos modificar programaticamente a localização a ser considerada para apresentar as mensagens ao usuário. Verificaremos, a partir de agora, como utilizar esses rótulos em nossas páginas web e também como manipular o código-fonte para, programaticamente, alterar a localização e, com isso, o idioma em que as mensagens são exibidas para o usuário.

A partir da declaração que fizemos no arquivo de configuração do JSF, e que pudemos ver na Listagem 3, podemos utilizar a variável labels para acessar todo e qualquer rótulo definido nos arquivos de linguagem. Observe o emprego desta variável na Listagem 4, para definir os textos dos rótulos dos campos de usuário e senha da página de login de nossa aplicação-guia, e também dos botões que disparam as ações de limpeza de dados e login. Pelos identificadores, somos capazes de acessar os valores por eles referenciados. Desta maneira, separamos a declaração de mensagens do sistema da estruturação das páginas propriamente ditas.

Listagem 3. Arquivo de configuração do JSF.


  <?xml version='1.0' encoding='UTF-8'?>
  <faces-config version="2.0"
      xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation=
       "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
   
  <lifecycle>
    <phase-listener>br.com.devmedia.jm.listeners.LoginListener</phase-listener>
  </lifecycle>
   
  <application>
      <resource-bundle>
        <var>labels</var>
        <base-name>br.com.devmedia.jm.messages</base-name>
      </resource-bundle>
      
      <locale-config>
        <default-locale>pt</default-locale>
        <supported-locale>en</supported-locale>
      </locale-config>
        
  </application>
   
  <!-- Declaração das regras de navegação, apresentadas no primeiro artigo da série -->
   
  <!-- Declaração dos beans gerenciados, apresentada no primeiro artigo da série -->
   
  </faces-config>

Listagem 4. Acessando rótulos de um arquivo de linguagem em uma página web.


  <?xml version='1.0' encoding='UTF-8' ?>
  <!DOCTYPE html>
  <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:p="http://primefaces.org/ui" xmlns:f="http://java.sun.com/jsf/core">
   
    <h:head>
      <title>#{labels.login_title}</title>
      <h:outputStylesheet library="css" name="estilos.css" />
    </h:head>
   
    <h:body>
      
      <h:form>
        
        <p:panel id="loginPanel" style="margin: 0px auto; vertical-align: top; 
                 width: 500px; margin-top: 300px;" >
          
          <p:panelGrid columns="2" id="loginFieldsPanel" style="width: 450px; 
                       margin: 0 auto; vertical-align: central">
            
            <h:outputLabel value="#{labels.login_usename}" />
            <p:inputText value="#{mBLogin.user.username}" id="usrname" />
            <h:outputLabel value="#{labels.login_passwd}" />
            <p:password value="#{mBLogin.user.password}" id="passwd" />
          
          </p:panelGrid>
          
          <p:panelGrid columns="3" id="loginActionPanel" style="width: 450px; 
                       margin: 0 auto; vertical-align: central">
            
            <p:commandButton action="#{mBLogin.doLogin()}" id="actionLogin" 
                value="#{labels.login_action_go}" ajax="false" />
            
            <p:commandButton action="#{mBLogin.cleanFields()}" id="actionClean"
                value="#{labels.login_action_clean}" ajax="true" 
                update="usrname passwd" />
            
            <p:commandButton actionListener="#{mBLanguage.changeLanguage}" id="actionLang"
                value="#{labels.login_action_change_switch_pt_en}" ajax="false" />
            
          </p:panelGrid>        
        </p:panel>      
      </h:form>    
    </h:body>
  </html>

Outra maneira de carregarmos uma referência para um arquivo de linguagem é utilizarmos um componente do JSF de dentro da própria página, conforme exibido na Listagem 5. Por esta listagem, observamos o uso do componente <f:loadBundle>, que pertence à biblioteca core do JSF.

Listagem 5. Carregando um arquivo de linguagem em uma página web.


  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE html>
  <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:p="http://primefaces.org/ui" 
        xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
      <title>#{labels.home_title}</title>
      <h:outputStylesheet library="css" name="estilos.css" />
   
      <f:loadBundle var="labels" basename="br.com.devmedia.jm.messages" />
   
    </h:head>
    <h:body>
      
      <p:accordionPanel id="home_accordion" >      
        <p:tab title="" ></p:tab>      
      </p:accordionPanel>
      
    </h:body>
  </html>

De uma maneira geral, navegadores incluem a região de referência no atributo Accept-Language do cabeçalho HTTP, e a implementação JSF tratará de identificar a melhor opção dentre aquelas declaradas como suportadas na lista de locais (Locale) da aplicação. Para obter mais informações sobre o marcador de linguagens, utilizado em cabeçalhos de requisições sobre o protocolo HTTP, consulte a seção Links.

Até aqui, vimos como trabalhar com arquivos de linguagem, carregando-os tanto programaticamente quanto declarativamente. Mas, e se quisermos trocar o idioma da página já com o sistema em execução? Veremos, agora, que isso é possível e, mais que isso, é bastante simples.

Primeiramente, é preciso entender que toda localização (ou configuração regional) pode ser representada, em Java, através de uma instância da classe java.util.Locale. Em JSF, portanto, basta sabermos qual é a entidade responsável por encapsular a configuração regional que será utilizada nas páginas de nosso sistema.

A API do JSF nos dá a classe javax.faces.component.UIViewRoot, que representa a raiz da árvore de componentes da página web em exibição. Esta classe contém, internamente, um atributo do tipo java.util.Locale ...

Quer ler esse conteúdo completo? Tenha acesso completo