JSF Java Server Faces

Objetivos do Curso
Apresentar ao aluno o framework JSF e sua utilização para a criação de aplicações web Mostrar ao aluno as características básicas do framework JSF permitindo a melhor utilização da ferramenta Auxiliar o aluno na criação da sua primeira aplicação web com JSF

Pré-requisitos
Bons conhecimentos em: Orientação a Objetos Linguagem Java™ Conhecimentos básicos em: HTTP Linguagem HTML XML JSP / Servlets

Notação utilizada no curso Negrito Utilizamos para termos e nomes importantes que apareçam pela primeira vez. Monospace Trechos de código Java e arquivos XML. . Itálico Utilizamos para termos e nomes não traduzidos.

Capítulo 1 Introdução ao JSF .

que pode possuir implementações de diferentes fornecedores. Parte da especificação JEE 5.Introdução O que é o JSF (Java Server Faces)? É uma tecnologia que incorpora características do padrão MVC (Model View Control) Framework para interfaces gráficas baseado em componentes e eventos Especificação (interface) de um framework MVC.0 (Java Enterprise Edition) .

Manutenibilidade – Separação clara entre lógica de interface e lógica de negócios Extensibilidade / Flexibilidade. Componentização e reaproveitamento de código. .Introdução Benefícios: Independência de fornecedor (é uma especificação) Especificação construída no modelo MVC. Produtividade – Construção fácil de interfaces ricas. Possui importantes fornecedores de componentes (JBoss/Oracle/Apache). bastante difundido e consolidado.

Capítulo 2 A arquitetura do JSF .

O padrão MVC A arquitetura do framework JSF foi desenvolvida seguindo o design pattern MVC O MVC consiste em dividir a aplicação em 3 camadas distintas: Model: Camada onde estão definidos os conceitos de negócio View: Camada onde estão as definições de interface Controller: Camada intermediária que recebe as requisições da interface e seqüência as operações de negócio .

O padrão MVC View JSP Controlador Swing M2 Controller Model M1 .

A camada Model A camada Model é responsável pelo negócio (business) da aplicação Definição de conceitos e estrutura das informações Implementação das regras de negócio Acesso ao Banco de Dados Essa camada não deve conter definições relativas a: Apresentação de informações Internacionalização de termos Formatação dados para exibição de grids Mensagens de erro para o usuário final .

) As classes de manipulação de dados. que representam os conceitos de negócio usados (aluno. estariam nessa camada: As classes de domínio. cálculos de nota. curso. responsáveis pelo acesso e persistência de informações na base de dados . em um sistema de cadastramento de alunos. histórico escolar.A camada Model Por exemplo. que implementam as regras de negócio (serviços de cadastro de alunos. etc) As classes de persistência de informações. etc.

JSP. etc.A camada View A camada View é responsável pela apresentação dos dados e interfaceamento com o usuário Define a tecnologia de interfaceamento (HTML. Swing.) Ocupa-se com a internacionalização de termos e definição de mensagens amigáveis ao usuário. esta camada não deve: Acessar diretamente a base de dados sistema Implementar algoritmos e regras de negócios . formatando as informações recebidas da camada Model para visualização pelo usuário Visando uma melhor modularização e reaproveitamento de código.

A camada Controller A camada Controller faz a interação entre as camadas View e Model Determina como a camada Model dever ser usada para atingir os objetivos da camada View Nesta camada são definindo os fluxos da aplicação (seqüência de telas a serem exibidas) Determina quais os processos (ações) devem ser executados para completar uma certa requisição Ordena os processos que irão utilizar a camada Model para execução das regras de negócio .

A camada Controller Voltando ao exemplo de controle de alunos. esta camada seria responsável por: Encaminhar as informações inseridas pelo usuário na camada View para as operações de CRUD na camada Model Encadeamento do fluxo de operações para que o usuário fizesse login no sistema antes de acessar a tela de listagem de alunos .

estarão disponíveis para todos os pontos do sistema . uma vez corrigidos. a alteração dos passos (ações) a serem executados em uma requisição Reaproveitamento de código: diferentes interfaces podem utilizar as mesmas rotinas negócio Manutenibilidade: o isolamento de erros é muito mais simples e. de maneira simples.Benefícios do padrão MVC O MVC é um padrão de projeto consagrado para o desenvolvimento modular de sistemas Alterações na exibição da interface (View) não causarão alterações na seqüência de telas (Controller) ou no acesso a dados (Model) Alterações estruturais do banco de dados (Model) são transparentes para telas que exibem as informações (View) O MVC desacopla as camadas de interface e negócios Flexibilidade: a camada Controller permite.

etc.O padrão MVC no JSF O JSF implementa as camadas Controller e View do padrão de projeto MVC em Java para aplicações no ambiente web.) . Os componentes padrão da camada View são muito semelhantes ao HTML. Os valores dos componentes da view são armazenados em propriedades equivalentes no Managed Bean indicado. A camada View é constituída de arquivos de visualização (JSP. Swing. validação. porém implementam os recursos que o JSF suporta (mapeamento para beans.) As visões são contruídas utilizando componentes que geram HTML como padrão. conversão etc. XHTML.

Ao fim de sua execução as actions podem retornar a indicação de uma navigation-rule (regra de navegação) que indica qual o próximo passo no fluxo de execução. de acordo com o valor retornado na action. São elas definem o fluxo das páginas do sistema. Todas as operações da camada Controller são orquestradas por uma servlet central. a Faces Servlet .xml definem qual será a próxima página. As actions por sua vez são métodos do Managed Bean invocados de acordo com eventos mapeados nos componentes de interface. Configuradas no faces-config.O padrão MVC no JSF A camada Controller é constituída pelos Navigation-Rules e Actions As navigation-rules são as regras de navegação da aplicação.

xml 4 – Resposta HTTP gerada para o cliente remoto.Visão esquemática da requisição JSF Servidor Web 1 – Requisição à uma view do sistema Browser Filtro de Requisição HTTP 2 – Requisição encaminhada para Faces Servlet web. Faces Servlet facesconfig.xml 3 – Orquestra etapas do ciclo de vida Ciclo de vida JSF .

Breve visão do Ciclo de Vida JSF Depois que a requisição é encaminhada para a Faces Servlet são executados os 6 passos a seguir: Restore View: Criação de uma árvore DOM que é a representação da view no servidor (chamada viewRoot). Process Validations: Verifica se os valores que “sincronizados” na viewRoot seguem as regras de validação declaradas nos seus respectivos validadores. . Invoke Application: Executa as actions. Apply Request Values: Sincroniza os valores informados na view à árvore de componentes. Render Response: Renderiza a tela de acordo com a árvore de componentes no servidor. atualizando-a em caso afirmativo. Update Model Values: Percorre a viewRoot verificando se os componentes estão mapeados em alguma propriedade do Managed Bean.

Capítulo 3 Criando a camada View .

Como visto na representação esquemática da requisição.Configurando o ambiente O primeiro passo para se criar uma nova aplicação JSF antes mesmo das telas é a configuração do framework no servidor web.xml da aplicação. é necessário que a Faces Servlet receba a requisição HTTP. para que o JSF seja ativado é necessário que o servidor web saiba quando isso deve acontecer. Para que o JSF seja acionado. Como toda servlet isso é configurado no arquivo web. O arquivo a seguir faz a configuração de uma nova aplicação .

faces. Inc.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>Descobrindo Talentos</display-name> <description>Aplicação de exemplo do curso de JSF</description> <session-config> <session-timeout>30</session-timeout> </session-config> <!-.//DTD Web Application 2.webapp.3//EN" "http://java.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/dt/*</url-pattern> </servlet-mapping> </web-app> .Configuração do Filtro para requisições HTTP --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.Configurando o ambiente <?xml version="1.

Exemplos: commandButton. textArea. combobox. Não submetem valores junto com o formulário. armazenando os dados dos componentes (da tela) em uma árvore. Há três tipos principais de componentes: De apresentação: Servem para exibição de textos. commandLink . a viewRoot).Componentes de Interface A estrutura dos componentes das páginas JSF é gerenciada pelo servidor O servidor mantêm o estado da interface. Exemplos: inputText. radio. De entrada: Componentes que o usuário interage entrando com valores. checkbox De ação: Componentes capazes de invocar actions que realizam operações. imagens e mensagens no browser.

LoginMB</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> .dtd"> <faces-config> <managed-bean> <managed-bean-name>loginMB</managed-bean-name> <managed-bean-class>dt.Managed Beans Os Managed Beans são parte da camada de modelo Quando isso acontece eles são tratados como manipuladores da visualização Para que o JSF os conheça. eles devem ser declarados no faces-config.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems.jsf. Inc...control. como no exemplo abaixo <?xml version="1.com/dtd/web-facesconfig_1_1.xml.1//EN" "http://java.sun. </faces-config> .//DTD JavaServer Faces Config 1.

Request: A instância do Managed Bean é mantida apenas durante uma requisição. não sendo armazenado em nenhum escopo. . Application: A instância Managed Bean existirá com seu estado mantido enquanto o servidor estiver no ar. enquanto o usuário estiver com a sessão ativa. isto é. Session: A instância do Managed Bean é mantido entre várias requisições. entre a submissão de uma página e a renderização da próxima.Managed Beans Os Managed Bean podem ser mantidos pelo JSF em quatro tipos de escopo (esses são os mesmos escopos definidos para servlets): None: Esse Managed Bean é criado pelo JSF sempre que for preciso.

Managed Beans
Quando utilizados como representação Java da view os Managed Beans podem definir propriedades associadas aos componentes da interface Essas propriedades devem seguir o padrão JavaBeans, ou seja deve haver um par de métodos get/set para elas Essas propriedades terão seus valores atualizados pelo JSF na 4a etapa do ciclo de vida da requisição (Update Model Values) Para que as propriedades sejam corretamente atualizadas o componente da view deve estar associado à propriedade através de Expression Language O exemplo a seguir mostra o mapeamento da propriedade username do Managed Bean LoginMB com uma caixa de texto da view login.jsp

<h:inputText id=”username” value=”#{loginMB.username}” />

Managed Beans
Podemos registrar no faces-config.xml valores padrão para os campos de um Managed Bean. Por exemplo, o loginManaged Bean mostrado acima poderia ter uma propriedade username que viesse com um valor padrão
<faces-config> <managed-bean> <managed-bean-name>loginMB</managed-bean-name> <managed-bean-class>dt.jsf.control.LoginMB</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>username</property-name> <property-class>java.lang.String</property-class> <value>guest</value> </managed-property> </managed-bean> ... </faces-config>

Usando componentes de interface
Uma das vantagens do JSF é o modelo de utilização de componentes de interface. Todo componente de visualização JSF possui algumas propriedades que nos auxiliam na construção da interface. A propriedade “id” define um id HTML para o componente. Essa será a identificação do componente na viewRoot após a submissão da página Atenção! Caso o componente esteja contido em outro, por exemplo uma caixa de texto contida num formulário, o id do componente na viewRoot será “ID_CONTAINER:ID_COMPONENTE”. No exemplo abaixo o id do outputText será loginForm:username

sendo necessário acessá-la diretamente como veremos mais adiante.Usando componentes de interface A propriedade rendered indica se o componente deverá ser exibido. Isso é feito através da tag interna <f:attribute> Quando isso é feito é necessário informar os atributos name e value. Esses atributos podem ter valor estático ou uma expression language Esses valores só estarão acessíveis ao Managed Bean através da viewRoot. ou não. na view . Outra característica interessante de todo componente JSF é a possibilidade de se passar atributos para eles como se fosse um mapa. .

<%@ taglib uri="http://java.validate}" value="OK" /> </h:form> </f:view> </body> </html> .password}” redisplay=”true”/> <h:commandButton action=“#{loginMB.com/jsf/core" prefix="f" %> <html> <head><title>Exemplo JSF</title></head> <body> <f:view> <h:form id="loginForm"> <h:outputText value="Usuario“ id=“username”/> <h:inputText value="#{loginMB.username}" /> <h:outputText value="Senha"/> <h:inputSecret value="#{loginMB.Construindo interfaces Completemos então nosso exemplo da tela de login construindo o JSP que será sua view e em seguida o Managed Bean que a representará.sun.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.

} /** * Método correspondente a ação disparada pelo commandButton * Obs: Como não tem retorno volta para a própria tela de login */ public void validate() { // Lógica de validação de username e password . } public String getPassword() { return password.. } } . public class LoginMB { private String username. private String password. } public void setPassword(String arg) { password = arg.Construindo interfaces O Managed Bean abaixo representa a tela de login apresentada acima. } public void setUsername(String arg) { username = arg.. public String getUsername() { return username.

enquanto um argentino ficaria satisfeito em ver os mesmo termos em castelhano. . Um usuário que acesse a aplicação no Brasil provavelmente desejará ver os termos na tela em português. O JSF possui um mecanismo padrão. Nesse mecanismo existe um bundle com os valores para cada idioma suportado. As chaves são utilizadas nas views e os valores são os termos nos diferentes idiomas que substituirão as chaves na renderização. muito simples. e um bundle padrão.Internacionalização de termos Um tópico muito importante para aplicações web é a questão de internacionalização de termos na interface. para internacionalização de termos baseado em arquivos de propriedades (conhecidos como resource bundles) O JSF faz uso de arquivos de propriedades (os bundles) onde os termos são cadastrados na forma de chaves e valores.

Internacionalização de termos Um tópico muito importante para aplicações web é a questão de internacionalização de termos na interface. O JSF utiliza a configuração de Locale do browser do usuário para selecionar o bundle adequado para a renderização da tela. muito simples.util.Locale) Nesse mecanismo cada idioma suportado pela aplicação terá seu próprio arquivo de bundle identificado pelo seu Locale Os bundles tem uma estrutura de chave/valor onde as chaves são utilizadas nas views e os valores são os termos nos diferentes idiomas que substituirão as chaves nas views. para internacionalização de termos baseado em arquivos de propriedades (conhecidos como resource bundles) específicos por país e idioma Essa identificação de país e idioma em Java é chamada locale (representada pela classe java. O JSF possui um mecanismo padrão. .

idioma (obrigatório) e país (opcional) O idioma é definido segundo um acrônimo formado por duas letras minúsculas (conforme padrão ISO) “en” – inglês “es” – espanhol “pt” – português O país serve como uma especialização do idioma e é definido segundo um acrônimo formado por duas letras maiúsculas (conforme padrão ISO) “BR” – Brasil “ES” – Espanha “PT” – Portugal “US” – Estados Unidos .Internacionalização de termos O Locale é um elemento determinado por dois parâmetros.

conforme o locale numa mesma aplicação. definindo idioma E país messages_pt_BR. Os arquivos de bundle são configurados no faces-config.properties Locale padrão caso o idioma do browser não seja suportado A ordem com que o JSF vai procurar os bundles de internacionalização é exatamente a apresentada acima.xml .properties messages_pt_PT.Internacionalização de termos O JSF supõe três tipos de bundle. Locale completo.properties Locale por idioma messages_en.properties messages_pt.

xml <?xml version="1.dtd"> <faces-config> .Internacionalização de termos Exemplo de configuração de bundles no faces-config.sun. <application> <locale-config> <default-locale>pt_BR</default-locale> <supported-locale>en</supported-locale> <supported-locale>pt</supported-locale> <supported-locale>pt_BR</supported-locale> </locale-config> <message-bundle>dt.1//EN" "http://java.Messages</message-bundle> </application> .0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems.com/dtd/web-facesconfig_1_1.//DTD JavaServer Faces Config 1... Inc.. </faces-config> ..jsf.

validate}" value="#{msg['button.password}” redisplay=”#” /> <h:commandButton action=“#{loginMB.password']}"/> <h:inputSecret value="#{loginMB.jsf.Messages" var="msg"/> <html> <head><title>#{msg.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.username}" /> <h:outputText value="#{msg['label.com/jsf/core" prefix="f" %> <f:loadBundle basename="dt.sun.confirm']}"/> </h:form> </f:view> </body> </html> .Internacionalização de termos Para utilizar as mensagens na tela de login <%@ taglib uri="http://java.username']}"/> <h:inputText value="#{loginMB.sun.pageTitle}</title></head> <body> <f:view> <h:form id="loginForm"> <h:outputText value="#{msg['label.

> (ou gt). ! (ou not) Validação: empty . <= (ou le). < (ou lt). >= (ou ge) Lógicos: && (ou and).Expression Language Como visto em exemplos anteriores Expression Language é parte fundamental da utilização do JSF Faz a associação entre componentes de interface e propriedades dos Managed Beans Indica as chaves dos bundles de internacionalização Também pode ser usada para inserir lógica na interface Operadores que podem ser utilizados em expressões: Aritméticos: +. -. || (ou or). % (ou mod) Relacionais: == (ou eq). *. != (ou ne). / (ou div).

Capítulo 4 Acionando a camada Controller .

As actions são métodos invocados como resposta a eventos disparados por componentes do tipo <commandButton> e <commandLink>.Actions As actions são os elementos da camada Controller dos Managed Bean. São associados aos componentes de evento por expression language no atributo action dos mesmos. As actions tem as seguintes funções: Invocar as operações da camada Model para execução das regras de negócio Determinar o(s) próximo(s) passo(s) do fluxo de telas da aplicação. conforme seu retorno .

Os métodos das actions não recebem parâmetros. void ou java.lang. (Isto é. As actions são executadas na 5a etapa do ciclo de vida de requisição JSF (Invoke Application) Nesse momento os dados já se encontram validados e atribuídos às suas respectivas propriedades no Managed Bean. por isso é importante que as propriedades do Managed Bean já tenham sido carregadas .Actions As actions são métodos que podem ter dois tipos de retorno.String podem fazer redirecionamentos para outras páginas através de navigationrules definidas no faces-config.String Actions com retorno void podem ser utilizadas para realizar alguma operação.lang. elas retorna para a mesma tela após a sua execução) Actions com retorno java.xml. mas sem interferir no fluxo de navegação.

<to-view-id>1: a página que será invocada quando o método de <from-action> retornar o valor de <from-outcome> <redirect>1: se presente define que deve ser executado um novo request quando a página de <to-view-id> for invocada.(opcional. se não especificado vale para qualquer action) <from-outcome>1: identificador que representa a navigationrule no retorno da action. Uma navigation-rule pode ter diversos navigation-case.Navigation-rules As navigation-rules determinam o fluxo das páginas da aplicação e são definidas no faces-config. se não especificado equivale a false) 1: Elementos internos à tag navigation-case . <from-action>1: define que action irá “disparar” essa navigation-rule (opcional.xml conforme segue: <from-view-id>: tela de origem para a navigation-rule <navigation-case>: define um caso de navegação.

.jsp</to-view-id> </navigation-case> </navigation-rule> . </faces-config> . <navigation-rule> <from-view-id>/dt/pages/login.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/dt/pages/login..Navigation-rules Exemplo para a tela de login <faces-config> .jsp</from-view-id> <navigation-case> <from-outcome>fail</from-outcome> <to-view-id>/dt/pages/fail..jsp</from-view-id> <navigation-case> <from-outcome>sucess</from-outcome> <to-view-id>/dt/pages/sucess..

} } } . this.username. } else { return “fail”..isValidUser(this.password). boolean ok = service. public String validate() { // Obtém o serviço da camada Model que valida usuário UserService service = ServiceLocator. com alguma lógica de validação de usuário.Navigation-rules Completando o exemplo.getUserService(). precisamos alterar o LoginMB. public class LoginMB { . if (ok) { return “success”..

UserService service = ServiceLocator. } faces..username. public void validate() { FacesContext faces = FacesContext.setViewRoot(destPage). "/dt/pages/success.createView(faces.createView(faces.getApplication(). boolean ok = service. } else { destPage = faces.getUserService().renderResponse(). faces.getCurrentInstance().getApplication(). "/dt/pages/success.xml há a alternativa de definir a navigation-rule diretamente no código da action. public class LoginMB { .jsp").password). } } . if (ok) { destPage = faces.getViewHandler() .getViewHandler() .isValidUser(this. UIViewRoot destPage = null.jsp").Navigation-rules Caso não desejemos mapear o fluxo de páginas do facesconfig. this..

Capítulo XX Componentes .

type = submit. reset.Componentes Tag column Funcionalidade Representa uma coluna de dados em um componente UIData. image <table> <form> <img> <input type=hidden> commandButton commandLink dataTable form graphicImage inputHidden Link para outra página ou âncora <a href> Um wrapper para dados tabulares Um formulário Mostra uma imagem Campo escondido em um formulário . Submete um form Renderizado como Uma coluna em uma tabela HTML <input type=type>.

Componentes Tag inputSecret inputText inputTextarea message messages outputFormat outputLabel Funcionalidade Entrada com máscara (senha) Campo de entrada Campo de entrada multi linha Exibe uma mensagem localizada Exibe mensagens localizadas Exibe uma mensagem localizada Label para campo de entrada Renderizado como <input type=password> <input type=text> <textarea> <span> se tem estilos Conjunto de <span> se tem estilos Texto simples <label> .

Componentes Tag outputLink outputText panelGrid panelGroup selectBooleanChe ckbox selectItem selectItems Funcionalidade Link para outra página ou âncora sem action Exibe uma linha de texto Exibe uma tabela Agrupa um conjunto de componentes Permite alterar o valor de uma opção booleana Um item em um componente UISelectOne <input type=checkbox> <option> Renderizado como <a> Texto <table> com <tr> e <td> Representa uma lista de itens Lista de <option> em um UISelectOne .

Componentes Tag selectManyCheckbox Funcionalidade Conjunto de checkboxes para escolha de múltiplos valores Listbox com vários selecionados Combo com seleção de vários itens Listbox com um item selecionado Combo box com seleção de um item Radio buttons Renderizado como <input> do tipo checkbox selectManyListbox selectManyMenu selectOneListbox selectOneMenu selectOneRadio <select> <select> <select> <select> <input type=radio> .

Capítulo XX Listeners .

ActionListeners são úteis para os casos de: Tratamento de eventos dos componentes de interface.event.ActionEvent. Recebem como parâmetro um objeto do tipo javax. Quando configurados. . já que o ActionListener é invocado antes. são invocados mesmo que não haja uma action registrada para o componente. Preparação de atributos para a execução da action. em resposta a um evento ocorrido no componente de ação.faces. Esses listeners podem ser configurados nos componentes que disparam actions. que pode ser utilizado para identificar qual componente invocou o ActionListener.ActionListeners ActionListeners são métodos invocados antes das actions.

Recebem como parâmetro um objeto do tipo javax. Quando configurados. que pode ser utilizado para identificar qual componente invocou o ActionListener.event.faces. para gravar o histórico das alterações de um determinado campo. . via EL (Expression Language) são invocados somente se o valor do componente que o registrou foi alterado.ValueChangeListener Os ValueChangeListeners são métodos de Managed Beans invocados em resposta a alteração do valor de um componente Esses listeners podem ser configurados nos componentes de entrada (que submetem valores).ValueChangeEvent. ValueChangeListeners pode ser usados. por exemplo.

Configurando Listeners Podemos alterar o login.activeValidate}”/> </h:form> </f:view> </body> </html> . <html> <head><title>#{msg.jsp para acrescentar listeners aos seus componentes ..username']}"/> <h:inputText value="#{loginMB.password}” redisplay=”#” /> <h:commandButton action=“#{loginMB..pageTitle}</title></head> <body> <f:view> <h:form id="loginForm"> <h:outputText value="#{msg['label.validate}" value="#{msg['button.changeUsername}”/> <h:outputText value="#{msg['label.confirm']}" actionListener=”#{loginMB.password']}"/> <h:inputSecret value="#{loginMB.username}" valueChangeListener=”#{loginMB.

event. if (this.getOldValue() + “ para ” + e. é necessário criar os métodos no Managed Bean .out.password = “guest”.out.. public class LoginMB { .ActionEvent.event.Configurando Listeners Para atender à associação acima. } . import javax. public void activeValidate(ActionEvent e) { System.faces.faces... } .username = “guest”) { this.println(“O usuário 'guest' tem uma senha padrão”).println(“O username será alterado de ” + e.getNewValue()).. } } public void changeUsername(ValueChangeEvent e) { System.. import javax..ValueChangeEvent.

faces. adicionamos as tags <f:actionListener> ou <f:valueChangeListener> como filho do componente em que queremos utilizar os listeners.ActionListener ou javax.event.Configurando Listeners Uma outra alternativa de configuração. para que sejam utilizados em diferentes pontos da aplicação. Para utilizar as classes listeners.event.ValueChangeListener.faces. é utilizar ActionListeners e ValueChangeListeners externos ao Managed Bean Eles podem ser implementados em classes separadas. Para criar os listeners separados é preciso criar uma classe que implemente as interfaces javax. .

} } import javax.faces.println(“O usuário “guest” tem uma senha padrão”).Configurando Listeners Podemos definir os mesmos listeners definidos no LoginMB conforme o exemplo a seguir import javax.event.faces.ActionEvent.getNewValue()).out. import javax. } } .event.event.ActionEvent.getOldValue() + “ para ” + e. public class DtValueChangeListener implements ValueChangeListener { public void processValueChange(ValueChangeEvent e) { System.faces.ValueChangeListener.println(“O username será alterado de ” + e.ActionListener.event.out. import javax.faces. public class DtActionListener implements ActionListener { public void processAction(ActionEvent e) { System.

<html> <head><title>#{msg.jsf.confirm']}"> <f:actionListener binding="#{dtActionListener}" type="dt.jsp ...username']}"/> <h:inputText value="#{loginMB.pageTitle}</title></head> <body> <f:view> <h:form id="loginForm"> <h:outputText value="#{msg['label.jsf..username}" > <f:valueChangeListener binding="#{dtValueChangeListener}" type="dt.listener. <h:commandButton action="validate" value="#{msg['button.DtValueListener"/> </h:inputText> .listener.Configurando Listeners Para configurar os listeners externos no login.DtActionListener"/> </h:commandButton> </h:form> </f:view> </body> </html> ..

Capítulo 4 Validação .

O JSF fornece alguns validadores.O mecanismo de validação Ao desenvolver a camada web. um dos problemas que sempre encontramos é a validação dos dados fornecidos pelo usuário. Quando os validadores padrão não forem suficiente nós podemos: Validar os valores nas actions Criar métodos validadores nos Managed Beans Criar Classes Validadoras . que podem ser utilizados na maioria das ocasiões.

Validação em Action A forma mais simples de se executar validações é executá-la diretamente na action acionada Essa estratégia só deve ser usada quando temos uma validação de negócio Pode ser necessário executar validações dependentes entre mais de um componente da interface A validação pode depender de algum serviço da camada Model Para validações de entrada de dados (como formato). A validação em action só é executada na quinta etapa do ciclo de vida (Invoke Application) após a etapa de atualização dos dados do managed-bean que ocorre na etapa anterior (Update Model Values) . é melhor utilizar validadores.

Validadores Para validações de entrada de dados apenas (como formatação) o JSF possuí um mecanismo de validação previsto no ciclo de vida da requisição. Eles são adicionados como filho do componente a ser validado. Os validadores padrão são adicionados aos componentes no JSP. Existem três validadores padrão: <f:validateLength>: valida se o tamanho do campo está no intervalo especificado <f:validateLongRange>: valida um intervalo de valores inteiros <f:validateDoubleRange>: valida um intervalo de valores com ponto flutuante . Além de estar previsto no ciclo de vida o JSF traz um conjunto de validadores padrão para serem utilizados.

de acordo com o tipo de validador utilizado. criando um resourceBundle. o mecanismo de validação irá armazenar mensagens de erro. ao FacesContext É recomendado sobrescrever as mensagens dos validadores padrão Para isso deve ser utilizado o validatorMessage do componente de interface que esta sendo validado Nele podemos escrever a mensagem que será exibida se o componente não passar em alguma validação. Também é possível substituir as mensagens padrão do JSF. .Validadores Caso os valores submetidos não passem nas validações.

username}" validatorMessage=”#{msg['error. <html> <head><title>#{msg.password}” redisplay=”#” validatorMessage=”#{msg['error.length']}”> <f:validateLength minimum=”8” maximum=”8”/> </h:inputSecret> .username.length']}”> <f:validateLength minimum=”6” /> </h:inputText> <h:outputText value="#{msg..Validadores O formulário da tela de login poderia ter as seguintes validações .password. </h:form> </f:view> </body> </html> ..pageTitle}</title></head> <body> <f:view> <h:form id="loginForm"> <h:outputText value="#{msg['label.password}"/> <h:inputSecret value="#{loginMB.username']}"/> <h:inputText value="#{loginMB...

podemos implementar o novos validadores implementando a interface javax.setSeverity(FacesMessage.Validadores Customizados Se os validadores padrão não forem suficientes. Object value) throws ValidatorException { try { String strDate = (String) value.parse(strDate). message. sdf.SEVERITY_ERROR). SimpleDateFormat sdf = new SimpleDateFormat(”dd/MM/yyyy”).application. UIComponent component. } catch (ParseException e) { FacesMessage message = new FacesMessage(”chaveDoBundle”).Validator public class DateFormatValidator implements Validator { public void validate(FacesContext faces. throw new ValidatorException(message).faces. } } } .

xml <f:validator validatorId=”DateValidator” /> .validator. <faces-config> .DateValidator</validator-class> </validator> ...jsf.Validadores Customizados Quando utilizamos validadores customizados. <validator> <validator-id>DateValidator</validator-id> <validator-class>dt.xml Agora este validador está disponível para ser reaproveitado em qualquer lugar.. </faces-config> Para utilizar o validador criado devemos utilizar a tag <f:validator> atribuindo ao validatorId o id configurado no faces-config. é necessário registrá-los no faces-config..

Esse método deve ter a seguinte um método com a assinatura: public void validate(FacesContext faces. Object value) Para utilizarmos este método basta mapeá-lo através da a propriedade validator do componente utilizando EL.Métodos Validadores Alternativamente aos validadores externos. <h:inputText validator="#{meuBean.validate}" /> Apesar de também se implementada no Managed Bean os métodos validadores são diferentes das validações nas actions Como os validadores externos eles são invocados na 3 etapa do ciclo de vida (Process Validations) . é possível criar métodos validadores nos Managed Beans. UIComponent component.

a mensagem padrão do JSF será exibida. Quando o campo obrigatório não for preenchido.Validação de campos obrigatórios Um tipo de validação muito importante que não é feita através de validadores é validação de campos obrigatórios. É possível utilizar o campo atributo requiredMessage para definir qual mensagem será exibida se o campo não estiver preenchido. a validação de campo requerido também será ignorada (a exemplo dos outros validadores) . (de forma similar ao atributo validatorMessage) Se alguma action de um componente com o atributo required="true" for invocado. É possível validar os campos obrigatórios apenas setando o atributo required do componente de entrada para true.

Validação no JSF .

Validações que envolvem mais de um campo (como validações de negócio) devem ser implementadas na action.Diagramas dinâmicos Os validadores padrão e validadores customizados validam apenas UM campo. . os valores das propriedades do Managed Bean não terão sido atualizadas (embora os novos valores estejam na viewRoot). Os componentes de action possuem um atributo immediate utilizado para invocar imediatamente a action Esse atributo determina que a 3a e 4a etapas do ciclo de vida (Process Validations e Update Model Values) não serão executadas Como a etapa Process Validations não é executada apenas validações executadas nas actions serão válidas Cuidado como a etapa Update Model Values também não foi executada.

O comportamento correto seria que. . o sistema não irá trocar de página e a mensagem de validação será exibida.Validação no JSF Isso é útil na seguinte situação: Imagine que o usuário do sistema está em uma tela e que preencheu o formulário com valores inválidos. ele não vai submeter o formulário. Porém. Se o atributo immediate for false. Isso é possível utilizando immediate="true" no link do menu. ao clicar no link. o sistema ignorasse o formulário preenchido. quando ele clicar no link do menu. pois irá clicar em um link no menu que exibirá outra página.

As mensagens de erro podem ser exibidas na tela através dos componentes h:messages e h:message. É necessário especificar o id do componente que o h:message está ligado.Exibindo erros de validação Quando algum campo validado não passa nas regras os validadores adicionam mensagens ao FacesContext e o JSF retorna o fluxo para a tela atual. O h:message exibe as mensagens específicas de um componente. O h:messages exibe todas as mensagens de erro que estão no FacesContext no momento em que a tela está sendo renderizada. Mesmo com as tags de mensagem presentes na view caso não haja nenhuma mensagem disponível as mesmas serão ignoradas pelo renderizador .

length']}”> <f:validateLength minimum=”8” maximum=”8”/> <h:inputSecret> .password.username']}"/> <h:inputText value="#{loginMB. <html> <head><title>#{msg.. </h:form> </f:view> </body> </html> .username}" required=”true” requiredMessage=”#{msg['error.username..required']}”/> <h:outputText value="#{msg['label.Exibindo erros de validação Já que a tela de login está usando validadores seria interessante que o usuário pudesse ver os erros caso ocorressem .password']}"/> <h:inputSecret value="#{loginMB.pageTitle}</title></head> <body> <f:view> <h:messages /> <h:form id="loginForm"> <h:outputText value="#{msg['label...password}” redisplay=”true” validatorMessage=”#{msg['error.

getCurrentInstance().Exibindo erros de validação •Em código: FacesContext. . "Login ou senha inválido".SEVERITY_ERROR. "Login ou senha inválido")). new FacesMessage(FacesMessage.addMessage( null.

Capítulo 5 Conversão .

Entretanto o mecanismo de conversão do JSF é muito mais poderoso que isso. As interfaces web geralmente baseadas em HTML só fornecem dados como texto (String) O JSF já possui conversores padrão dos tipos primitivos. Não é preciso se preocupar com esse tipo de conversão. . A conversão que realmente interessa é transformar uma String num objeto que não seja um tipo primitivo Os conversores do JSF resolvem este problema e nos auxiliam a trabalhar com referências para objetos nos Managed Beans. ao invés de trabalhar com tipos primitivos.Conversores Outra característica importante em aplicações web é a questão de conversão de dados.

ele pode ser reutilizado em qualquer interface. pois uma vez que um conversor foi criado. .Conversores Trabalhar com conversores para objetos de domínio facilita muito o desenvolvimento da camada web. Não é preciso receber da interface tipos primitivos e construir os objetos de modelo. Os conversores fazem este trabalho e temos apenas que nos focar em o que fazer com os objetos de modelo. A criação dos conversores para objetos de modelo aumenta a produtividade. A quantidade de erros diminui devido à conversão estar concentrada e um único local.

o JSF já traz alguns conversores padrão <f:convertDateTime>: conversões de formatação (máscara) de data <f:convertNumber>:conversões de formatação (máscara) de números Sua utilização é semelhante com validadores. É necessário adicionar a tag do converter como filho do campo que terá o valor convertido. Assim como acontece com os validadores é possível criar conversores customizados .Conversores Assim como os validadores.

Conversores <h:outputText id= "shipDate" value="#{cashier.shipDate}"> <f:convertDateTime dateStyle="full" /> </h:outputText> <h:outputText value="#{cart.total}" > <f:convertNumber type="currency"/> </h:outputText> .

. String value) { . o conversor irá tranformar o Objeto em uma representação String do mesmo.convert.Conversores Customizados Para criamos conversores customizados precisamos criar uma classe que implemente a interface javax.faces..Converter reimplementando os métodos: getAsObject(): invocado quando os valores de um formulário estiverem sendo submetidos e setados em um Managed Bean. UIComponent component. } } . UIComponent component. o conversor irá tranformar a String que recebida e retornar um Objeto getAsString(): é o caminho inverso... public class DtConverter implements Convert public Object getAsObject(FacesContext faces. invocado quando uma tela está sendo carregada com valores que estão em um Managed Bean. } public String getAsString(FacesContext faces. Object value) { .

User result = service. } } .getUsername(). return user. return result.getUserService(). } public String getAsString(FacesContext faces. Object value) { User user = (User) value.Conversores Customizados Vamos criar um conversor que transforme um “username” num objeto User public class UserConverter implements Convert public Object getAsObject(FacesContext faces. UIComponent component. UIComponent component.findUserByUsername(value). String value) { // Obtém o serviço da camada Model que valida usuário UserService service = ServiceLocator.

jsf.xml Podemos registrar o conversor para o tipo de objeto.jsf...User</converter-for-class> <converter-class>dt.Conversores Customizados Para que este conversor funcione. é necessário registrá-lo no facesconfig.model.UserConverter<converter-class> </converter> ... <faces-config> . <converter> <converter-for-class>dt.converter. para que todo componente que estiver associado a uma propriedade desse tipo passará pelo conversor. </faces-config> .

registrando um converterId no faces-config.xml e utilizar a tag <f:converter> <faces-config> .UserConverter<converter-class> </converter> .converter.user}" converter=“UserConverter”> <f:converter converterId=”UserConverter”/> </h:inputText> ... </faces-config> A definição do converter no jsp seria (duas formas): <h:inputText id=”user” value="#{meuBean. <converter> <converter-id>UserConverter</converter-id> <converter-class>dt..jsf.Conversores Customizados Podemos também utilizar os conversores de maneira semelhante aos validadores..

Capítulo 6 Tópicos Avançados .

.Ciclo de Vida Agora que já utilizamos o JSF e compreendemos o funcionamento de seu ciclo de vida e poderemos entender melhor cada etapa do ciclo.

que é a representação da tela no servidor.1a Etapa – Restore View Etapa responsável pela criação da árvore de componentes (viewRoot) e armazenamento da mesma ao FacesContext O FacesContext mantém toda informação de estado que é necessária para gerenciar os componentes GUI. . O estado da view é armazenado em um objeto viewRoot.

Se algum componente de entrada (não de action) tiver o atributo immediate. Nos componentes de ação a definição do immediate representa a execução imediata da 5a etapa (Invoke Application) . as validações e conversões serão processadas nesta etapa. adiciona uma mensagem de erro que será tratada na 6a etapa (Render Response) Se houver EventListeners registrados para os componentes. Importante – O atributo immediate existem em componentes de entrada e componentes de ação entretanto seu comportamento é diferente. eles são invocados nesta etapa. Se houver erro de conversão.2a Etapa – Apply Request Values Nesta etapa o JSF pega os valores que vieram na requisição (request) HTTP e aplica-os aos seus respectivos componentes na viewRoot.

uma mensagem é adicionada para ser tratada pela última fase do ciclo (Render Response).3a Etapa – Process Validations Nesta etapa são executadas as validações definidas para os componentes de entrada. Se houver falha(s) de validação. já na viewRoot. as próximas fases (Update Model Values e Invoke Application) são ignoradas seguindo direto para a fase Render Response O fluxo de telas retorna para a tela onde foram originados os erros para a exibição das falhas de validação. . Se isso ocorrer. Verifica se os valores armazenados nos componentes. seguem as regras de validação declaradas.

uma mensagem é adicionada para ser tratada pela última fase do ciclo (Render Response) Se isso ocorrer. Se houver algum problema no conversor.4a Etapa – Update Model Values Esta é a etapa de atualização dos valores das propriedades do Managed Bean com os valores já carregados (e validados) da viewRoot Percorre todos os componentes da árvore. . Então são aplicados os conversores (padrão e/ou customizados). a próxima fase (Invoke Application) são ignoradas seguindo direto para a fase Render Response O fluxo de telas retorna para a tela onde foram originados os erros para a exibição das falhas de conversão. verificando se o campo “value” é uma expressão EL que liga o componente a alguma propriedade o Managed Bean.

5a Etapa – Invoke Application Nesta etapa são executadas as regras definidas nas Actions Se houver ActionListeners definidos são executados antes da action. Importante – Se a execução da action foi acionada por um componente com o atributo immediate ativado as fases anteriores (Process Validations e Update Model Values) não foram executadas Por tanto se for necessário obter o valor de algum componente de entrada será necessário buscá-lo diretamente na viewRoot do Faces Context .xml Lembrando que também é possível criar a navigation-rule diretamente no código da action. após a execução da action ela pode alterar definir o próximo passo do fluxo da aplicação ao retornar a identificação de uma navigation-rule do faces-config. Conforme já vimos.

É nesta etapa que o JSF verifica se há mensagens de erro no FacesContext e em caso afirmativo volta o fluxo para a tela original Se houver mensagens durante a renderização da tela as tags <h:messages> e <h:message> são ativadas exibindo as mensagens Caso não haja mensagens de erro a etapa Render Response encaminha o fluxo para a próxima tela do fluxo. conforme especificado pelo retorno da fase anterior (Invoke Application) .6a Etapa – Render Response A última etapa do ciclo de vida do JSF é responsável por renderizar a tela de acordo com a árvore de componentes.

. entretanto é possível criarmos interfaces em JSF sem utilizar as tags JSP. Geralmente ela equivale aos componentes definidos nas views JSP. Podemos manipular a viewRoot de alguma interface no Managed Bean. Existem duas maneira de se manipular a viewRoot diretamente: Utilizar o atributo binding de algum componente. a viewRoot é uma representação das views e seus componentes para o servidor.Manipulando a ViewRoot Como visto anteriormente. Utilizar o FacesContext para obter o objeto que representa a viewRoot e buscar uma referência para o componente da árvore.

HtmlCommandButton Isso permite a criação de páginas com o mínimo possível de código em JSP Essa forma de desenvolver interface é similar desenvolver uma aplicação em swing.html.component.Manipulando a ViewRoot Todo componente que utilizado no JSP tem uma classe que o representa em Java.HtmlPanelGrid. Quando utilizamos a tag <h:panelGrid> a classe utilizada é javax. precisaremos conhecer um pouco mais a fundo a API do JSF. .faces.html.faces. Para isso.component. Quando utilizamos a tag <h:commandButton> a classe utilizada é javax.

e para acessá-la podemos recorrer ao método estático FacesContext.Manipulando a ViewRoot FacesContext: Objeto de contexto que representa o próprio mecanismo do JSF.getCurrentInstance() ViewRoot: A árvore de componentes da interface pode ser obtida dentro do Managed Bean a partir do FacesContext através do método getViewRoot() Dessa forma podemos acessar diretamente os valores submetidos pela tela. Tudo que podemos acessar do funcionamento do framework é buscado através desse contexto. O FacesContext é uma instância singleton gerenciada pelo servidor. mesmo quando o componente de ação for marcado como immediate .

Manipulando a ViewRoot Application: Objeto que encapsula as responsabilidades da aplicação (similar ao que o FacesContext faz com o núcleo funcional do JSF) Esse objeto é responsável por criar os componentes JSF e prover recursos como a ExpressionFactory É possível acessar o Application através do método getApplication() do FacesContext Para criar componentes programaticamente. . é necessário invocar o método createComponent(<componente>. precisamos da ExpressionFactory obtida a partir da instância de Application.COMPONENT_TYPE) na instância de Application obtida no FacesContext Para criar expressões da EL e realizar os mapeamentos para Managed Beans programaticamente.

porém codificando em Java.</head> <body> <f:view> <h:form id="form"> <h:panelGrid binding="#{loginMB.com/jsf/core" prefix="f"%> <%@taglib uri="http://java..grid}" /> </h:form> </f:view> </body> </html> . <%@taglib uri="http://java..sun. já conseguimos fazer quase tudo que faríamos no JSP.Manipulando a ViewRoot Conhecendo esses 3 objetos.sun. Vamos montar como exemplo uma página abaixo (que representa uma listagem de usuários) em Java utilizando a viewRoot.com/jsf/html" prefix="h"%> <html> <head>.

public LoginMB() { // Cria grid de exibição } public HtmlPanelGrid getGrid() { return grid.Manipulando a ViewRoot O código do LoginMB seria: public class LoginMB { private HtmlPanelGrid grid. Com este mapeamento (via binding) podemos construir a interface programaticamente como mostrado a seguir. } public void setGrid(HtmlPanelGrid grid) { this. } . . } A propriedade binding da tag <h:panelGrid> indica que o panelGrid que está no JSP é o objeto HtmlPanelGrid do loginMB Este atributo existe em todos os componentes de interface..grid = grid..

Manipulando a ViewRoot Vejamos uma visão global do LoginMB public class LoginMB { private String username.. } } . } // Criação da grid private HtmlPanelGrid createGrid() { . } public HtmlPanelGrid getGrid() { return grid.grid = grid. } } = arg. private HtmlPanelGrid grid.createGrid() } public public public public String getUsername() { return username... void setUsername(String arg) { username String getPassword() { return password. private String password. } // Método da action public String validate() { . } public void setGrid(HtmlPanelGrid grid) { this.. public LoginMB() { grid = this. void setPassword(String arg) { password } = arg.

// Cria uma EL para associar o componente à propriedade do bean ValueExpression usernameLinkEL = elFactory.Manipulando a ViewRoot Exploremos agora o método createGrid para criar o inputText cujo preenchimento é obrigatório para a propriedade “username” private HtmlPanelGrid createGrid() { FacesContext faces = FacesContext. Application app = faces. ExpressionFactory elFactory = app.username']}".required.getApplication(). txUsername.class). "#{loginMB.setRequired(true).class). "#{msg['error.getCurrentInstance(). String.getELContext(). .getELContext().. // Cria uma EL para buscar uma mensagem no Bundle ValueExpression requiredMessageEL = elFactory. String. txUsername.COMPONENT_TYPE)..createComponent(HtmlInputText.setValueExpression("value".username}". .setId("username"). HtmlInputText txUsername = (HtmlInputText) app . requiredMessageEL). usernameLinkEL).setValueExpression("requiredMessage".createValueExpression( faces. txUsername.createValueExpression( faces. txUsername.getExpressionFactory().

COMPONENT_TYPE). . // Associa o label ao inputText lbUsername. // Cria uma expressão regular para buscar o label no Bundle ValueExpression usernameLabelEL = elFactory.username']}". // Adiciona uma expressão regular para buscar o label no Bundle lbUsername.getELContext(). usernameLabelEL).class)..createValueExpression( faces.Manipulando a ViewRoot Poderiamos adicionar um label para o inputText de “username” (internacionalizado) como na continuação abaixo abaixo: private HtmlPanelGrid createGrid() { . .setValueExpression("value".. "#{msg['label.setFor("username"). String.createComponent( HtmlOutputLabel.. HtmlOutputLabel lbUsername = (HtmlOutputLabel) app..

COMPONENT_TYPE). // Criando o validador para ser associado ao componente LengthValidator validator = (LengthValidator) app.Manipulando a ViewRoot Agora adicionemos um inputSecret para o “password” com uma validação de número de caracteres: private HtmlPanelGrid createGrid() { .createComponent( HtmlInputSecret.setValueExpression("validatorMessage".setMinimum(8). txPassword. validatorMessageEL).setId("password"). // Cria uma expressão regular para buscar o label no Bundle ValueExpression validatorMessageEL = elFactory.VALIDATOR_ID)..createValueExpression( faces.class).password']}".validator. ... .setRedisplay(true). String..setMaximum(12). txPassword. txPassword.createValidator( LengthValidator. validator. txPassword.getELContext(). validator.addValidator(validator). "#{msg['error. HtmlInputSecret txPassword = (HtmlInputSecret) app.

Manipulando a ViewRoot
Para acrescentarmos um label para o inputSecret seguimos o mesmo processo mostrado anteriormente Agora criaremos o botão de submissão:
private HtmlPanelGrid createGrid() { ... // Criando os componentes de ação MethodExpression actionEL = elFactory.createMethodExpression( faces.getELContext(), "#{loginMB.validate}", LoginMB.class, new Class[] {}); HtmlCommandButton btValidate = (HtmlCommandButton) app .createComponent(HtmlCommandButton.COMPONENT_TYPE); btValidate.setActionExpression(action); ...

Manipulando a ViewRoot
Por fim criaremos o HtmlPanelGrid que gerenciará o layout desses componentes:
private HtmlPanelGrid createGrid() { ... // Adicionando componentes à grid HtmlPanelGrid grid = (HtmlPanelGrid) app .createComponent(HtmlPanelGrid.COMPONENT_TYPE); grid.setId("grid"); grid.setColumns(2); List<UIComponent> elems = grid.getChildren(); elems.add(lbUsername); elems.add(txUsername); elems.add(lbPassword); elems.add(txPassword); elems.add(btValidate); return grid; }

Manipulando a ViewRoot
Vantagens: Quando a lógica para construção de tela é complexa, pode ser mais fácil programar a interface em código Java. Utilizando Ajax e construindo as interfaces programaticamente, é possível desenvolver interfaces muito interativas. É possível desenvolver aplicações que a partir de meta-dados gere as interfaces dinamicamente. Desvantagens A produtividade é bem menor para construir interfaces programaticamente. Ainda não há ferramentas para desenhar a interface programaticamente. Para JSPs já existem ferramentas. A complexidade de desenvolver nos beans é muito maior.

entre essas etapas..listener.xml <faces-config> .faces. Para isso podemos implementar a interface javax.. o ciclo de vida do JSF possui 6 etapas. adicionar fases customizadas. <lifecycle> <phase-listener>dt.DtPhaseListener</phase-listener> </lifecycle> . É possível...PhaseListener e registrá-lo no faces-config.jsf.PhaseListener Os PhaseListeners são interceptadores das etapas do ciclo de vida JSF e nos permitem estender as funcionalidades do framework Como vimos anteriormente. </faces-config> .application.

println(”Preparando para execução da fase ” + this. } public void beforePhase(PhaseEvent event) { System.getPhaseId()).out.getPhaseId()). } public PhaseId getPhaseId() { return PhaseId.RESTORE_VIEW.out.PhaseListener O PasheListener a seguir será invocado na fase Restore View A phase que ele será invocado é identificado pelo retorno do método getPhaseId() public class DtPhaseListener implements PhaseListener { public void afterPhase(PhaseEvent event) { System. } } .println(”Já passou pela fase ” + this.

PhaseListener Com o nosso PhaseListener. o ciclo de vida da nossa aplicação ficará assim: DtPhase Listener .

Sign up to vote on this title
UsefulNot useful