Você está na página 1de 48

PARTE 1

DESENVOLVENDO INTELIGENTEMENTE COM JAVASERVER FACES


JavaServer Faces (JSF) um framework de componentes de interface de usurio (UI) para aplicaes web Java 2 Enterprise Edition que, uma vez adotado, permite s empresas migrar de tecnologias ultrapassadas, como: terminais virtuais (VTs) baseados em caracteres, para tecnologias e plataformas atualizadas e baseadas em padres, como JSF e Java. Durante os ltimos 15 anos, a indstria de software viu muitas tecnologias e plataformas aparecerem e sumirem. Normalmente, a utilizao de determinada tecnologia diminui por vrias razes, incluindo moda e competio. Outra razo comum para a queda de certas tecnologias o fato de serem projetadas e mantidas por uma nica empresa, ento os consumidores destas tecnologias so forados a confiar no suporte provido apenas pelos criadores. Sempre que um criador decide tornar obsoleta uma tecnologia em favor de outra soluo mais avanada, o consumidor deixado com uma plataforma desatualizada e sem suporte. O JSF permite s empresas e consumidores aproveitarem as ltimas tecnologias assim que surgem, com o mnimo impacto nas aplicaes JSF existentes. JSF tambm adiciona extremo reuso de funcionalidade e aparncia visual indstria de software. A parte 1 deste livro vai ensin-lo o que JSF, alm de descrever como aprimorar o JSF atravs do desenvolvimento de seus prprios componentes e abrir seus olhos para um novo horizonte.

CAPTULO 1

A FUNDAO DO JSF: COMPONENTES


JavaServer Faces (JSF) um framework de interface de usurio (UI) para aplicaes web em Java. Foi criado para facilitar, de maneira significativa, a escrita e manuteno de aplicaes que rodam em um Java application Server e apresentam suas UIs de volta para um cliente especfico. Especificao do JavaServer Faces Para aqueles, dentre vocs, que no tiveram chance de conhecer JSF antes de ler este livro, este captulo lhes dar uma introduo rpida sua funcionalidade fundamental. Se j for familiarizado com JSF, ainda sim poder encontrar discusses sobre componentes e arquitetura de ciclo de vida interessante, pois estes tpicos so fundamentais para sua compreenso do resto do livro. Este captulo cobrir o desenvolvimento de aplicativos, mostrar um resumo de JSF e como se relaciona com outros frameworks similares, alm de examinar profundamente a arquitetura JSF e seu modelo de componentes. Ao final deste captulo voc dever entender a arquitetura JSF, seus blocos fundamentais e seu ciclo de vida de request. Antes de pular dentro da arquitetura do JSF, vamos definir a audincia para JSF (e, em ltima forma, para este livro). A especificao JSF define os tipos de desenvolvedores que compem a audincia primordial: criadores de pginas, desenvolvedores de aplicaes, criadores de componentes, fornecedores de ferramentas e implementadores de JSF, como mostrado na tabela 1-1.
Tabela 1-1. Tipos de desenvolvedores JSF* Tipo Page author (autor de pginas) Descrio Um page author responsvel pela criao da UI e tem conhecimento de linguagens de markup e script, assim como a tecnologia de apresentao, como JavaServer Pages (JSP). De acordo com a especificao JSF, este tipo de desenvolvedor geralmente no est familiarizado com linguagens de programao como: Java ou Visual Basic. Um application developer, de acordo com a especificao JSF, est a cargo da funcionalidade Server-side de uma aplicao que pode ou no estar relacionada com a UI. Os skills tcnicos de um application developer geralmente incluem Java, Enterprise JavaBeans (EJBs) ou outras tecnologias de servidores. Continuao

Application Developer (desenvolvedor de aplicaes)

PRO JSF E AJAX


Tabela 1-1. Tipos de desenvolvedores JSF* (continuao) Tipo Component writer (criador de componentes) Descrio Um component writer o fornecedor principal de componentes reutilizveis. Este desenvolvedor responsvel pela criao de bibliotecas de componentes que possam ser utilizadas por outros, como o page author. Um fornecedor de ferramentas, como diz o nome, fornece ferramentas que auxiliem o desenvolvedor que cria aplicaes com JSF Um JSF implementer um desenvolvedor que fornece o executvel (ou a implementao de uma especificao JSF) para todos os desenvolvedores definidos anteriormente. Exemplo de implementaes disponveis so: Sun Reference Implementation (RI) (http:// java.sun.com/j2ee/javaserverfaces/) e Apache MyFaces (http:// myfaces.apache.org).

Tools provider (fornecedor de ferramentas) JSF implementers (implementadores de JSF)

* Fonte: a especificao 1.1 do JavaServer Faces.

Em nossa experincia, os page authors e application developers so, normalmente, a mesma pessoa, logo, eles conhecem desenho de UI e linguagens de programao, como Java ou Visual Basic. Neste livro, focalizaremos a maior parte da nossa ateno nos component writers.

RESUMO DAS TECNOLOGIAS DE DESENVOLVIMENTO DE APLICAES


Ao longo de relativamente curta histria dos computadores e do software, o desenvolvimento de aplicaes passou por vrias grandes etapas evolucionrias, todas prometendo aumentar a produtividade e a flexibilidade do desenvolvedor. Estas melhorias tecnolgicas progrediram exponencialmente desde que o primeiro computador foi introduzido, e parece que as tecnologias de computadores e software continuaro a evoluir no mesmo ritmo acelerado no futuro. Nenhum exponencial eterno... mas podemos adiar o eterno. Gordon Moore (famoso pela lei de Moore) Fairchild Camera and Instrument Corporation Durante estes anos de evoluo o perfil de distribuio de uma aplicao, assim como a tecnologia de computadores e software utilizada para desenvolv-la, mudaram.

One-Tier (Um Tier)


No final dos anos 70 e comeo dos anos 80, ocorreu um deslocamento fundamental dos grandes computadores centrais para os computadores pessoais (Personal Computers ou PCs), o qual moveu o poder de controle de umas poucas pessoas para muitas pessoas (qualquer um com um PC). Embora a maioria das aplicaes entregue neste perodo fosse mais poderosa do que qualquer coisa desenvolvida at ento, ela era

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

projetada e desenvolvida para tarefas de um nico usurio (single user) e carecia de colaborao nos dados comuns; neste ponto no existiam bancos de dados centrais ou emails. Aplicaes distribudas ou instaladas desta forma so referidas como aplicaes one tier (Nota de traduo: tambm conhecidas como monolticas). Sob o ponto de vista de manuteno, esta soluo one-tier uma aplicao que reside na mquina de um indivduo que controla a interao com a lgica de negcios. Estas aplicaes one-tier integram todas as trs camadas de aplicao conhecidas (apresentao, lgica de negcios e dados), tornando sua manuteno difcil e o compartilhamento e escalabilidade da informao quase impossveis.

Two-Tier: Cliente-Servidor
As solues two-tier (ou cliente-servidor) se apresentaram no centro do palco nos anos 80 e empurraram as solues one-tier para os arquivos da histria. A arquitetura two-tier, que permite compartilhar dados, mudou a forma como as aplicaes eram desenvolvidas e distribudas. As aplicaes two-tier interagem diretamente com o usurio final; as lgicas de apresentao e negcios so armazenadas no cliente e os dados em um servidor remoto. Esta arquitetura permite a mltiplos usurios acessarem os dados centrais, com aplicaes como: clientes de email (como Microsoft Outlook ou Mozilla Thunderbird). Embora a soluo two-tier resolva o problema de mltiplos usurios acessarem a mesma fonte de dados (data source), tambm tem as suas limitaes, como a falta de flexibilidade do projeto com relao a modificaes ou porte (Nota de traduo: portar, neste contexto, significa mudar de plataforma), a qual, por sua vez, aumenta os custos de manuteno.

Multitier: Aplicaes Web


A prxima fase no desenvolvimento de aplicaes chegou com a Internet e o Web browser, introduzindo a arquitetura three-tier ou multitier. Na soluo one-tier, as lgicas de apresentao, negcios e dados so integradas em uma aplicao monoltica. A arquitetura multitier quebra este tipo de aplicao em trs camadas, permitindo aos desenvolvedores se focalizarem em reas de domnio especfico model (ou modelo acesso aos dados), view (ou viso apresentao) e controller (ou controlador lgica). Este paradigma de programao, representando a diviso entre estas camadas, conhecido como a arquitetura Model-View-Controller (MVC) e foi primeiramente introduzida pela linguagem SmallTalk, espalhando-se pela comunidade de desenvolvedores nos anos 80. Dividir uma aplicao monoltica em camadas em combinao com um cliente padronizado (um Web browser, por exemplo) e um protocolo padronizado de comunicao (Hypertext Transfer Protocol [http]) repentinamente deu aos usurios acesso ubquo (onipresente) s aplicaes centralizadas e familiares, como email via browser (Gmail do Google, por exemplo). As aplicaes no so mais algo que somente poderiam vir em um CD ou atravs de um download. Uma soluo multitier d ao proprietrio da aplicao administrao e manuteno centralizadas, o que lhe permite atualizaes instantneas para todos que a utilizem.

EXPLORANDO

DESENVOLVIMENTO

DE

APLICAES ATUAL

Neste novo mundo de aplicaes multitier, os desenvolvedores necessitam estar atualizados com as tecnologias e padres emergentes, fornecidos atravs de organizaes como o World Wide Web Consortium (W3C) e o Java Community Process (JCP). A indstria est em evoluo, o que bom, mas

PRO JSF E AJAX

tambm pressiona os desenvolvedores de aplicaes a sempre construrem aplicaes multitier competitivas. Se observar uma soluo de software multitier tpica servindo uma empresa de varejo, por exemplo , ver que ela poder incluir suporte a mltiplos agentes, como Web browsers, dispositivos mveis (PDAs) e terminais de vdeo baseados em caracteres (VT, por exemplo o VT100). A figura 1-1 mostra um esquema simples da arquitetura de tal aplicao multitier.

Figura 1-1. Arquitetura comum J2EE para uma soluo tpica multitier servindo uma empresa de varejo.

Neste cenrio, o desenvolvedor de aplicativos obrigado a fornecer no apenas uma aplicao, mas trs. Esta arquitetura contm uma aplicao para a interface Web, outra para o dispositivo mvel e, finalmente, uma para o dispositivo Telnet (um terminal VT). Todas as trs aplicaes usam sua prpria pilha de tecnologias, o que ser um pesadelo de manuteno para o desenvolvedor e o administrador, e podero causar problemas de segurana e escalabilidade. Para o desenvolvedor de aplicaes surge uma questo: Quantas tecnologias terei que aprender para criar uma soluo completa para o meu projeto?

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

Frameworks
Comparados a dez anos atrs, os clientes de hoje possuem demandas muito maiores e requerimentos mais especficos para novos projetos de aplicaes Web. Eles requerem aplicaes Web ricas e mais amigveis, com segurana intrnseca, acessibilidade, internacionalizao, portabilidade etc. As aplicaes multitier devem disponibilizar, de maneira bem sucedida, todas essas caractersticas, no importando a complexidade crescente dos cenrios de falhas adicionais e, tambm, crescentes requisitos de escalabilidade e segurana. A crescente complexidade da criao de aplicaes implica necessidade de simplicidade. At agora, no reino J2EE, no h uma escolha clara de tecnologia para aplicaes Web. As interfaces de programao de aplicaes (APIs), como JSP e servlets, no fornecem abstrao suficiente do trabalho bruto de se implementar uma aplicao multitier. Para atender a estes requisitos e fornecer algum nvel de simplicidade, a indstria evoluiu em uma direo na qual as comunidades open source e as empresas de software esto fornecendo aos desenvolvedores de frameworks para proteg-los da complexidade introduzida pelas aplicaes multitier.

Tapestry, Struts, Tiles, TopLink, Hibernate, ADF UIX


Muitos frameworks possuem as mesmas idias, mas resolvem um problema de maneira diferente e em diferentes camadas de uma aplicao multitier (camada view, camada controller e camada model). Como exemplos de frameworks, temos Struts (um framework controlado por open source); TopLink e Hibernate (frameworks da camada model); Tiles, Tapestry, XUL e ADF UIX (frameworks da camada view). Os benefcios dos frameworks de aplicao so: modularidade, reusabilidade e a inverso de controle (Inversion of Control - IoC), que eles fornecem aos desenvolvedores. Ao encapsular os detalhes de implementao, os frameworks aumentam a modularidade e melhoram a qualidade do software atravs da centralizao do impacto dos detalhes de projeto e implementao. Graas ao ambiente estvel criado pelos frameworks, estes benefcios aumentam o reuso ao permitir que os desenvolvedores criem componentes genricos que podem ser reutilizados em novas aplicaes. Esta reutilizao de componentes de framework aumenta a produtividade do desenvolvedor e a qualidade do software da aplicao. Ao promover o IoC, o framework gerencia a chamada dos mtodos especficos da aplicao em resposta aos eventos gerados pelo usurios.

Nota:

IoC significa que voc registrou alguma parte do seu cdigo com o framework, e ele ir invocar o seu cdigo quando o cliente o requisitar (Nota de traduo: esta caracterstica tambm conhecida como CallBack). Isto tambm referido como O princpio de Hollywood (No nos chame. Ns o chamaremos).

No cenrio de software para varejo (veja a figura 1-1), os frameworks podem ajudar a aumentar a produtividade do desenvolvedor e facilitar a manuteno, mas os frameworks tambm so incompatveis uns com os outros, o que torna a integrao difcil de se lidar. Em contraste, o JSF um framework padro que objetiva resolver esta incompatibilidade.

PRO JSF E AJAX

INTRODUO AO JSF
Resumidamente, JSF um framework de componentes UI para aplicaes J2EE. Antes de iniciarmos a falar sobre componentes UI (e por componentes UI queremos dizer blocos de construo para desenvolvedores, e no os componentes do framework em si), vale a pena discutir o motivo pelo qual voc necessita de mais um framework. JSF tenta, entre outras coisas, resolver os mesmos problemas que os anteriormente mencionados Apache Tapestry e Oracle ADF UIX, ambos frameworks que esto disponveis h algum tempo e se provaram bem sucedidos. O diferencial que o JSF traz, o qual no existem em frameworks similares, o suporte de uma especificao padro (JSR-127). O fato do JSF ser parte da especificao do padro J2EE, torna prioritrio para os maiores fornecedores de ferramentas J2EE do mercado (incluindo Oracle, IBM, Borland e Sun) suport-lo, o que, por sua vez, garantir a sua ampla adoo e suporte das ferramentas. Muitas aplicaes Web ainda esto presas nos anos 90, quando muito esforo era alocado s tarefas de encanamento bsico (nota de traduo: prover infra-estrutura, comunicao entre componentes etc) e no nos componentes de alto nvel (de abstrao). Basicamente, quando h pouca ou nenhuma abstrao sobre o cdigo, o desenvolvimento de aplicaes Web torna-se complicado e difcil de manter. Voc pode investir muito tempo na aplicao para torn-la rica e interativa usando vrias tecnologias, como: applets, plug-ins (Flex), HTML dinmico (DHTML) e JavaScript. Quando utilizadas juntas, estas tecnologias podem resultar em uma aplicao Web poderosa e interativa; mas como voc mantm tal aplicao? Como voc reutiliza o que criou?

Modelo de Componentes
O JSF traz para a mesa o melhor framework J2EE. O JSF veio para simplificar a vida dos desenvolvedores de aplicativos, tornando possvel a eles focalizarem na apresentao, sem a necessidade de conhecer o cdigo e os scripts por baixo dela. Eles sentiro o aumento na produtividade com o JSF ao utilizarem componentes UI que ocultam a maior parte do trabalho bruto de integrao de funcionalidade rica nas aplicaes Web. O objetivo fornecer um caminho fcil para criar UIs a partir de um conjunto de componentes UI reutilizveis. Estes componentes reutilizveis vm em vrias formas com diferentes funcionalidades, desde componentes de layout (como o layout de uma pgina inteira) at botes simples. Os desenvolvedores de aplicaes podem utilizar estes componentes para criar uma pgina e aninhar componentes UI, uns dentro dos outros, para obter o efeito desejado; por exemplo, aninhar campos de texto e botes em um componente de layout de linha (row layout) renderizar os componentes aninhados em uma nica linha no cliente. Esta estrutura de componentes aninhados freqentemente conhecida como relacionamento parent-to-child (pai para filho) e visualizada como uma hierarquia de componentes UI. Esta hierarquia de componentes UI representa a descrio de uma pgina JSF em runtime.

Modelo de Navegao
O JSF fornece um modelo de navegao declarativo, o qual permite aos desenvolvedores de aplicaes o ajuste das regras de navegao de modo a definir a navegao de uma view para outra em uma aplicao Web. As regras de navegao no JSF so definidas dentro do arquivo de configurao do JSF, facesconfig.xml, e so direcionadas a cada pgina. O exemplo de cdigo 1-1 mostra uma regra de navegao configurada no faces-config.xml.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES Exemplo de Cdigo 1-1. Regras de Navegao Configuradas no faces-config.xml. <navigation-rule> <from-view-id>/login.jspx</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/result.jspx</to-view-id> </navigation-case> </navigation-rule>

No exemplo de cdigo 1-1, uma regra criada de modo que a partir de uma view, login.jspx, no caso de um resultado success (sucesso), o usurio ser direcionado a uma pgina chamada result.jspx. O resultado o valor de retorno de uma ao realizada na aplicao, como um boto sendo pressionado. No JSF, uma ao anexada ao UIComponent, o que permite um controle fino sobre a pgina. Estas aes podem ter sua prpria regra de navegao ou compartilhar a mesma regra.

Ciclo de Vida de Aplicao


Outro benefcio que os desenvolvedores de aplicao iro descobrir quando utilizarem JSF que o framework auxilia a gerenciar o estado da UI atravs dos requisitos ao servidor. Ao invs de tomar conta das selees feitas pelo usurio e pass-las de pgina em pgina, o framework cuidar disto para voc. O framework JSF tambm possui processos intrnsecos em seu ciclo de vida para lhe auxiliar com a validao, converso e atualizao dos modelos. Como um bnus extra, o JSF fornece um modelo simples para enviar eventos gerados pelo cliente para o cdigo de aplicao no servidor.

Desenvolvimento de Aplicaes com o JSF


Um dos diferencias chave do JSF sua arquitetura, projetada para ser independente de protocolos especficos e de cdigo, de tal forma que permite aos desenvolvedores anexarem qualquer tecnologia de renderizao aplicao JSF. No JSF o RenderKit o responsvel pela apresentao da aplicao JSF, renderizando o cdigo para o cliente. Voc pode definir um RenderKit para qualquer tipo de cdigo (HTML, DHTML, Telnet/modo caracter, e, eventualmente, SVG, Flash, XUL etc) e utiliz-lo para exibir uma pgina JSF. Esta separao entre a descrio da pgina (hierarquia de componentes UI) e a renderizao do cdigo um diferencial-chave que resulta em flexibilidade para o desenvolvedor de componentes, enquanto protege o desenvolvedor de aplicao das mudanas isoladas na camada de renderizao. Ao invs de ter que aprender e implementar as diferentes tecnologias de renderizao para resolver um problema comum, os desenvolvedores de aplicao podem utilizar componentes customizados JSF para criar aplicaes voltadas para diferentes browsers, assistentes pessoais (PDAs) e outros, com um modelo de programao comum: JSF e Java. Aplicando este novo conhecimento sobre JSF no exemplo prvio da figura 1-1, a soluo de varejo, a arquitetura poderia ser similar figura 1-2.

10

PRO JSF E AJAX

Figura 1-2. A arquitetura J2EE utilizando JSF para uma soluo multitier tpica, servindo uma empresa de varejo.

Nesta arquitetura, apenas uma aplicao est servindo trs diferentes agenes usando trs diferentes RenderKits - Hypertext Markup Language (HTML), Wireless Markup Language (WML) e Telnet. Na prtica, a aplicao provavelmente seria composta de trs pginas diferentes mas com uma diferena principal; todas seriam construdas com a mesma tecnologia - JSF e Java. Isto poupar tempo de desenvolvimento e reduzir a manuteno. Alm disto, e talvez mais importante, o JSF estabelece padres, os quais so criados para serem utilizados pelas ferramentas (como JDeveloper da Oracle, Studio Creator da Sun e plug-ins para Eclipse, como Exadel Studio) para fornecerem aos desenvolvedores a facilidade de uso h muito tempo sonhada pela comunidade de desenvolvedores J2EE.

Arquitetura do JSF
Visto de um satlite, o JSF implementa o que conhecido como padro Model 2, o qual baseado na arquitetura MVC. Se observar como o padro Model 2 aplicado em uma aplicao JSF, ver que ele consta de trs elementos - a view, o modelo de navegao e a lgica da aplicao, como na figura 1-3.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

11

Figura 1-3. Uma arquitetura MVC com JSF (Model 2).

Model (Modelo)
Com o JSF o conceito de managed bean (bean gerenciado) foi criado. O managed bean a cola da lgica da aplicao cdigo de apoio (backing code) ou bean de apoio (backing bean. Os managed beans so definidos no aquivo faces-config.xml e do ao desenvolvedor de aplicao acesso total a todos os mtodos mapeados do backing bean. Este conceito de IoC bem sucedido em frameworks, como Spring, HiveMind e o Oracle ADF model binding (JSR-227). A caracterstica de managed bean responsvel pela criao dos backing beans ou outros beans, como Data Access Objects (DAO). No JSF, um backing bean um objeto Java simples (POJO) com nenhuma dependncia de interfaces ou classes especficas de implementaes. O previamente mencionado JSF controller o FacesServlet no est ciente de qual ao foi tomada; ele est ciente apenas do resultado de uma ao em particular e ir utiliz-lo para decidir para onde navegar. No JSF o componente que fica ciente de qual ao ou mtodo devem ser invocados no caso de um evento de usurio. O Exemplo de Cdigo 1-2 mostra um managed bean definido no arquivo faces-config.xml. Exemplo de Cdigo 1-2. Um Managed Bean Definido no Arquivo faces-config.xml <managed-bean> <managed-bean-name>sample</managed-bean-name> <managed-bean-class> com.apress.projsf.ch1.application.SampleBean </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>

12

PRO JSF E AJAX

O Exemplo de Cdigo 1-2 define um backing bean, sample, que aponta para uma classe chamada com.apress.projsf.ch1.application.SampleBean. O <managed-bean-scope> indica onde a instncia deste bean ser armazenada depois de criada request, session ou application. O exemplo de cdigo tambm tem uma opo none para bean que no deve ser armazenado em escopo algum, mas, ao invs disto, ser instanciado novamente em cada acesso. A tabela 1-2 lista todos os escopos disponveis.
Tabela 1-2. Escopos de Managed Beans Escopo de Managed Bean None Request Session Application Descrio A instncia ser criada para cada chamada do mtodo A instncia ser criada para cada novo request A instncia ser criada no request inicial e armazenada na sesso do usurio A instncia ser criada no request inicial e armazenada na aplicao Web

View (Viso)
A camada view do JSF descreve o layout pretendido, o comportamento e a renderizao da aplicao. Uma das peas-chave de uma aplicao JSF o UIComponent. UIComponents so a base da camada view do JSF e representam comportamento e estrutura de uma aplicao. Um desenvolvedor dever utilizar estes UIComponents para criar uma aplicao atravs do aninhamento de componentes uns dentro dos outros. Esta estrutura aninhada ser representada, em tempo de execuo (runtime), por uma hierarquia de componentes, como mostrado na figura 1-4, a qual, por sua vez, representa a view ou UI, de maneira semelhante ao desenvolvimento de uma aplicao baseada em Swing.

Figura 1-4. Da descrio da p gina hierarquia de componentes JSF.

A descrio de pgina default da especificao JSF JSP, mas nada existe na especificao JSF que impea um implementador de fornecer descries de pginas alternativas, como Extensible Markup Language (XML), WML ou HTML. Utilizar JSP como descrio de pgina tem seus lados bom e mau. No lado bom, uma soluo popular e conhecida; como tal, aprender como criar aplicaes JSF e JSP representa uma pequena curva de aprendizado para a maioria dos desenvolvedores J2EE. Adicionalmente, como um bnus, a adoo de JSF como a tecnologia de view para novas aplicaes web boa. A

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

13

conseqncia que o JSF tem dependncia de JSP, de tal forma que necessrio trabalhar com ciclos de vida diferentes de uma aplicao que parcialmente JSP e parcialmente JSF. Mais adiante neste captulo (veja a seo JSF e JSP) falaremos sobre estas diferenas e sobre o impacto que tm nas aplicaes construdas com a sintaxe JSP e componentes JSF.

Controller (Controlador)
O JSF vem com um controller simples FacesServlet. O FacesServlet age como um despachante, controlando o fluxo de navegao e despachando requests para as pginas JSF apropriadas.

Um Framework de Interface de Usurio Baseado em Componentes


Agora que j arrumamos o palco para o livro, hora de focalizarmos nas partes que diferenciam o JSF de outras tecnologias antigas: UIComponents. O JSF um framework baseado em componentes UI, no qual componentes, como HtmlDataTable e HtmlPanelGrid, podem ser visualizados como blocos prfabricados que permitem aos desenvolvedores de aplicao produtivamente construir aplicaes complexas com componentes reutilizveis. Ele tambm permite aos desenvolvedores de aplicao focalizarem na lgica da aplicao, ao invs da criao de funcionalidades ricas e dinmicas.

Nota:

O JSF todo componentes e componentes reutilizveis! O JSF foi divulgado primeiramente em Maro de 2004 e teve um release subseqente 1.1, em agosto de 2004. A JSR inicial (JSR-127) foi substituda pela JSR-252, a qual trouxe o release do JSF 1.2.

O JSF consiste de cinco blocos fundamentais: UIComponent: O UIComponent responsvel pelo comportamento e por acessar o modelo de dados. Renderer: O Renderer est a cargo de apresentar o cdigo de markup para o cliente para uma famlia de componentes. RenderKit: uma biblioteca de Renderers com uma tecnologia comum de renderizao (HTML, por exemplo). Subclasse de componente especfica para um renderer: A subclasse de componente especfica para um renderer uma classe de convenincia e representa facetas e atributos especficos para um renderer. Tag JSP: A linguagem de descrio de pginas default do JSF o JSP, logo, o JSF necessita seguir o contrato do JSP e fornecer tags JSP representando cada componente JSF.

O JSF enderea a idia de separao clara entre a lgica de aplicao e a apresentao visual atravs de uma separao forte da UI e do modelo de dados. O Renderer o responsvel pelo cdigo markup renderizado para o cliente e o UIComponent o responsvel pelo comportamento e por acessar o modelo de dados. A figura 1-5 mostra a separao da UI, comportamento e modelo de dados.

14

PRO JSF E AJAX

Figura 1-5. Separao da UI, do comportamento e do modelo de dados.

Para ilustrar o benefcio de separar a UI e os modelos de dados, vamos ver um exemplo do elemento comum de formulrio HTML <select> . Este elemento de lista possui um atributo multiple que altera o comportamento de seleo simples para mltipla seleo de opes. Este modelo no tem separao de renderizao e comportamento. Para que um desenvolvedor de aplicao possa alterar o comportamento do elemento de simples seleo para mltipla seleo, ele deve fazer um ajuste simplesmente alterar o atributo multiple. Entretanto, isto ter um impacto enorme na lgica de aplicao, j que os valores passados pelo cliente agora sero representados por uma lista de chave-valor, ao invs de apenas um nico par chavevalor. Os componentes UI UISelectOne e UISelectMany so bons exemplos de separao clara entre comportamento e aparncia. Por exemplo, o UISelectOne tem um comportamento distinto para selecionar um valor nico a partir de vrias opes, e o UISelectMany tem um comportamento para selecionar muitos valores de uma lista de opes. O componente UISelectOne tem trs tipos de renderers Listbox, Radio e Menu. Alterar a aparncia de Radio para Menu no afetar o comportamento da aplicao. Entretando, se os desenvolvedores de aplicao desejarem alterar o comportamento de um componente de seleo mltipla, podem substituir o componente JSF UISelectOne pelo componente JSF UISelectMany ao invs de simplesmente alterar um atributo no cdigo da pgina, como fariam com o elemento <select> diretamente. Esta separao clara entre alterar o comportamento de um componente JSF e alterar sua aparncia d aos desenvolvedores de aplicao melhor entendimento do impacto de suas alteraes quando modificarem a definio da pgina. A figura 1-6 ilustra o UIComponent e trs RenderKits com aparncias diferentes.

Figura 1-6. O UISelectOne e seus renderers.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

15

Uma boa regra para seguir , antes de iniciar um projeto de componentes, pesquisar na Web componentes prontos. Na maioria dos casos voc, provavelmente, vai resolver escrevendo um novo Renderer para um componente j existente, e j existe um bom nmero de componentes. Se no conseguir encontrar o componente que est procurando, ento dever criar o seu prprio. Para criar um novo componente voc deve estar certo de que ele introduz um novo comportamento, funcionalidade ou definio, e que o componente tem um comportamento diferenciado do lado do servidor. Se o componente existe e voc apenas necessita de uma nova aparncia, ento crie um novo Renderer (por exemplo para usar Ajax com um componente de entrada de dados). Vamos ver as diferentes partes que formam um componente JSF.

UIComponent
A base de todos os componentes JSF so as classes abstratas UIComponent e UIComponentBase. A classe UIComponent (javax.faces.component.UIComponent) define o contrato comportamental e informao de estado para todos os componentes, e a classe UIComponentBase (javax.faces.component.UIComponentBase) uma classe de convenincia que implementa quase todos os mtodos da classe UIComponent. Uma descrio simples de um UIComponent um JavaBean normal com properties, events e listeners. A especificao JSF define um conjunto de subclasses padres de UIComponent,ou superclasses comportamentais (UISelectOne e UISelectMany, por exemplo), que estendem a classe UIComponentBase. Na maioria dos casos os criadores de componentes iro estender essas subclasses padres de UIComponent. Entretanto, eles podem derivar a classe UIComponentBase tambm. Um componente JSF consiste de um UIComponent e um ou mais Renderers. importante entender que as subclasses padres de UIComponent definem apenas comportamentos genricos, independentes de renderer, como UISelectOne. A tabela 13 resume os UIComponents comportamentais padres e listas suas subclasses de convenincia associadas, renderer types e tags JSP.
Tabela 1.3. Componentes Fornecidos pela Implementao JSF*. UI Component UIColumn UICommand UIData UIForm UIGraphic UIInput Renderer-Specific Class null** HtmlCommandButton HtmlCommandLink HtmlDataTable HtmlForm HtmlGraphicImage HtmlInputHidden HtmlInputSecret HtmlInputText HtmlInputTextArea UIMessage UIMessages UIOutput HtmlMessage HtmlMessages HtmlOutputFormat HtmlOutputLabel Button Link Table Form Image Hidden Secret Text Textarea Message Messages Format Label Renderer Type Syntax/JSP Tag <h:column> <h:commandButton> <h:commandLink> <h:dataTable> <h:form> <h:graphicImage> <h:inputHidden> <h:inputSecret> <h:inputText> <h:inputTextarea> <h:message> <h:messages> <h:outputFormat> <h:outputLabel> Continuao

16

PRO JSF E AJAX

Tabela 1.3. Componentes Fornecidos pela Implementao JSF*. (continuao) UI Component Renderer-Specific Class HtmlOutputLink HtmlOutputText UIPanel UIParameter UISelectOneBoolean UISelectItem UISelectItems UISelectMany HtmlPanelGrid HtmlPanelGroup null* HtmlSelectBooleanCheckbox Checkbox null null HtmlSelectManyCheckbox HtmlSelectManyListbox HtmlSelectManyMenu UISelectOne HtmlSelectOneListbox HtmlSelectOneMenu HtmlSelectOneRadio UIViewRoot null Checkbox Listbox Menu Listbox Menu Radio Renderer Type Syntax/JSP Tag Link Text Grid Group <h:outputLink> <h:outputText> <h:panelGrid> <h:panelGroup> <h:parameter> <h:selectBooleanCheckbox> <h:selectItem> <h:selectItems> <h:selectManyCheckbox> <h:selectManyListbox> <h:selectManyMenu> <h:selectOneListbox> <h:selectOneMenu> <h:selectOneRadio> <f.view>

* Fonte:Especificao do JavaServer Faces 1.1 ** Este componente no possui um renderer associado.

Para cada combinao de UICompontent e Renderer, existe uma subclasse especfica para o renderer, tambm chamada de classe de convenincia (convenience class). Uma implementao padro de JSF, como a Sun RI ou o runtime do MyFaces, vem com um conjunto de renderers para HTML (fornecidos pelo RenderKit padro de HTML) e um conjunto de subclasses especficas para o renderer HTML, como HtmlSelectOneRadio.

Subclasse de Componente Especfica para um Renderer


Na maioria dos casos, esta subclasse cria uma instncia do componente em runtime. Como seu nome diz, esta subclasse permite acesso aos atributos especficos do renderer em um componente JSF, como: style, disabled, tooltip e outros, fornecendo getters e setters de propriedades para todos estes atributos. Em conjunto com o atributo binding no tag JSP do JSF, esta subclasse permite aos desenvolvedores de aplicao usar setters de propriedade JavaBean para alterar atributos especficos do renderer no componente em runtime. Embora isto funcione e seja uma ferramenta til para prototipagem, ns recomendamos que, quando possvel, os desenvolvedores de aplicao evitem modificar os atributos especficos do renderer a partir da lgica de aplicao do backing bean, utilizando, ao invs disto, as superclasses comportamentais do componente. Se os desenvolvedores de aplicao utilizarem a classe ancestral ao invs da classe de convenincia, eles no necessitaro modificar o cdigo do backing bean quando o componente JSF for alterado para utilizar um componente especfico de renderer, diferente na definio da pgina, como mudar de HtmlSelectOneRadio para HtmlSelectOneListbox. O cdigo do backing bean somente necessita ser alterado quando a superclasse comportamental tambm alterada, como mudar de HtmlSelectOneRadio para HtmlSelectManyList.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

17

Esta subclasse opcional, mas uma boa prtica fornec-la juntamente com o componente JSF, uma vez que, s vezes, os desenvolvedores de aplicao possam desejar utiliz-la por convenincia, e para escritores de componentes difcil saber se os desenvolvedores de aplicao tentaro us-la. Uma vez que esta classe de convenincia estende o UIComponent e a superclasse comportamental (UISelectOne, por exemplo) em runtime, a instncia do componente no somente conter informao disponvel nessa classe de convenincia como tambm informao estendida das classes UIComponent. Se olhar para o modelo de herana utilizado pelo JSF para criar uma instncia de um componente, parecer como a figura 1-7.

Figura 1-7. A herana de UIComponent.

Este modelo permite acesso programtico a todas as propriedades e atributos definidos pelas diferentes classes que formam o componente. Como mencionado anteriormente, a classe UIComponentBase contm acordos comportamentais para todos os componentes, a subclasse UISelectOne contm propriedades e mtodos especficos para o seu comportamento (selecionar apenas um, por exemplo), e a subclasse especfica para o renderer (HtmlSelectOneListbox, por exemplo) contm getters e setters para todos os atributos especficos para o renderer, como tambm o rendererType de um componente em particular.

Utilizando uma Subclasse Especfica de Renderer


O Exemplo de Cdigo 1-3 ilustra o benefcio de utilizar uma superclasse comportamental ao invs da classe de convenincia para manipular a pgina em runtime. O primeiro pedao do cdigo ilustra uma pgina com um componente selectOneRadio simples com trs opes e um commandButton. Exemplo de Cdigo 1-3. Um JSF selectOneRadio Ligado a umaSsubclasseEespecfica de Renderer. <h:form> <h:selectOneRadio binding=#{sample.selectOneRadio} > <f:selectItem itemLabel=Jonas itemValue=jonas.jacobi /> <f:selectItem itemLabel=John itemValue=john.fallows /> <f:selectItem itemLabel=Duke itemValue=java.dude /> </h:selectOneRadio> <h:commandButton value=Select Duke actionListener=#{sample.onAction} /> </h:form>

18

PRO JSF E AJAX

Na tag JSP selectOneRadio, ou custom action (ao customizada), o atributo binding recebe uma expresso de ligao #{sample.selectOneRadio}. Esta expresso indica uma propriedade de um backend JavaBean selectOneRadio que, por sua vez, est ligada instncia do UIComponent criada por este tag JSP. O Exemplo de Cdigo 1-4 mostra o backend JavaBean, ou o managed bean, que contm a lgica da pgina que, em runtime, selecionar a opo default no componente selectOneRadio para java.dude, sempre que o usurio clicar o command button. Exemplo de Cdigo 1-4. Um Backing Bean Utilizando a Subclasse HtmlSelectOneRadio package com.apress.projsf.ch1.application; import javax.faces.event.ActionEvent; import javax.faces.component.html.HtmlSelectOneRadio; public class SampleBean { public void onAction( ActionEvent event) { _selectOneRadio.setValue(java.dude); } public void setSelectOneRadio( HtmlSelectOneRadio selectOneRadio) { _selectOneRadio = selectOneRadio; } public HtmlSelectOneRadio getSelectOneRadio() { return _selectOneRadio; } private HtmlSelectOneRadio _selectOneRadio; } No Exemplo de Cdigo 1-4, o managed bean est utilizando a subclasse especfica de renderer HtmlSelectOneRadio. Se os desenvolvedores de aplicao quiserem alterar a UI e substituir o componente selectOneRadio pelo selectOneMenu na pgina, uma exception do tipo class cast ser levantada em runtime. O desenvolvedor de aplicao pode evitar isto utilizando a classe ancestral do componente selectOneRadio - UISelectOne. O Exemplo de Cdigo 1-5 mostra como a pgina e o cdigo-fonte do managed bean seriam de acordo com a recomendao.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

19

Exemplo de Cdigo 1-5. Um JSF selectOneRadio Ligado a uma Superclasse Comportamental <body> <h:form> <h:selectOneRadio binding=#{sample.selectOne} > <f:selectItem itemLabel=Jonas itemValue=jonas.jacobi /> <f:selectItem itemLabel=John itemValue=john.fallows /> <f:selectItem itemLabel=Duke itemValue=java.dude /> </h:selectOneRadio> <h:commandButton value=Select Duke actionListener=#{sample.onAction} /> </h:form> </body> O Exemplo de Cdigo 1-5 contm a mesma descrio de pgina, exceto por um pequeno ajuste na expresso de value-binding. Para ser mais genrico, o nome do mtodo do managed bean foi alterado para selecOne, ao invs de selectOneRadio, logo, a expresso na descrio de pgina foi alterada para referenciar um nome de propriedade do backend bean mais genrico, como mostrado no Exemplo de Cdigo 1-6. Exemplo de Cdigo 1-6. O Novo Backing Bean Utilizando a classe UISelectOne. package com.apress.projsf.ch1.application; import javax.faces.event.ActionEvent; import javax.faces.component.UISelectOne; public class SampleBean { public void onAction( ActionEvent event) { _selectOne.setValue(java.dude); } public void setSelectOne( UISelectOne selectOne) { _selectOne = selectOne; } public UISelectOne getSelectOne() { return _selectOne; } private UISelectOne _selectOne; }

20

PRO JSF E AJAX

O novo managed bean est aproveitando a herana de componentes para tornar as alteraes de UI mais agnsticas. Ao invs da classe de convenincia HtmlSelectOneRadio, ele utiliza a superclasse comportamental UISelectOne. Os desenvolvedores de aplicao podem agora mudar para outro componente na mesma famlia de componentes sem temer a quebra da lgica da aplicao.

Acessando Atributos Especficos do Renderer


No exemplo anterior, ns alteramos programadamente a propriedade value no componente UISelectOne, a qual definida pela superclasse comportamental. Mas como um desenvolvedor de aplicao tem acesso aos atributos especficos do renderer, se a subclasse especfica dele no foi fornecida ou (como no Exemplo de Cdigo 1-6) no foi utilizada? Todos os atributos e propriedades so acessados por um Map centralizado que pode ser utilizado a partir de qualquer clase UIComponent e subclasses, atravs de uma propriedade chamada attributes, como mostrado no Exemplo de Cdigo 1-7. Exemplo de Cdigo 1-7. Utilizando o Mapa de Atributos de Componente para Atualizar um Atributo Especfico do Renderer // Renderer-specific attribute example Map attrs = selectOne.getAttributes(); attrs.put(style, font-face:bold); O Exemplo de Cdigo 1-7 mostra como um desenvolvedor pode acessar atributos sem utilizar uma superclasse especfica de renderer. Os escritores de componentes podem introduzir tambm uma interface para os mtodos de atributos especficos de um renderer, implementados por cada subclasse especfica de renderer.

Salvando e Recuperando o Estado


Uma parte crucial da criao de aplicaes Web salvar estado. Pegue um carrinho de compras tradicional, baseado em HTML, como exemplo. Neste caso, o desenvolvedor de aplicao tem que armazenar as selees de produto do usurio e persistir esta informao at que ele finalize a compra. Na maioria dos casos, uma aplicao de carrinho de compras criada com mltiplas pginas, de modo que o estado de cada pgina deve ser salvo at que o comprador finalize a compra. Este estado armazenado em campos hidden dentro de formulrio, armazenada na sesso ou passada como request para a prxima pgina. Aqueles que j lidaram com isto sabem que no uma tarefa trivial. O gerenciamento de estado um dos benefcios primrios do uso de JSF para criar aplicaes. O JSF fornece manuseio de estado de UI automtico atravs de uma classe chamada StateManager, que salva e recupera o estado para uma view em particular (hierarquia dos UIComponents) entre requests no servidor. Cada UIComponent salva e recupera seu prprio estado interno quando requisitado pelo StateManager; o StateManager por si salva e recupera o estado associado com a estrutura da hierarquia do UIComponent. Se um UIComponent estiver marcado como transient, ento ser omitido da estrutura pelo StateManager, sendo removido da rvore UIComponent ao final do request. Existem duas alternativas para armazenar o estado de uma view no lado cliente ou no lado servidor. Por default, o estado salvo no servidor. A implementao Server-side (lado do servidor) suportada pelas especificaes JSP e Servlet, mas o JSF lida com os detalhes de como isto funciona. Uma classe chamada

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

21

ResponseStateManager, a qual criada e gerenciada pelo RenderKit, gerencia a preservao de estado do lado cliente (client-side). A preservao de estado client-side depende no apenas da implementao JSF, mas tambm muito da linguagem de marcao enviada para o cliente e como o estado pode ser gerenciado por ele. Usando HTML como linguagem de marcao, o estado armazenado tipicamente em um campo hidden de formulrio. Nota: Embora o JSF 1.1 mantenha o nome do estado da view em um campo hidden, o JSF 1.2 agora padronizou o nome como javax.faces.ViewState, de modo que mecanismos alternativos de postback, como Ajax, possam se integrar mais facilmente ao ciclo de vida do JSF.

Uma das desvantagens de salvar o estado na sesso do usurio o consumo de memria. Se a escalabilidade um problema para os desenvolvedores de aplicao, a implementao client-side evitar que o consumo de memria saia pelo teto e acrescentar uma vantagem em ambientes com cluster. Mas, desde que o estado deva ser enviado de volta e voltar novamente entre o cliente e o servidor, o tempo de resposta pode aumentar. Voc pode configurar o mtodo de preservao de estado, como mostrado no Exemplo de Cdigo 1-8, no arquivo descritor de deployment da aplicao WEB-INF/web.xml atravs do parmetro STATE_SAVING_METHOD para client ou server. Exemplo de Cdigo 1-8. Alterando o Mtodo de Preservao de Estado no Deployment Descriptor <context param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context param>

Famlia de Componentes e Tipo de Componente


A famlia de componentes um string que representa o comportamento do componente (um componente de entrada ou de comando, por exemplo). A famlia do componente declarada no arquivo de configurao do JSF faces-config.xml e utilizada para selecionar um Renderer para um componente em particular. O Exemplo de Cdigo 1-9 mostra como associar um Renderer com uma famlia de componentes em particular. Exemplo de Cdigo 1-9. Associando um Renderer com uma Famlia de Componentes em Particular <render-kit> <renderer> <component-family> javax.faces.Input </component-family> <renderer-type> com.apress.projsf.Date </renderer-type> <renderer-class> com.apress.projsf.ch2.render.html.basic.HtmlInputDateRenderer </renderer-class>

22

PRO JSF E AJAX

Nota:

O prefixo javax.faces reservado para uso das famlias de componentes definidas na especificao JSF. Todos os exemplos neste livro utilizam o prefixo com.apress.projsf para famlias customizadas de componentes.

O tipo de componente um string utilizado para identificar a subclasse de UIComponent. Voc pode encontrar informao sobre o relacionamento entre o tipo de componente e a subclasse UIComponnete no arquivo de configurao JSF, como mostrado no Exemplo de Cdigo 1-10. Exemplo de Cdigo 1-10. Mapeamento entre o Ttipo de Componente e a Subclasse de UIComponent <component> <component-type> com.apress.projsf.ProInputDate </component-type> <component-class> com.apress.projsf.ch2.component.pro.ProInputDate </component-class> No Exemplo de Cdigo 1-10, uma subclasse de UIComponent com.apress.projsf.ch2.component.pro. ProInputDate foi assinalada como tipo de componente com.projsf.ProInputDate. Por conveno, o tipo de componente declarado tambm na subclasse UIComponent como uma constante COMPONENT_TYPE. Isto simplifica a vida dos desenvolvedores, de modo que eles no necessitam lembrar do tipo de componente para cada componente.

Nota:

O prefixo javax.faces reservado para os tipos de componente definidos na especificao JSF. Todos os exemplos neste livro utilizam o prefixo com.apress.projsf para os tipos customizados de componentes.

Converters, Validators, Events e Listeners


Alm de fornecer UIComponents, uma implementao JSF tambm fornece classes auxiliares para estes UIComponents. Estas classes auxiliares (Nota de traduo: conhecidas como helper classes) so divididas entre: converters (conversores), validators (validadores) e um modelo de event (evento) e listener (observadores de eventos). Os converters fornecem converso de tipo bidirecional entre o valor submetido de um componente e o correspondente tipo de objeto na camada de modelo. Os validators realizam a validao no tipo do objeto; por exemplo, eles podem assegurar que uma data no esteja no passado. O Exemplo de Cdigo 1-11 mostra um componente inputText com um converter de data associado. Exemplo de Cdigo 1-11. Um Componente inputText com um Converter Date Associado <h:inputText value=#{sample.date} > <f:convertDateTime pattern=yyyy-MMM-dd /> </h:inputText>

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

23

O JSF tambm fornece um modo de associar listeners (classes que observam eventos) e transmitir eventos para eles, semelhante maneira como o AWT e Swing fazem. Por exemplo, um commandButton fonte para ActionEvents. Quando um commandButton acionado, ocorre um postback (a pgina enviada para o servidor) e um novo ActionEvent armazenado na fila de eventos. Quaisquer listeners de eventos registrados com o commandButton sero notificados deste evento. O Exemplo de Cdigo 1-12 mostra um commandButton com um listener associado. Nota: A especificao JSF para registrar listeners e transmitir eventos baseada nos padres de projeto da especificao JavaBean 1.0.1.

Exemplo de Cdigo 1-12. Um commandButton com um Listener associado <h:commandButton value=Login action=success actionListener=#{sample.onLogin} /> No Exemplo de Cdigo 1-12, um componente commandButton tem duas propriedades action e actionListener. Ambas so atributos que aceitam expresses de associao de mtodos; a diferena que action requer um mtodo que retorne um string e actionListener requer um mtodo que receba um ActionEvent e retorne void. O valor do string do atributo action utilizado para propsito de navegao. Quando o ActionEvent enfileirado processado, estas expresses de associao de mtodos sero utilizadas para executar os mtodos do backing bean referenciados pelo action e pelo actionListener.

Facets
Uma view JSF composta por uma hierarquia de componentes, permitindo acesso a cada filho de componente por ndice. Algumas vezes necessrio tambm fornecer um meio alternativo de adicionar componentes subordinados que no so parte desta lista ordenada. Um exemplo o componente dataTable, onde os filhos representam as colunas a serem renderizadas na tabela. Em alguns casos pode ser til identificar um componente que represente o cabealho e/ou o rodap da tabela inteira, separado da coleo de filhos que representa as colunas individuais. Estes componentes filhos header (cabealho) e footer (rodap) so chamados de facets, referenciados apenas por nome e sem ordenao especfica. O nome de um facet representa o papel que o componente aninhado ir representar no componente pai. importante notar que um componente pai pode conter apenas um componente filho com aquele nome de facet, mas o mesmo componente pai pode conter muitos componentes filhos indexados. O Exemplo de Cdigo 1-13 mostra como adicionar um facet header aos componentes dataTable e column. Exemplo de Cdigo 1-13. Usando Facets em um componente dataTable <h:dataTable value=#{sample.tableList} var=rows > <f:facet name=header > <h:outputText value=Contact Information /> </f:facet>

24

PRO JSF E AJAX

<h:column> <f:facet name=header > <h:outputText value=Firstname /> </f:facet> <h:outputText value=#{rows.firstname} /> </h:column> </h:dataTable>

Renderers
A especificao JSF delineia dois modelos de como um componente JSF pode lidar com valores advindos de um request (decode - decodificar) ou enviados para uma resposta (encode - codificar). Estes dois modelos implementao direta ou implementao delegada , tem duas abordagens distintas; a implementao direta depende da instncia do UIComponent para lidar com encode e decode, e a implementao delegada deixa estas responsabilidades para um Renderer. Como voc deve ter visto na Figura 1-5, a abordagem delegada permite aos desenvolvedores de aplicao trabalhar diretamente com um UIComponent, independentemente do que ser renderizado no cliente. Neste livro vamos discutir apenas a abordagem de implementao delegada, j que nosso objetivo fornecer mltiplos Renderers para cada componente comportamental. Esta abordagem tambm o que torna o JSF um poderoso framework de UI.

Nota:

A abordagem de implementao direta permite uma performance ligeiramente melhor, uma vez que no h necessidade de delegar para um Renderer, mas tambm limita seriamente a extensibilidade e portabilidade para vrios clientes.

Os Renderers so responsveis pela apresentao de um componente JSF e devem gerar o markup apropriado para o client-side, como HTML e JavaScript ou XUL. Os Renderers tambm so responsveis por converter a informao oriunda do cliente para algo compreensvel pelo componente (um string vindo de um POST HTML para um objeto Date, por exemplo). Embora um Renderer introduza atributos client-side, como: style, disabled, tootip e outros, estes atributos so expostos na subclasse especfica do renderer do componente (HtmlSelectOneRadio, por exemplo). Uma grande diferena entre UIComponents e Renderers o modo que definido em runtime. Renderers so definidos como singletons, logo, existe apenas um Renderer para todas as instncias de um UIComponent para cada tipo de renderer em particular.

Cuidado: J que instncias individuais de Renderer sero criadas sob demanda durante o processo de renderizao e utilizadas durante o ciclo de vida da aplicao Web, importante entender que cada instncia poder ser invocada por mais de um thread de processamento de requests simultaneamente. Isto requer que os Renderers sejam programados de maneira thread-safe.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

25

Renderer Types
O renderer type, ou tipo de renderer, um identificador que definido pelo componente e utilizado em combinao com a famlia do componente; ele identifica univocamente qual classe Renderer deve ser utilizada com o componente. Combinar renderer type com famlia de componentes extremamente poderoso j que permite o reuso do renderer type para mltiplos componentes comportamentais. O Exemplo de Cdigo 1-14 ilustra como uma famlia de componentes associada com um renderer especfico e renderer type. Exemplo de Cdigo 1-14. Renderer Ttype Definido no Arquivo de Configurao JSF <render-kit> <renderer> <component-family> javax.faces.Input </component-family> <renderer-type> com.apress.projsf.Date </renderer-type> <renderer-class> com.apress.projsf.ch2.renderer.html.HtmlInputDateRenderer </renderer-class> A Tabela 1-4 contm um subconjunto de famlias de componentes padres com seus componentes associados e renderer types.
Table 1-4. Um Subconjunto de Todas as Famlias de Componentes, seus Componentes e Renderer Types Famlia de Componentes* C o m p o n e n t e Command UICommand HtmlCommandButton HtmlCommandLink Data Form Graphic Input UIData HtmlDataTable UIForm HtmlForm UIGraphic HtmlGraphicImage UIInput HtmlInputHidden HtmlInputSecret HtmlInputText HtmlInputTextArea Tipo de Componente Command HtmlCommandButton HtmlCommandLink Data HtmlDataTable Form Form Graphic HtmlGraphicImage Input HtmlInputHidden HtmlInputSecret HtmlInputText HtmlInputTextArea Hidden Secret Text Textarea Continuao Image Form Table Button Link Renderer Type**

26

PRO JSF E AJAX

Table 1-4. Um Subconjunto de Todas as Famlias de Componentes, seus Componentes e Renderer Types (continuao) Famlia de Componentes* C o m p o n e n t e Output UIOutput HtmlOutputFormat HtmlOutputLabel HtmlOutputLink HtmlOutputText Panel UIPanel HtmlPanelGrid HtmlPanelGroup Tipo de Componente Output HtmlOutputFormat HtmlOutputLabel HtmlOutputLink HtmlOutputText Panel HtmlPanelGrid HtmlPanelGroup Grid Group Format Label Link Text Renderer Type**

* O nome completo da famlia de componente javax.faces.<nome da tabela>. ** O nome completo do renderer type javax.faces.< nome da tabela >.

A Tabela 1-4 mostra que o renderer type Text utilizado em vrios lugares para o componente HtmlInputText e para o componente HtmlOutputText. A combinao da famlia de componentes Output e o renderer type Link utiliza a classe de Renderer que ir gerar um elemento HTML link <a href=...>texto</a> para o cliente.

RenderKits
A funcionalidade do RenderKit suportar UIComponents que utilizem a abordagem de implementao delegada com a delegao de Renderers para o UIComponent. Os RenderKits agregam instncias de Renderers com tipos de markup similares, e o RenderKit default fornecido por todas as implementaes JSF o RenderKit bsico de HTML, contendo Renderers que produzem sada HTML 4.0.1. Outros RenderKits possveis podem possuir Renderers suportando tecnologias de exibio como SVG, WML, Ajax, XUL e outras. Neste livro voc ver RenderKits adicionais para Componentes DHTML/HTML da Microsoft e para a linguagem de associao XUL/XML do Mozilla (XBL). O RenderKit no responsvel por criar o Renderer porque armazena apenas uma nica instncia de cada renderer type. Cada RenderKit associado com uma view (hierarquia de componentes) em runtime com a propriedate UIViewRoot. Se nenhum RenderKit foi selecionado, o RenderKit default ir ser utilizado. Em se tratando de RenderKits, muitas vezes no haver necessidade de criar um novo RenderKit. Adicionar um Renderer customizado a um RenderKit pr existente apenas uma operao de configurao. Se um identificador de RenderKit for omitido, o Renderer customizado ser automaticamente adicionado ao RenderKit de HTML default. Se quiser adicionar um RenderKit com Renderers customizados, voc pode fazer a mesma coisa - atualizar o arquivo de configurao JSF. O Exemplo de Cdigo 1-15 mostra como adicionar um novo Renderer ao arquivo de configurao JSF. Exemplo de Cdigo 1-15. Um Novo Renderer Adicionado ao RenderKit Default de HTML <render-kit> <! no render-kit-id, so add this Renderer to the HTML_BASIC RenderKit > <renderer>

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES <component-family> javax.faces.Input </component-family> <renderer-type> com.apress..projsf.Date </renderer-type> <renderer-class> com.apress.projsf.ch2.renderer.html.HtmlInputDateRenderer </renderer-class> ... </render-kit>

27

Ao no informar o identificador do RenderKit na configurao, o Exemplo de Cdigo 1-15 com.apress.projsf.ch2.renderer.html.HtmlInputDateRenderer adicionado automaticamente ao RenderKit HTML default padro.

Tag Handlers de Ao Personalizada


J que a linguagem de descrio de pgina default JSP, a maioria dos componentes JSF ter uma custom action JSP. Quando o container JSP encontra uma custom action, ele procura pelo processador de tag JSF associado com esta ao. O propsito principal do JSF tag handler (processador de tag JSF) criar uma instncia do componente, utilizando a subclasse especfica do renderer, e associar o componente a um Renderer no primeiro request da pgina.

Ciclo de Vida de Processamento de Requests


Como um escritor de componentes, essencial que tenha um entendimento claro sobre o ciclo de vida do JSF. Uma pgina construda com componentes JSF passar por um ciclo de vida de processamento de requests bem definido. Este ciclo tem seis fases Restore View (Restaurar a view), Apply Request Values (aplicar os valores do request), Process Validations (processar validaes), Update Model Values (atualizar os valores do modelo), Invoke Application (invocar a aplicao) e Render Response (renderizar a resposta), como mostrado na Figura 1-8.

Figura 1-8. Ciclo de vida formal do JSF

28

PRO JSF E AJAX Eis como o processo dividido: 1. Restore View: Esta fase responsvel por restaurar a hierarquia de componentes do request prvio e anex-la ao FacesContext. Se nenhum estado preservado estiver disponvel, esta fase responsvel por criar um novo UIViewRoot, que o n raiz na hierarquia de componentes, e armazen-la no FacesContext. Apply Request Values: Nesta fase, cada componente tem a oportunidade de atualizar seu estado corrente com informaes advindas do request. Process Validations: Esta fase responsvel por processar quaisquer validators ou converters anexados aos componentes da hierarquia de componentes. Update Model Values: Durante esta fase, todos os objetos de modelos de dados apropriados tero seus valores atualizados para igualar ao valor local do componente, e os valores locais dos componentes sero limpos. Invoke Application: Nesta fase, qualquer transmisso de eventos para a aplicao ainda remanescente ser efetuada (aes executadas por HtmlCommandButton, por exemplo). Render Response: Esta fase responsvel por renderizar a resposta para o cliente e armazenar o novo estado para processamento nos requests subseqentes.

2. 3. 4.

5. 6.

Para colocar estas seis fases em um contexto de vida real, utilizaremos um exemplo simples onde o usurio acessar uma aplicao construda com JSF e JSP. Esta aplicao contm uma pgina simples de login com alguns campos de entrada para username e password e um boto para validar. Caso o login seja bem sucedido, o usurio ser redirecionado para uma segunda pgina que exibir o nome do usurio.

Criando uma Aplicao Utilizando o JSF


Esta aplicao contm trs partes essenciais a descrio da aplicao (JSP), um arquivo de configurao JSF e um managed bean. Esta aplicao tem duas pginas JSP login.jspx e result.jspx. O Exemplo de Cdigo 1-16 mostra a pgina de login. Exemplo de Cdigo 1-16. A Pgina de Login <?xml version=1.0" encoding=utf-8"?> <jsp:root xmlns:jsp=http://java.sun.com/JSP/Page version=2.0" xmlns:f=http://java.sun.com/jsf/core xmlns:h=http://java.sun.com/jsf/html> <jsp:output omit-xml-declaration=true doctype-root-element=HTML doctype-system=http://www.w3.org/TR/html4/loose.dtd doctype-public=-//W3C//DTD HTML 4.01 Transitional//EN/> <jsp:directive.page contentType=text/html;charset=utf-8"/> <f:view> <html> <body> <h:form> <h:outputText value=Application Login /> <h:inputText value=#{credentials.username} />

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

29

<h:inputText value=#{credentials.password} /> <h:commandButton value=Login action=success actionListener=#{credentials.onLogin} /> </h:form> </body> </html> </f:view> </jsp:root> A estrutura da pgina simples e descreve uma pgina contendo dois campos de entrada para username e password e um boto para efetuar o login. A Figura 1-9 mostra como a pgina se parece quando renderizada no browser.

Figura 1-9. A P gina de Login

A segunda pgina da aplicao, mostrada no Exemplo de Cdigo 1-17, simples e meramente ilustra a navegao e totalidade do ciclo de vida. A pgina contm um componente <h:outputText> que renderizar o valor digitado no componente <h:inputText> para o username na pgina inicial, em caso de login bem sucedido. Exemplo de Cdigo 1-17. Regras de Navegao e Managed Beans Para a Aplicao <?xml version=1.0" encoding=utf-8"?> <jsp:root xmlns:jsp=http://java.sun.com/JSP/Page version=2.0" xmlns:f=http://java.sun.com/jsf/core xmlns:h=http://java.sun.com/jsf/html> <jsp:output omit-xml-declaration=true doctype-root-element=HTML doctype-system=http://www.w3.org/TR/html4/loose.dtd doctype-public=-//W3C//DTD HTML 4.01 Transitional//EN/> <jsp:directive.page contentType=text/html;charset=utf-8"/> <f:view> <html>

30

PRO JSF E AJAX

<body> <h:form> <h:outputText value=#{credentials.username} /> </h:form> </body> </html> </f:view> </jsp:root> Para poder navegar de uma pgina para outra, voc tem que definir um navigation case (caso de navegao) no arquivo de configurao do JSF faces-config.xml. Tambm necessita criar um mapeamento para o cdigo de backend utilizando um managed bean. O Exemplo de Cdigo 1-18 mostra como fazer isto. Exemplo de Cdigo 1-18. Regras de Navegao e Managed Beans para a Aplicao <navigation-rule> <from-view-id>/login.jspx</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/result.jspx</to-view-id> </navigation-case> </navigation-rule> <managed-bean> <managed-bean-name>credentials</managed-bean-name> <managed-bean-class> com.apress.projsf.ch1.application.CredentialsBean </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> Como pode ver, o Exemplo de Cdigo 1-18 define que, a partir da pgina login.jspx, no caso de sucesso, o usurio da aplicao ser direcionado para a pgina result.jspx. Ela tambm define um managed bean que aponta para uma classe CredentialsBean , contendo uma lgica de aplicao simples. O Exemplo de Cdigo 1-19 mostra a lgica de aplicao. Exemplo de Cdigo 1-19. A Lgica da Aplicao package com.apress.projsf.ch1.application; import javax.faces.event.AbortProcessingException; import javax.faces.event.ActionEvent; public class CredentialsBean { public void onLogin( ActionEvent event)

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES { If (!duke.equalsIgnoreCase(_username)) throw new AbortProcessingException(Unrecognized username!); // clear out the password, for good measure! _password = null; } public void setUsername( String username) { _username = username; } public String getUsername() { return _username; } public void setPassword( String password) { _password = password; } public String getPassword() { return _password; } private String _username; private String _password; }

31

Inicializao da Aplicao Web


Ao receber um request JSF, a implementao JSF deve iniciar, ou adquirir, referncias a vrios processos e servios que devem estar disponveis para uma aplicao Web JSF executando em um ambiente de servlet ou portlet. Para ter acesso a estas referncias, a implementao JSF ir invocar vrias factories (objetos que instanciam outros objetos) responsveis por criar as instncias necessrias para iniciar a aplicao JSF. Quando uma aplicao Web JSF inicia, nossas factories so iniciadas tambm; cada uma destas factories responsvel por reas diferentes dentro de uma aplicao Web JSF: ApplicationFactory: A classe ApplicationFactory responsvel pela criao da instncia da aplicao (Application), a qual pode ser vista como um servio que permite, por exemplo, que a instncia de Lifecycle crie e restaure as views JSF (hierarquia de componentes) nos novos requests e armazene o estado da view JSF. LifecycleFactory: A LifecycleFactory responsvel por retornar uma instncia da classe Lifecycle, que identifica um lifecycle. A instncia default do Lifecycle responsvel por invocar a lgica de processamento, para implementar a funcionalidade desejada para cada fase do ciclo de vida de processamento de requests do JSF.

32

PRO JSF E AJAX RenderKitFactory: A RenderKitFactory responsvel por retornar um RenderKit para a aplicao Web JSF. Um RenderKit uma biblioteca de Renderers com uma tecnologia comum de renderizao. FacesContextFactory: A FacesContextFactory prov um meio de criar uma instncia da classe FacesContext para a implementao JSF, que utilizada para representar informao contextual associada ao request e eventualmente resposta. A Figura 1-10 mostra os envolvidos na inicializao da aplicao.

Figura 1-10. A criao da aplicao

Cada aplicao Web JSF tem uma ApplicationFactory. Esta classe de factory responsvel por criar e substituir a instncia da classe Application necessria para todas as aplicaes que utilizam JSF. A instncia de Application fornecer servios suportados pela instncia a outros processos. Semelhantemente, o arquivo de configurao JSF faces-config.xml lido uma s vez durante a criao da aplicao Web e armazenado na instncia de Application. A RenderKitFactory responsvel por retornar uma instncia de RenderKit baseada no identificador de RenderKit para esta aplicao Web JSF. Para cada implementao JSF deve haver um RenderKit default o RenderKit HTML, que identificado por uma constante string RenderKitFactory.HTML_BASIC_RENDER_KIT. A LifecycleFactory responsvel por criar (se necessrio) e retornar uma instncia de Lifecycle. Esta instncia de Lifecycle responsvel por invocar a lgica de processamento para implementar a funcionalidade desejada para cada fase (veja a Figura 1-8) do ciclo de vida de processamento de requests. A ltima factory FacesContextFactory , fornece implementao JSF uma maneira de criar instncia de FacesContext, utilizada para representar informao contextual associada com um request e, eventualmente, criando uma resposta.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

33

Request Inicial
Quando o usurio acessa a aplicao pela primeira vez, um request inicial enviado ao FacesServlet, o qual despacha o request para a instncia de Lifecycle JSF (veja a Figura 1-10).

Fase de Restore View


A primeira fase do ciclo de vida JSF a Restore View (veja a Figura 1-11) que responsvel por verificar se esta pgina foi requisitada anteriormente ou se um novo request.

Figura 1-11. Fase Restore View durante o request inicial

Na figura 1-11, voc est observando o processo de um request inicial e como a primeira fase Restore View no ciclo de vida JSF responsvel por restaurar uma view do servidor e o estado do cliente. Durante o primeiro request para esta view, o mtodo ViewHandler.restoreView() retornar null, j que no h estado armazenado.

Nota:

Os identificadores de fase de ciclo de vida JSF so parte da API pblica do JSF na classe PhaseId.

34

PRO JSF E AJAX

Se o valor de retorno null, a fase Restore View chamar renderResponse() no FacesContext para este request. O mtodo renderResponse() indicar que quando esta fase estiver concluda, o mtodo render() ser chamado para executar a fase 6 Render Response sem passar pelas fases 2 at 5. Subseqentemente, a fase Restore View ir chamar o mtodo ViewHandler.createView() para criar a raiz da hierarquia de componentes UIViewRoot e anex-la ao FacesContext. O componente UIViewRoot no renderiza nada, mas executa um papel importante na distribuio de eventos durante um request postback (secundrio).

Fase Render Response


Quando o mtodo renderResponse() invocado durante a fase Restore View, o ciclo de vida pula diretamente para o mtodo render(), responsvel por executar a fase Render Response, como demonstrado na Figura 1-12.

Figura 1-12. A fase Render Response durante o request inicial

Durante esta fase, o mtodo ViewHandler.renderView() chamado para executar o documento JSP. O mtodo renderView() passar o valor da propriedade viewId adquirido do n UIViewRoot, como um path relativo ao contexto para o mtodo dispatch()do ExternalContext associado a este request. O mtodo dispatch() ir encaminhar o valor da propriedade viewId (/login.jspx como um path relativo ao contexto, por exemplo) para o container Web. J que o mapeamento especfico do JSF no parte do request encaminhado; o request ser ignorado pelo FacesServlet e passado diretamente ao container JSP, o qual, por sua vez, localizar o JSP baseado no path relativo ao contexto e executar a pgina JSP correspondente ao viewId (/login.jspx, por exemplo). A Figura 1-13 mostra o processamento de um documento JSF JSP.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

35

Figura 1-13. Informando o ResponseWriter no FacesContext

O Identificador da View JSF: View ID Dependendo de qual mapeamento utilizado prefix (prefixo) ou suffix (sufixo) o identificador de view do UIViewRoot derivado ligeiramente diferente do uniform resource identifier (URI) do request. Se o mapeamento prefix for utilizado, como em /faces/* (que o mais comum ) para o FacesServlet, a propriedade viewId obtida da informao de path vinda aps o mapeamento; por exemplo, /context-roofaces/login.jspx ir resultar em um view identifier igual a /login.jspx. Se o mapeamento suffix for utilizado, como *.jsf, a propriedade viewId obtida da informao de path do servlet do URI do request, aps substituir o sufixo com o valor do parmetro de inicializao do contexto, cujo nome dado pela constante: ViewHandler. DEFAULT_SUFFIX_NAME. Por exemplo, a URI /context-root/login.jsf resultar em um view identifier igual a /login.jsp por default, mas possvel alterar o parmetro de inicializao de contexto para usar o sufixo .jspx como default. Antes de processar e executar o documento JSF JSP, o runtime do JSP determina primeiramente o tipo de contedo e encoding de caracteres a ser utilizado. Para o JSF trabalhar em harmonia com o ciclo de vida JSP, o tag <f:view> necessita estar presente. O tag <f:view> um tag JSP body que armazena (em buffer) todo o contedo renderizado pelos componentes JSF aninhados. Simplesmente falando, o tag <f:view> serve como um container para todos os outros componentes JSF. O tag <f:view> responsvel por criar e armazenar uma instncia de ResponseWriter no FacesContext. O mtodo createResponseWriter() cria uma nova instncia de ResponseWriter para o tipo de contedo e encoding especficos. O ResponseWriter responsvel por escrever o markup gerado para o cliente, neste caso para o buffer de contedo do <f:view>.

36

PRO JSF E AJAX Tipo de Contedo e Encoding de Caracteres Quando um servidor envia um documento para um browser no cliente, ele tambm passa informao no header Content-type (tipo de contedo) do HTTP sobre o tipo MIME (Multipurpose Internet Mail Extensions) do documento, como text/html e o conjunto de caracteres, como UTF-8 ou ISSO-88591. O cliente utiliza esta informao para processar corretamente os bytes oriundos do servidor. Uma lista de tipos de contedos aceitveis enviada no header HTTP Accept, do cliente para o servidor. Isto pode ser utilizado dinamicamente para selecionar o tipo de documento apropriado para a resposta, ou o desenvolvedor da aplicao pode especificar um contedo esttico para o documento. No JSF, o tag <f:view> passa null para a RenderKitFactory como uma lista de tipos de contedo aceitveis, mesmo que o container JSP esteja ciente da lista completa aceita pelo browser do cliente. Ento, o RenderKit default RenderKit HTML bsico padro deve assumir que o tipo de contedo deve ter sido alterado para text/html, uma vez que est renderizando apenas HTML. O RenderKit usa esta informao sobre o tipo de contedo e encoding de caracter para criar um ResponseWriter que possa produzir markup corretamente formatado para o cliente.

Para cada tag JSF JSP dentro do <f:view> um componente JSF criado e anexado hierarquia de componentes durante o request inicial. Como deve-se lembrar, o UIViewRoot criado na primeira fase e anexado ao FacesContext, de modo que podemos seguramente assumir que os componentes sero anexados hierarquia de componentes. A Figura 1-14 mostra a execuo do tag inicial <h:form>.

Figura 1-14. Escrevendo o elemento inicial <form> no buffer de contedo de <f:view>

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

37

No documento JSP login, o prximo tag JSF JSP a ser executado o <h:form>. O tag JSF JSP invoca o mtodo Application.createComponent() que recebe um string representando o tipo de componente, por exemplo: javax.faces.HtmlForm (veja a seo Famlas de Componentes e Tipos de Componentes). O tipo de componente mapeado a uma classe definida no arquivo faces-config.xml, e uma instncia do componente HtmlForm criada e anexada ao UIViewRoot. A seguir, um Renderer para o componente recm-criado necessita ser encontrado. Um Renderer localizado pela famlia de componentes e Renderer Type, os quais juntos definem um identificador nico para o Renderer (veja a seo Renderer Types).

Nota:

Vamos usar o componente HtmlInputText para ilustrar o relacionamento entre a famlia de componentes e o renderer type. O componente HtmlInputText tem a famlia javax.faces.Input e o renderer type javax.faces.Text. Juntos, eles identificam unicamente a classe apropriada de Renderer dentro do RenderKit bsico HTML javax.faces.renderer.html.HtmlInputText.

O renderer type j conhecido pelo tag <h:form>, e a famlia de componentes pode ser localizada na superclasse do componente, UIForm. O tag, ento, chama um mtodo endcodeBegin() no componente, o qual, por sua vez, chama o mtodo encodeBegin() no renderer do HtmlForm. O mtodo encodeBegin() no Renderer chama mtodos no ResponseWriter para escrever o markup para o elemento HTML form <form method= action=>. Toda a sada do ResponseWriter enviada para o buffer de contedo do <f:view>. A Figura 1-15 mostra o processo de fechamento do tag <h:form>.

Figura 1-15. A sada e o fechamento do elemento </form>

38

PRO JSF E AJAX

O processo continua e todos os componentes aninhados dentro do componente HtmlForm so renderizados e adicionados ao buffer de contedo do <f:view>. Ento o tag de fechamento de <h:form> executado. O tag <h:form> invoca o mtodo encodeEnd() no Renderer, HtmlFormRenderer, o qual, por sua vez, chama o mtodo writeState() no ViewHandler. O mtodo writeState() passa um token para o ResponseWriter, o qual adicionado ao buffer de contedo do <f:view>. O mtodo encodeEnd() ento chama mtodos no ResponseWriter para escrever o tag de fechamento para o elemento HTML form - </ form>. A Figura 1-16 mostra o fechamento do tag <f:view>.

Nota:

O ViewHandler representa a tecnologia de view e, neste caso, a tecnologia de view JSP. Nada na especificao JSF previne qualquer um de implementar um ViewHandler alternativo para outra tecnologia de view, como XML.

Figura 1-16. Substituindo o token pelo estado serializado e fechando </f:view>

No momento que pegar o tag de fechamento </f:view>, toda a hierarquia de componentes est disponvel. Voc no pode salvar o estado da hierarquia de componentes representando esta pgina da aplicao at ter a rvore completa. O tag </f:view> chama o mtodo writeState() no StateManager. Dependendo do parmetro inicial STATE_SAVING_METHOD para a preservao do estado (veja a seo Salvando e Restaurando o Estado), o StateManager armazena o estado na sesso no servidor ou delega ao ResponseStateManager a tarefa de salvar o estado no cliente, substituindo o token com o estado serializado. Aps o estado ter sido salvo, o buffer enviado ao cliente e a execuo de qualquer tag JSP (no JSF) ser efetuada. A pgina de login agora renderizada no browser.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

39

Note:

No JSF 1.2, o tag <f:view> no mais responsvel por armazenar a sada em buffer. Ao invs disto, o armazenamento feito utilizando um wrapper (padro decorator) para ServletResponse. Adicionalmente, a hierarquia de componentes no mais criada durante a renderizao. Durante a fase Render Response do JSF 1.2, a hierarquia criada primeiro e renderizada depois. Logo, durante a renderizao, a hierarquia completa est disponvel, logo, o estado gravado diretamente na resposta armazenada, ao invs de necessitar um token para ser substitudo pelo estado real no </f:view>.

Request Postback
At agora, a nica coisa que o usurio viu foi a renderizao inicial da primeira pgina requisitada. Aps receber a pgina, o usurio digita o username, a password e clica no boto de login. Um postback efetuado e veremos agora como o JSF lida com postbacks. Algumas partes so similares ao que estivemos falando no request inicial, mas existem, obviamente, diferenas, especialmente no ciclo de vida de request JSF. No postback, todas as seis fases do ciclo de vida de request JSF so chamadas (a no ser que em algum lugar do processo o mtodo FacesContext.renderResponse() seja chamado, forando o ciclo de vida a pular diretamente para a fase Render Response). Isto diferente do request inicial, onde apenas a primeira e ltima fases eram chamadas.

Fase Restore View


A primeira parte de um postback a mesma do request inicial; a fase Restore View executa e chama o mtodo restoreView() no ViewHandler para restaurar qualquer estado disponvel do request prvio. A Figura 1-17 mostra como restaurar o estado preservado da hierarquia de componentes.

Figura 1-17. Restaurando o estado preservado da hierarquia de componentes

40

PRO JSF E AJAX

Aqui onde as semelhanas terminam; ao invs de retornar null, o mtodo restoreView() retornar o estado corrente da hierarquia de componentes associada com um viewId e FacesContext do StateManager e se o parmetro inicial STATE_SAVING_METHOD for selecionado para client-side, chamar o ResponseStateManager para recuperar o estado do request corrente. A hierarquia de componentes ento passada para o FacesContext pela fase Restore View.

Fase Apply Request Values


Na fase Apply Request Values, cada componente de entrada estabelece o valor submetido dos parmetros de request, e cada comando de componentes envia um evento para a fila, a ser enviado para a fase Invoke Application. A Figura 1-18 mostra como a fase Apply Request Values passa novos valores para os componentes.

Figura 1-18. Aplicando novos valores, passados no request, aos componentes

O valor submetido neste ponto armazenado como submitted (submetido) no componente e nenhum valor foi colocado no modelo ainda. No momento em que a fase Apply Request for completada, os Renderers no mais necessitam observar os parmetros de request, j que todos os valores foram atualizados em cada componente.

Fase de Process Validation


Na fase de process validation, a converso e validao so efetuadas chamando o mtodo processValidators() no UIViewRoot. A Figura 1-19 mostra a converso e validao.

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

41

Figura 1-19. Efetuando a validao e converso

Este processo ir continuar chamando o mtodo processValidators() recursivamente em cada componente da hierarquia. Durante a validao de cada componente HtmlInputText, a converso de tipo ocorrer primeiramente no valor submetido de cada componente (um string para outro objeto, por exemplo). O novo objeto colocado como um valor local no componente e o valor submitted limpo. O novo objeto validado. Se no houver erros, ento a prxima etapa enfileirar um evento ValueChangeEvent que ser disparado ao final da fase. Se um erro de converso ou validao ocorrer, uma mensagem correspondente JSF ser anexada ao FacesContext utilizando o componente clientId, e ento o mtodo renderResponse() chamado para indicar que o ciclo de vida deve pular diretamente para a fase Render Response, aps a fase Process Validations completar.

Fase Update Model


Neste ponto do ciclo de vida, todos os valores submetidos foram convertidos e validados, logo, seguro coloc-los no modelo de dados. Durante a fase Update Mode, o ciclo de vida JSF passa pela hierarquia de componentes, chamando o mtodo processUpdates() em cada componente. A Figura 1-20 mostra a fase Update Model atualizando o modelo. Para determinar onde armazenar o novo valor, o mtodo processUpdates() utilizar a associao de valor, a qual definida o atributo value do componente (por exemplo #{credentials.username}). A associao de valor aponta para uma propriedade em um managed bean (por exemplo, username). Utilizando associao de valor, o valor local do componente armazenado no modelo de dados e depois sendo limpo no componente. Quaisquer mensagens JSF e erros no modelo por exemplo, validaes implementadas pelo modelo , so anexados ao FacesContext com o clientId correspondente. O mtodo renderResponse() chamado para indicar que o ciclo de vida deve pular diretamente para a fase Render Response aps a fase Update Model estiver completa.

42

PRO JSF E AJAX

Figura 1-20. Atualizando o modelo de dados

Fase Invoke Application


Na fase Invoke Application necessrio correr a hierarquia de componentes, j que esta fase manipular apenas os eventos enfileirados das fases anteriores e, dependendo do resultado, ir continuar at a fase final Render Response ou redirecionar para outra pgina. A Figura 1-21 mostra a transmisso de eventos enfileirados para esta fase e o processamento dos mtodos associados ao.

Figura 1-21. Executando a lgica de aplicao

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

43

Como mencionado na seo anterior Converters, Validators, Events e Listeners, temos dois mtodos que sero processados quando ocorrer um ActionEvent. A primeira coisa que acontece uma chamada ao mtodo processApplication(), no UIViewRoot, que recebe cada evento enfileirado e transmite para o componente alvo para o evento (por exemplo: commandButton.broadcast(FacesEvent)). O componente UICommand sabe sobre os atributos action e actionListener, assim como o default ActionListener anexado ao objeto Application. Primeiramente, todos os ActionListeners registrados so chamados e, ento, a associao de mtodo actionListener executada (por exemplo: #{credentials.onLogin}), e, finalmente, o componente chama o mtodo processAction() no ActionListener default para processar o mtodo de ao e lidar com a navegao. importante que a associao de mtodo de ao seja chamada no final do processo, j que ela define uma possvel navegao e no queremos navegar antes de processar todos os eventos.

Postback com Navegao


Quando o ActionListener default est processando um ActionEvent, ele chama uma associao de mtodo de ao e obtm o resultado, que um string. Se o resultado retornar null, ento o ActionListener default continuar com o prximo evento na fila. Aps todos os eventos terem sido transmitidos, a fase Invoke Application estar completa e o processamento do ciclo de vida continuar at a fase final Render Response. Se o resultado no for null, ento o ActionListener default passa o FaceContext, o fromAction (que a expresso de associao de mtodo, por exemplo: credentials.doLogin) e o outcome (resultado) para o NavigationHandler. A Figura 1-22 mostra a navegao no caso de postback.

Figura 1-22. Navegao com postback

44

PRO JSF E AJAX

As regras de navegao esto definidas no faces-config.xml, que lido na inicializao, e toda a informao armazenada no objeto Application (veja a seo Modelo de Navegao). A primeira coisa que o NavigationHandler faz verificar se existe uma regra de navegao que seja compatvel com a combinao de fromViewId (obtido do FacesContext), fromAction e outcome. Podemos lidar com a navegao de duas maneiras. Redirecionar significa um novo request (e, como bnus, voc pode criar um bookmark para a nova pgina) e inicia o ciclo de vida do JSF novamente; podemos tambm fazer com que o mtodo handleNavigation() crie um novo UIViewRoot, coloque-o no FacesContext e deixe o ActionListener default chamar renderResponse() para iniciar a fase Render Response. Esta soluo replica o comportamento do request inicial na fase Render Response, mas com um novo identificador de view. A Figura 1-23 mostra a execuo do JSP durante o postback.

Figura 1-23. A fase Render Response em um postback

Durante um postback, a primeira parte da fase Render Response a mesma que no request inicial at a chamada do mtodo dispatch(), exceto que temos agora uma hierarquia de componentes completa e no apenas o UIViewRoot (veja a Figura 1-13). Aps despachar, a pgina JSP executada e o tag inicial <f:view> faz a mesma coisa que no request inicial criar e armazenar uma instncia do ResponseWriter no FacesContext e atuar como um buffer para a sada renderizada dos componentes (veja a Figura 1-14). Ao invs de criar novos componentes e anex-los ao UIViewRoot, como no request inicial, as tags de componentes individuais aninhadas dentro do tag <f:view> tero que localizar suas contrapartidas que j existam na hierarquia de componentes. Isto acontece durante a execuo da pgina JSP, atravessando at o incio da rvore de tags para encontrar o tag de componente pai mais prximo. A partir do tag do componente pai, o tag do componente filho pode encontrar seus componentes correspondentes pelo identificador de componente ou pelo nome do facet (veja a seo Facets).

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES

45

A despeito de estarmos mapeando componentes ao invs de criar novas instncias, o processamento segue da mesma maneira que no request inicial renderizando os componentes para o buffer do tag <f:view>, armazenando o estado, seja no cliente ou na sesso (no servidor), e, finalmente, enviando o markup do buffer para o container JSP, de modo a ser renderizado (veja a Figura 1-15).

JSF e JSP
No JSF, um criador de componentes pode alterar uma propriedade booleana, chamada rendersChildren, em um componente. Esta propriedade decide se um componente deve ou no renderizar seus componentesfilhos. Para componentes da implementao JSF, o valor de rendersChildren sempre false. Isto significa que cada componente responsvel por renderizar sua sada para o ResponseWriter e armazen-la no buffer de <f:view>, no importando como seus filhos so renderizados. Se rendersChildren for alterada para true em um componente, ento o mtodo encodeBegin() chamado no tag de fechamento ao invs de no tag de inicializao (veja a Figura 1-14) para assegurar que nenhum filho renderizado para o buffer at que o pai termine o loop em seus filhos. Uma vez que o pai sabe sobre seus filhos, eles podem ser renderizados no buffer de contedo do <f:view>. Um componente que usa isto o dataTable, porque necessita ter acesso a todos os seus componentes-filhos antes que qualquer sada seja renderizada. Considerando que alguns componentes possam requerer que rendersChildren seja true, haver impacto na maneira como voc constri sua descrio de pgina. Lembra-se da pgina de Login? Vamos adicionar alguns rtulos aos campos de entrada e ajustar um pouco o layout, de modo que os componentes fiquem alinhados verticalmente, ao invs de horizontalmente, como mostrado no Exemplo de Cdigo 1-20. Exemplo de Cdigo 1-20. A Pgina Login Modificada com Alguns Tags JSP <?xml version=1.0' encoding=windows-1252'?> <jsp:root xmlns:jsp=http://java.sun.com/JSP/Page version=2.0" xmlns:f=http://java.sun.com/jsf/core xmlns:h=http://java.sun.com/jsf/html> <jsp:output omit-xml-declaration=true doctype-root-element=HTML doctype-system=http://www.w3.org/TR/html4/loose.dtd doctype-public=-//W3C//DTD HTML 4.01 Transitional//EN/> <jsp:directive.page contentType=text/html;charset=windows-1252"/> <f:view> <html> <body> <h:form> <h:outputText value=Application Login /> <h:panelGrid columns=2"> <jsp:text>Username</jsp:text> <h:inputText value=#{sample.username} /> <jsp:text>Password</jsp:text> <h:inputText value=#{sample.password} /> </h:panelGrid> <h:commandButton value=Submit action=#{credentials.onLogin} />

46

PRO JSF E AJAX

</h:form> </body> </html> </f:view> </jsp:root> Este exemplo insere os componentes em um tag <h:panelGrid>. O componente criado por este tag renderiza seus filhos em um grid bi-dimensional, com duas colunas. O componente HtmlPanelGrid tem sua propriedade rendersChildren como true, logo, ele pode observar todos os seus filhos antes de renderizar o markup para cada coluna. O exemplo tambm adiciona dois tags que no so JSF <jsp:text> que adicionaro um rtulo a cada campo de entrada. Em runtime a pgina se parece com a Figura 1-24.

Figura 1-24. Renderizao do contedo diferente de JSF com o rendersChildren true

Como pode ver, os rtulos Username e Password fora colocados incorretamente no topo da pgina. Durante a execuo desta pgina, qualquer componente JSF dentro do componente HtmlPanelGrid ser proibido de ser renderizado at que o tag final de HtmlPanelGrid (</h:panelGrid>) seja lido. Note que nenhum tag ou texto arbitrrio aninhado dentro do componente HtmlPanelGrid ser adiado. Logo, <jsp:text> renderizado para o buffer imediatamente. Voc pode alterar este comportamento colocando um tag <f:verbatim> em volta do contedo JSF, como no Exemplo de Cdigo 1-21. Exemplo de Cdigo 1-21. A Pgina Login com o Tag <f:verbatim> em Volta do Contedo que No JSF <h:form> <h:outputText value=Application Login/> <h:panelGrid columns=2"> <f:verbatim><jsp:text>Username</jsp:text></f:verbatim> <h:inputText value=#{credentials.username} /> <f:verbatim><jsp:text>Password</jsp:text></f:verbatim> <h:inputText value=#{credentials.password} />

CAPTULO 1 A FUNDAO DO JSF: COMPONENTES </h:panelGrid> <h:commandButton value=Submit action=#{credentials.onLogin} /> </h:form>

47

O tag <f:verbatim> pega o contedo que no JSF e o adiciona hierarquia de componentes como um componente UIOutput. Em runtime, a pgina se parecer com a Figura 1-25.

Figura 1-25. Renderizao de contedo diferente de JSF usando o tag <f:verbatim>

Nota:

O problema com o rendersChildren foi resolvido pelo JSF Expert Group na verso JSF 1.2. A nova caracterstica de intercalao de contedo (content-interweaving) acomoda as diferenas entre as estratgias de renderizao do JSP e JSF, tornando desnecessrio adicionar o tag <f:verbatim>.

RESUMO
Este captulo age como um mini guia para o resto do livro; ele tambm lhe d a fundamentao para continuar sua jornada dentro do mundo do JSF alm deste livro. Uma dos diferenciais-chave do JSF sobre as outras tecnologias de view sua abertura e habilidade de adoo de tecnologias emergentes, como XUL, HTC e Ajax, assim como outras tecnologias de view futuras. O JSF tem benefcios claros sobre outras tecnologias porque uma aplicao criada com ele pode continuar a viver enquanto as tecnologias em torno se vo e outras nascem. O JSF pode reduzir os custos de manuteno do desenvolvimento de aplicao, j que apenas um nico modelo de programao necessrio JSF e Java mesmo que os sistemas necessitem de agentes diferentes, como Telnet, mensagem instantnea, PDAs, browsers e outros tipos como leitores de cdigo de barras. Este captulo tratou de detalhes que compem uma aplicao JSF os componentes, modelo de navegao e lgica atravs de managed beans. Tambm exploramos os prs e contras do modelo de componentes JSF e sua clara separao entre apresentao e comportamento, alm de discutirmos a estrutura dos componentes JSF UIComponent, Renderer, subclasse especfica RenderKit e o processador

48

PRO JSF E AJAX

de tags JSP. O captulo tambm detalhou como o ciclo de vida de request do JSF funciona no request inicial e no postback, incluindo a navegao. crucial entender a separao entre apresentao e comportamento de modo a compreender o potencial dos componentes JSF.

Você também pode gostar