Prévia do material em texto
JSF JavaServer Faces, é um Framework Web no padrão MVC como o objetivo de simplificar a construção de interfaces com o usuário para aplicações Java Web e fazer componente UI reutilizável fácil de implementar. Ao contrário da versão anterior da JSF, para a versão 2.0 quase tudo é declarado no arquivo faces-config.xml, além disso foi disponibilizada a permissão para usar anotações para navegação declarada, foi proposto o CDI Bean, o que torna o desenvolvimento mais fácil e mais rápido. JSF é uma excelente tecnologia JAVA no campo de desenvolvimento de aplicações Web. Este é o melhor lugar para passar conceitos JSF de maneira fácil e sequencial. Versão 1.0 Apostila destinada ao curso com carga horária de 32 (trinta e duas) horas Curso JSF Sumário 1. JavaServer Faces..................................................................................................................4 Características da JSF...........................................................................................................4 2. Ajax com JSF..........................................................................................................................6 Enviar uma solicitação do Ajax..............................................................................................6 Renderizar a visão parcial.....................................................................................................6 Processar a visão parcial.......................................................................................................7 Outro Exemplo.......................................................................................................................8 3. Navegação...........................................................................................................................10 Navegação estática e dinâmica...........................................................................................10 Navegação Estática.............................................................................................................11 Navegação Dinâmica...........................................................................................................13 Outros detalhes....................................................................................................................14 Especificar wild-cards......................................................................................................15 4. Facelets................................................................................................................................16 Por que usar Facelets?........................................................................................................16 JSF 2 Templating com exemplo Facelets............................................................................17 1. Layout do modelo........................................................................................................17 2. Cabeçalho, Conteúdo e Rodapé.................................................................................18 3. Utilizando template......................................................................................................20 5. Richfaces..............................................................................................................................22 Baixar os RichFaces............................................................................................................22 Adicionar as bibliotecas RichFaces para o projeto..............................................................22 Registrar o RichFaces no web.xml......................................................................................22 managed bean.....................................................................................................................24 Demonstração dos Componentes.......................................................................................25 6. Primefaces............................................................................................................................28 Características do PrimeFaces............................................................................................28 Aplicativo Exemplo...............................................................................................................28 7. Validação e Conversão........................................................................................................36 Fases do Ciclo de Vida........................................................................................................37 Sobre o atributo imediato.................................................................................................37 Um exemplo de trabalho......................................................................................................38 Conversão............................................................................................................................38 Um conversor para cada ocasião....................................................................................39 Conversores Personalizados...........................................................................................39 Validação..............................................................................................................................42 Validação e o Ciclo de Vida da JSF e seus componentes..............................................42 Padrão de Validação........................................................................................................43 8. JSF e Spring.........................................................................................................................44 Lado Spring..........................................................................................................................44 Lado Java Server Faces......................................................................................................45 Spring Beans no ambiente JSF...........................................................................................45 SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 2 de 50 Curso JSF Apoio da API para a integração...........................................................................................46 9. JSF e Seam 2.......................................................................................................................47 Integração com JSF com EJB 3.0.......................................................................................47 Integração com AJAX...........................................................................................................47 10. Formulário Master/Detail....................................................................................................49 SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 3 de 50 Curso JSF 1. JavaServer Faces Quais são as razões que iniciaram o projeto JSF e porque está tão falado estes dias? Há razões para o desenvolvimento de um novo framework apesar das muitas tecnologias já existentes como JSP, Servlets, Struts, entre outras. Ao desenvolver aplicações complexas Web baseadas em JSP, existe um problema enfrentado com essas tecnologias. Vejamos uma lista de alguns dos problemas enfrentados com as tecnologias anteriores, como JSP e Servlets: • Codificação tediosa e repetitiva – Tecnologias anteriores, como JSP obrigam ao programador realizar um monte de codificação tediosas e repetitivas. • Trabalhar diretamente com HTTP Request e HTTP Response – Usar estas tecnologiasos programadores trabalham diretamente com um solicitação HTTP e responde com objetos que manipula os registros. Por exemplo se o usuário submete o formulário de inscrição, em seguida, o programador escreve o código para obter os valores de cada elemento na forma em que uma variável realiza um posterior processamento. Quando existe a necessidade de recuperar os registros no banco de dados e, em seguida, mostrar no formulário de edição, então, neste caso, o programador escreve o código para recuperar o registro no banco de dados e em seguida, defina os valores nos formulários. • Não disponibilidade de IDE – É outro grande problema que afeta o custo programadores produtividade e desenvolvimento dos aumentos projetos. JSF muda esse cenário, fornecendo uma estrutura intuitiva para os desenvolvedores. Além disso, JSP é uma especificação na qual muitos fornecedores estão desenvolvendo suas próprias implementações. Ambas as implementações livres e comerciais de JSF estão disponíveis estes dias. Pode-se escolher qualquer um deles com base em sua necessidade e orçamento. Agora, em alguns dias os fornecedores de software estarão desenvolvendo uma IDE para o desenvolvimento de aplicativos baseados em JSF que é uma boa notícia para os iniciantes. Uma vez que familiarizado com os conceitos fundamentais do JSF pode-se iniciar o desenvolvimento de projetos de software usando qualquer IDE disponível no mercado. Estas mudanças permitem que o programador torne seu trabalho muito mais fácil. JSF é um componente de estrutura orientada e dirigida a eventos para aplicações Web. Facilita o desenvolvimento de GUI para aplicações Web. JSF permite que os programadores trabalhem com as interfaces extensíveis como botões, caixas de texto, caixas, entre outras. O programador escreve o código para um determinado evento, tais como o botão clicado. Isto faz com que a programação seja muito mais fácil e agora não há necessidade de escrever uma requisição e lógica de processamento de resposta. Características da JSF Uma das característica principais do JSF é que não só foi projetado para a codificação por SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 4 de 50 Curso JSF parte dos especialistas, mas para: • Autores de Páginas – Web designers possuem a experiência com arte gráfica. Podem observar e sentir o projeto de aplicação web em HTML/JSP utilizando bibliotecas de marcas personalizadas de JSF. • Desenvolvedores de Aplicativos – podem integrar este projeto com componentes de interface do usuário. objetos de programa, iniciadores de eventos, conversores, validadores. • Desenvolvedores de Componentes – podem construir componentes de interface personalizados por causa da natureza extensível e personalizável da JSF. Podem criar seus próprios componentes diretamente de classes de componentes de interface do usuário ou estender os componentes padrão do JSF. • Arquitetos de Aplicativos – responsáveis pela criação de aplicativos Web. Definição de navegação de página, garantindo escalabilidade para a aplicação, configurando registro o objeto bean são os principais pontos que um arquiteto de aplicativos trata. • Fornecedores de Ferramentas – JSF é bem adequado para os fornecedores de ferramentas, por exemplo, Sun Java Studio Creator é uma ferramenta de desenvolvimento de aplicativos, que fornecem ferramentas que tiram vantagens do JSF para criar interface do usuário mais fácil. Muitos dos frameworks de desenvolvimento Web surgiram após uma fundamentada existência de Servlet e JSP. Struts surgiu como uma estrutura padrão de aplicativos Web. Tornou-se um framework padrão, porque chegou mais cedo no mercado e com as características necessárias, e os concorrentes tiveram que adicionar os recursos que faltavam para o Struts para obterem sucesso. Assim, tornou-se necessário para Java o advento de um novo framework padrão como um modelo de componente poderoso. Esta foi a principal razão para o desenvolvimento da tecnologia JSF. Então o principal propósito de desenvolver a JSF, foi criar uma coleção de APIs para os componentes de interface com a capacidade de gerir seus estados, manipular os eventos e validação. Struts possui a opção de migrar para JSF. A opção mais simples é usar os componentes. Isto permite tirar proveito de componentes de terceiros. A principal característica da JSF é a facilidade de uso. Torna o desenvolvimento de aplicações Web mais fácil e mais rápido do que em outros frameworks porque suporta componentes de interface do usuário e uma fácil manipulação de eventos. Possui componentes construído por terceiros que pode reduzir o custo de reescrever os elementos existentes e minimizar o tempo de desenvolvimento. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 5 de 50 Curso JSF 2. Ajax com JSF Conforme colocado na capa desta a JSF 2.0 foi uma grande atualização sobre a JSF 1.2, uma das adições mais importantes para essa versão foi quanto ao suporte padrão para Ajax. Muitos conceitos e características são realizados ao longo do RichFaces. JSF vem com uma tag que fornece a funcionalidade Ajax. A tag é chamada de <f:ajax>. Vamos dividir o uso desta tag em três partes: 1. Enviar uma solicitação para o Ajax; 2. Renderizar a visão parcial; 3. Processar a visão parcial. Enviar uma solicitação do Ajax JSF vem com uma tag para enviar uma solicitação do Ajax. Esta tag é realmente um comportamento do lado cliente, e implica não ser utilizado isoladamente em uma página, é sempre adicionado uma tag filha (comportamento) para outro componente da interface do usuário (ou pode até mesmo envolver vários componentes). Usaremos um simples aplicativo para demonstrar essa utilização: <h:form> <h:panelGrid> <h:inputText value="#{bean.texto}"> <f:ajax event="keyup"/> </h:inputText> <h:outputText id="texto" value="#{bean.texto}" /> </h:panelGrid> </h:form> No trecho de código acima devemos tomar cuidado ao disparar uma solicitação Ajax com base no evento onkeyup. Observe que o nome real do evento é keyup. Este cuida de em disparar uma solicitação do Ajax. Em seguida, precisamos descobrir como fazer o processamento da visão parcial. Renderizar a visão parcial Em JSF 1.2 (e sem RichFaces) cada pedido retorna uma visão. Não necessitamos preocupar com que partes da visão JSF queremos atualizar. O conceito básico por trás de Ajax é atualizar apenas as partes da página que realmente precisam. Para conseguir isso, devemos informar esses componentes para o servidor cuja marcação iremos atualizar no navegador. O que tudo isto significa? Agora precisamos especificar quais componentes de visão queremos retornar. Uma visão parcial é processada pelo servidor. Uma parcela é atualizada e enviada como XML para o navegador onde o DOM é atualizado. Este exemplo não é apenas um componente com o texto id. A tag tem um atributo de renderização que aponta para o ID do componente para renderizar a volta. Poderia também ser uma EL (Expression Language). Somando-se ao nosso exemplo, se pareceria com isso: SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 6 de 50 Curso JSF <h:inputText value="#{bean.texto}" > <f:ajax event="keyup" render="texto"/> </h:inputText> <h:outputText id="texto" value="#{bean.texto}" /> Ao usar RichFaces, o mesmo atributo é chamado reRender. O evento que é especificado através do atributo deve ser um no qual o componente pai suporta. Aovisualizar o HTML gerado, teremos: <input id="j_idt5:j_idt7" type="texto" name="j_idt5:j_idt7" onkeyup="mojarra.ab(this, event, 'keyup', 0, 'j_idt5:texto')" /> Processar a visão parcial Ao especificar um evento que não está disponível no componente pai, uma mensagem de erro será exibida ao executar a página. Vejamos agora o código do bean: @ManagedBean(name = "bean") public class Bean { private String texto; // Métodos padrão GET e SET } Vamos supor que também queremos mostrar e atualizar um contador com o comprimento do texto. Adicionar um nova propriedade no bean: private Integer tamanho; // Métodos padrão GET e SET Também adicionamos um método ouvinte Ajax para realizar a contagem, observe que o método recebe um objeto da classe AjaxBehaviorEvent: public void tamanhoListener(AjaxBehaviorEvent event) { tamanho = texto.length(); } Atualizar a página: <h:inputText value="#{bean.texto}" > <f:ajax event="keyup" render="texto tamanho" listener="#{bean.tamanhoListener}"/> </h:inputText> <h:outputText id="texto" value="#{bean.texto}" /> <h:outputText id="tamanho" value="#{bean.tamanho}" /> Adicionamos um identificador para tamanho, use espaço como um separador. No exemplo acima, especificamos que o mesmo deve disparar uma solicitação Ajax e temos de especificar um evento. Se não for especificado, cada componente da interface do usuário tem um evento padrão na qual o pedido Ajax usaria para enviar. A tag <h:inputText>, o padrão evento Ajax é o evento onchange. Nosso exemplo, no entanto, funcionaria, só que ao em vez de onkeyup, teria que usar a tecla tab ou sair do campo de entrada para disparar a requisição Ajax. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 7 de 50 Curso JSF Outro Exemplo Agora que já estamos familiarizados como o Ajax funciona vejamos esse outro exemplo, comecemos pelo Bean: import javax.faces.event.ActionEvent; import javax.faces.model.ManagedBean; import javax.faces.model.SessionScoped; @ManagedBean(name="calcula") @SessionScoped public class Calcula { private Integer conta = 0; public Integer getConta() { return conta++; } public void reset(ActionEvent ae) { conta = 0; } } Neste exemplo temos um contador para criarmos um simples aplicativo como um cronômetro. Um bean simples é utilizado para armazenar a contagem, bem como incrementá-la e redefini-la. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/> <title>Ajax</title> </h:head> <h:body> <h:form id="form1" prependId="false"> <h:outputScript name="jsf.js" library="javax.faces" target="head"/> <h:outputText id="cta" value="#{calcula.conta}"/> <br/> <!-- Incrementar o contador no servidor e no cliente --> <h:commandButton id="btContar" value="Contar" onclick="jsf.ajax.request(this, event, {execute: this.id, render: 'cta'}); return false;"/> <br/> <!-- Reiniciar o contador --> <h:commandButton id="btReiniciar" value="Reiniciar" onclick="jsf.ajax.request(this, event, {execute:'reset', render: 'cta'}); return false;" actionListener="#{calcula.reset}"/> </h:form> </h:body> </html> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 8 de 50 Curso JSF Neste formulário temos três widgets: Um outputText e dois CommandButtons. O "cta" tem o conteúdo do valor da contagem. "btContar" adiciona um elemento ao contador a "cta" e reprocessa apenas o campo, ou seja, não há recarga completa da página. Da mesma forma, "btReiniciar" redefine o valor do contador para 0. A tag <h:outputScript> informa que devemos incluir a biblioteca ajax em nossa página. Isto é necessário para a chamada para o response de jsf.ajax.request. O mesmo texto de saída "cta" é o alvo do ajax, não contém qualquer marcação fora do comum. Temos "btContar" no qual o método onclick faz duas ações: • Uma chamada jsf.ajax.request • Retornar “false”. O retorno falso, para aqueles que não conhecem JavaScript, significa que não deve executar a submissão do formulário. A chamada jsf.ajax.request, possui tem três parâmetros: 1. O objeto de chamada 2. O evento de chamada. 3. O último parâmetro é um objeto JavaScript com duas propriedades - uma executa a propriedade, que tem a lista de ids de todos os componentes JSF que vamos executar - já que estamos executando este botão, vamos incluí-lo na lista como 'this.id'. A segunda propriedade é todos os componentes JSF que queremos atualizar que neste caso, é apenas "cta”. Por último, temos o botão “btReiniciar” com o evento onclick praticamente idêntico, mas não há um atributo adicional, "actionListener". Desde já estamos executando um 'reset', que significa que o JSF vai chamar esse método como parte do botão. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 9 de 50 Curso JSF 3. Navegação O modelo de navegação JSF é tanto declarativa quanto programática, ou seja, a navegação pode ser configurada estaticamente em tempo de implantação ou dinamicamente durante o tempo de execução de uma aplicação Web. Navegação de página para a aplicação JSF é tratado através de regras de navegação em um arquivo de configuração. A navegação pode especificar qual o componente que inicia a solicitação de Web, qual componente Web controla a resposta, e que valor faz com que a navegação para seguir o fluxo. Até agora, vimos uma navegação apenas com base no valor da sequência codificada de um atributo action. Também podemos controlar a navegação usando as expressões de ligação de valor e método de ligação de expressões. Navegação, em seguida, depende do valor da expressão. Navegação estática e dinâmica Ao controlar a navegação através de valores de String do atributo action, o caminho de navegação deve ser conhecido quando o aplicativo é implantado. Chamamos isso de Navegação Estática, porque o fluxo é determinado estaticamente e não é modificado. Sendo o mesmo para cada solicitação. Quando usamos a navegação estática, codificamos explicitamente um valor para o atributo ação de uma Custom tag JSF. Ao definir as regras de navegação em um arquivo de configuração. A regra especifica o fluxo de navegação quando o <from-outcome> de uma página coincide com o valor do atributo action. Quando isso ocorre, a navegação flui para o <to-view-id> especificado. Estes elementos são parte de um elemento de regra de navegação em um arquivo de configuração, o faces-config.xml. Ao controlar a navegação através do valor de expressões de ligação ou métodos de ligação de expressões, o caminho de navegação não conhece quando o aplicativo é implantado. Na verdade, o fluxo de navegação pode variar de acordo com a solicitação pedida, dependendo do valor da expressão. Chamamos isso de Navegação Dinâmica. Para uma navegação dinâmica, usamos uma expressão de valor de ligação ou o método de ligação de expressão, como o valor do atributo action. Com um valor de expressões de ligação, o valor da propriedade deve ser do tipo String. Com o método de expressões de ligação, o método não obtém parâmetro e retorna um valor do tipo String: public String search(); O valor String retornado pelo método é comparado ao valor especificado na regra de navegação para determinar aonde o fluxo de controle deve ir. Resumidamente: • Navegação Estática é recomendado quando a saída de uma páginaé conhecido com antecedência e é sempre mais fácil prever a saída da página atual. • Navegação Dinâmica quando a saída da página atual é altamente imprevisível e a saída depende, principalmente, a execução de alguma regra de negócio. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 10 de 50 Curso JSF Navegação Estática Como mencionado anteriormente, se a resposta da página é conhecido antecipadamente, então este tipo de navegação pode ser escolhido. Tomemos um exemplo para ilustrar isso. Vamos exibir uma página da Web (a página de login) que solicita a entrada do usuário como o nome de usuário e a senha. Uma vez que esses valores são inseridos e o formulário é enviado, em seguida, uma página de boas-vindas é exibida. Aqui sabe-se que o resultado da página de login é sempre a página de boas vindas. login.jsp <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Aplicação de Login</title> </head> <body> <h1>Aplicação de Login</h1> <f:view> <h:form> <p>Login: <h:inputText value="#{LoginBean.username}" id="usernameTextField" required="true"/> <h:message for="usernameTextField" /> </p> <p>Senha: <h:inputSecret value="#{LoginBean.password}" id="passwordTextField" required="true"/> <h:message for="passwordTextField" /> </p> <h:commandButton value="Submit Values" action="loginWelcome"/> </h:form> </f:view> </body> </html> Contém os campos de entrada do usuário para usuário e senha é mostrada a seguir. Um botão está ligado na extremidade da forma de apresentação da informação pedido para o servidor. LoginBean.java package net.javabeat.articles.jsf.navigation; public class LoginBean { private String username; private String password; public LoginBean() { } public String getUsername() { SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 11 de 50 Curso JSF return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } A classe UserBean encapsula o nome de usuário e senha para as propriedades que detém a informação solicitada. O nome do usuário e os valores da senha digitada pelo usuário será mapeada diretamente para UserBean.username e UserBean.password através de '#{UserBean.username}' as expressões e '#{UserBean.password}'. faces-config.xml <?xml version='1.0' encoding='UTF-8'?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <managed-bean> <managed-bean-name>LoginBean</managed-bean-name> <managed-bean-class> net.javabeat.articles.jsf.navigation.LoginBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <description></description> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>loginWelcome</from-outcome> <to-view-id>/loginWelcome.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config> Este arquivo de configuração contém uma entrada de definição do bean gerenciado por LoginBean através do elemento "managed-bean”. Em seguida, vem a parte mais importante que está relacionada ao Tratamento da navegação. Definimos a regra de navegação para a página login.jsp através dos elementos de regra de navegação “from- view-id“. A presença de “from-view-id“ é que a regra será aplicável para o resultado da página login.jsp. Em seguida, definimos um elemento interno chamado de navegação que define uma saída possivelmente o único para a página atual. Note a presença de elementos “from-outcome“ e “to-view-id“. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 12 de 50 Curso JSF O valor “LoginWelcome” representa um dos resultados lógicos da página login.jsp. O valor para “to-view-id” aponta para a página de resposta seguinte a ser exibida. Para resumir, se a página atual é login.jsp e no resultado da página é "loginWelcome”, então a próxima página a ser exibida é a loginWelcome.jsp. Navegação Dinâmica Vejamos como controlar o comportamento de uma navegação dinâmica nesta seção. Vamos estender o exemplo acima para fazer isso. Neste momento, exibmos uma página de sucesso de login quando o nome de usuário e senha são valores combinados 'guest', mais uma página de falha de logon é exibida. Como os valores são inseridos pelo usuário apenas no tempo de execução, a próxima exibição a ser exibida não pode ser prevista. Isto significa que o ponto de vista seguinte a ser selecionado depende da execução de alguma regra de negócios no código. Adicione o seguinte método na classe LoginBean: public String nextPage() { if (username.equals("guest") && password.equals("guest")) { return "loginSuccess"; } return "loginFailure"; } O método nextPage() determina a próxima página a ser exibida com base nos valores do nome de usuário e a senha. Se tanto o nome de usuário e senha é 'guest' uma página de sucesso de login será exibida. Estamos retornando loginSucess (para o sucesso da entrada) e loginFailure (para falha na entrada). Adicione o seguinte regra de navegação no arquivo faces-config.xml: <navigation-rule> <description></description> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>loginSuccess</from-outcome> <to-view-id>/loginSuccess.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>loginFailure</from-outcome> <to-view-id>/loginFailure.jsp</to-view-id> </navigation-case> </navigation-rule> Adicionamos dois elementos “navigation-case” para a página de login, uma para o sucesso e outra para o fracasso. O arquivo de configuração mostra a página login.jsp, se o resultado lógico for loginSuccess, em seguida, mostrar a página loginSuccess.jsp. Caso contrário, se o resultado lógico for loginFailure, depois a página loginFailure.jsp deve ser exibida. A página loginSuccess.jsp apenas exibe uma mensagem de Login Bem-Sucedido junto ao nome do usuário que é retirado do bean gerenciado por LoginBean. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 13 de 50 Curso JSF loginSuccess.jsp <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Sucesso no Login</title> </head> <body> <h3>Entrada com Sucesso</h3> <f:view> <h:form> <p>Você teve sucesso com o Login.<p/> <p>Bem vindo <h:outputText value="#{LoginBean.username}"/><p/> </h:form> </f:view> </body> </html> loginFailure.jsp <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <html> <head> <title>Login Falhou</title> </head> <body> <h3>Login Falhou</h3> <f:view> <h:form> <p>O login id <h:outputText value="#{LoginBean.username}"/> não é encontrado.<p/> <p>Por favor tente novamente...</p> </h:form> </f:view> </body> </html> Outros detalhes Para finalizar, veremos os detalhes “left-over” do mecanismo de Navegação da JSF. Vamos cobrir o uso do elemento "request" bem como da especificação do uso wild-strings.Normalmente, quando um redirecionamento é encontrado pelo servidor, a solicitação atual for encerrada, o controle é redirecionado para o navegador e este faz a requisição (que está disponível como a URL na instrução de redirecionamento). O mesmo acontece aqui também. Considere o seguinte elemento: <navigation-case> <from-outcome>loginFailure</from-outcome> <to-view-id>/loginFailure.jsp</to-view-id> <redirect/> </navigation-case> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 14 de 50 Curso JSF Suponha-se, que o resultado da página login.jsp é loginFailure.jsp. Se o redirecionamento do elemento não está presente no arquivo de configuração, então a URL do navegador ainda mostra o login.jsp e não loginFailure.jsp (embora o conteúdo exibido no navegador será loginFailure.jsp). A presença do elemento redirecionará o controle do servidor para o navegador e é feita uma solicitação para a página de destino loginFailure.jsp. Especificar wild-cards Também é possível especificar um caractere wild-card (*) no elemento 'from-view-id'. Por exemplo, digamos que desejamos lidar com o mecanismo de navegação para todos os arquivos JSF dentro da pasta "registo", então podemos ter o seguinte elemento: <navigation-rule> <from-view-id>/registro/*</from-view-id> <navigation-case> ... </navigation-case> </navigation-rule> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 15 de 50 Curso JSF 4. Facelets Enquanto JavaServer Faces e JSP são feitos para serem alinhados, Facelets estão fora da especificação JSP e fornece uma alta performance, a JSF tecnologia é centrada no ponto de vista. Qualquer um que tenha criado uma página JSP será capaz de fazer o mesmo com Facelets e utilizar a familiaridade de tags no padrão XML. A diferença está internamente, onde toda a carga do fornecedor JSP é removida para aumentar consideravelmente a JSF como uma plataforma que pode proporcionar o simples desenvolvimento “plug-and-go“ sem a necessidade de desenvolvimento de tags JSP. Aqui está um exemplo de como é fácil definir uma visão com Facelets: <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jstl/core"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Hello</title> </head> <body> <form id="helloForm" jsfc="h:form"> <h2>Oi. Meu nome é Duke. Estou pensando em um número entre #{UserNumberBean.minimum} e #{UserNumberBean.maximum}. Pode advinhar qual é? </h2> <img id="waveImage" src="wave.med.gif" /> <input type="text" jsfc="h:inputText" id="userNo" value="#{UserNumberBean.userNumber}" validator="#{UserNumberBean.validate}"/> <input type="submit" jsfc="h:commandButton" id="submit" action="success" value="Submeter" /> <p /> <h:message showSummary="true" id="errors1" for="userNo"/> <p /> <c:forEach begin="1" end="4" varStatus="v"> #{view.viewId} #{v.index}<br/> </c:forEach> </form> </body> </html> Você pode estar pensando que a marcação parece extremamente familiar. Esse é o ponto. Não existe qualquer necessidade de aprender uma outra linguagem de templates ou esquema. Por que usar Facelets? Facelets não é dependente de um contêiner JSP. Isso significa que podemos começar a usar os novos recursos de JSF. Aqui está uma pequena lista dos recursos do Facelets: • Trabalha com JSF 1.1 e JSF 1.2, incluindo a RI da Sun e o Apache MyFaces. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 16 de 50 Curso JSF • Tempo zero para o desenvolvimento de tags para UIComponents • Rápido templating/decoradores para componentes e Páginas • Capacidade de especificar UIComponents em arquivos separados • Line – Tag – Atribute, erros são reportados precisamente • Especificar as tags em arquivos separados, mesmo embalado com jar • Suporte a EL completo, incluindo funções • Em tempo de compilação Validação EL • Arquivos de configuração XML não são necessárias, mas estão disponíveis Todos os desenvolvedores desejam um projeto mais amigável. Desenvolvedores passam um tempo considerável definindo: UIComponents, Conversores e Validadores no arquivo faces- config.xml. Facelets só exige a especificação de um apelido ao nome para ligar seus objetos em suas páginas (sem XML necessário). A chave é a facilidade de integração e desenvolvimento. JSF 2 Templating com exemplo Facelets Neste exemplo, mostramos a utilização de 4 tags Facelets para construir a página a partir de um modelo: • ui:insert – Usado em arquivo de modelo, define o conteúdo que vai substituir pelo arquivo que carrega o modelo. O conteúdo pode ser substituir por um tag ui:define. • ui:define – Define o conteúdo que é inserido no modelo com uma correspondência pela tag ui:insert. • ui:include – Semelhante a tag jsp:include do JSP padrão, inclui o conteúdo de outra página XHTML. • ui:composition – Se for usado com um atributo "template", o modelo especifico é carregado, e os filhos desta tag definem o layout do modelo, caso contrário, é um grupo de elementos, que pode ser inserido em algum lugar. Além disso, JSF remove as tags outside da tag ui:composition. 1. Layout do modelo Para JSF, um arquivo modelo é apenas um simples arquivo XHTML, com poucas tags no padrão Facelets para definir o layout do modelo. commonLayout.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 17 de 50 Curso JSF xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> <h:outputStylesheet name="common-style.css" library="css" /> </h:head> <h:body> <div id="page"> <div id="header"> <ui:insert name="header"> <ui:include src="/template/common/commonHeader.xhtml" /> </ui:insert> </div> <div id="content"> <ui:insert name="content" > <ui:include src="/template/common/commonContent.xhtml" /> </ui:insert> </div> <div id="footer"> <ui:insert name="footer" > <ui:include src="/template/common/commonFooter.xhtml" /> </ui:insert> </div> </div> </h:body> </html> Neste modelo, definimos o layout da Web padrão, com os seguintes detalhes: • Usamos a tag h:outputStylesheet para incluir um arquivo CSS no cabeçalho para denominar o layout de página inteira. • Usamos a tag ui:insert para definir três seções substituíveis: cabeçalho, conteúdo e rodapé. • Usamos a tag ui:include para fornecer um conteúdo padrão, se nenhuma substituição é especificada quando o modelo for usado. 2. Cabeçalho, Conteúdo e Rodapé Codificação para os três conteúdos da página. commonHeader.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition> <h1>Este é o cabeçalho padrão</h1> </ui:composition> </body> </html> commonContent.xhtml SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 18 de 50 Curso JSF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition> <h1>Este é o conteúdo padrão</h1> </ui:composition> </body> </html> commonFooter.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition> <h1>Este é o rodapé padrão</h1> </ui:composition> </body> </html> Quando estas páginas forem inseridas no arquivo modelo, todas as tags ui:composition serão removidas. Por exemplo: commonHeader.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"> <body> TODAS AS TAGS acima desta linha serão removidas pelo JSF <ui:composition> <h1>Este é o cabeçalho padrão</h1> </ui:composition> TODAS AS TAGS abaixo desta linha serão removidas pelo JSF </body> </html> JSF utiliza os seguintes elementos para inserir no arquivo de modelo: <ui:composition> <h1>Este é um cabeçalho padrão</h1> </ui:composition> Ao inserir o modelo commonLayout, tornou-se: commonLayout.xhtml ... <h:body> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 19 de 50 Curso JSF <div id="page"> <div id="header"> <h1>Este é um cabeçalho padrão</h1> </div> ... 3. Utilizando template Para fazer uso de um modelo já existente, por exemplo. CommonLayout.xhtml, utilize a tag ui:composition com um atributo template. Vejamos os seguintes exemplos: default.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:body> <ui:composition template="template/common/commonLayout.xhtml"> </ui:composition> </h:body> </html> A página JSF carrega o modelo commonLayout.xhtml e exibe todo o conteúdo da página padrão. page1.xhtml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 20 de 50 Curso JSF xmlns:ui="http://java.sun.com/jsf/facelets"> <h:body> <ui:composition template="/template/common/commonLayout.xhtml"> <ui:define name="content"> <h2>Este é o conteúdo da Página 1</h2> </ui:define> <ui:define name="footer"> <h2>Este é o rodapé da Página 1</h2> </ui:define> </ui:composition> </h:body> </html> Ao carregar a página JSF para o modelo commonLayout.xhtml e usar a tag ui:define para substituir a tag ui:insert, que foi definida no arquivo modelo. Enquanto o nome da tag ui:define é comparado com o nome da tag ui:insert, que foi definida para o modelo, ui:insert teve seu conteúdo substituído. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 21 de 50 Curso JSF 5. Richfaces RichFaces, como a maioria dos outros frameworks de componentes projetados para uso com JSF, foi extensivamente modificado para permitir total compatibilidade. Nesta seção descreveremos todas as ações necessárias e configurações que devem ser feitas para conectar os componentes RichFaces em uma aplicação JSF. Baixar os RichFaces A última versão dos componentes RichFaces está disponível na área de Downloads do JBoss RichFaces na comunidade JBoss: http://labs.jboss.com/jbossrichfaces/downloads São arquivos binários (baixar os arquivos *.bin.zip ou *.bin.tar.gz) contém compilado, pronto para usar a versão do RichFaces com o conjunto básico. Para começar com RichFaces no sistema de arquivo de computador criar uma nova pasta com o nome "RichFaces", e nesta baixe e descompacte o arquivo com os binários. Adicionar as bibliotecas RichFaces para o projeto Na pasta com os arquivos descompactados anteriormente abra pasta lib. Esta pasta contém três arquivos *.jar com a API, interface do usuário e as bibliotecas de execução. Copiar os arquivos JARs na pasta lib para a pasta WEB-INF/lib da aplicação JSF. Uma aplicação JSF com RichFaces assume que os arquivos JARs a seguir estão disponíveis no projeto: commons-beanutils-1.7.0.jar, commons-collections-3.2.jar, commons- digester-1.8.jar, commons-logging-1.0.4.jar, jhighlight-1.0.jar. Registrar o RichFaces no web.xml Depois de adicionar as bibliotecas RichFaces ao projeto é necessário registrá-las no arquivo web.xml. Adicionar seguintes linhas neste arquivo: ... <!-- Ligar o "Blue Sky" skin para o projeto --> <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>blueSky</param-value> </context-param> <!-- Fazer o RichFaces se espalhar para os controles padrão HTML --> <context-param> <param-name>org.richfaces.CONTROL_SKINNING</param-name> <param-value>enable</param-value> </context-param> <!-- Definir e mapear o filtro RichFaces --> <filter> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 22 de 50 Curso JSF <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>richfaces</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> ... Finalmente, o arquivo web.xml deve ficar assim: <?xml version="1.0"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>Greeter</display-name> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>org.richfaces.SKIN</param-name> <param-value>blueSky</param-value> </context-param> <context-param> <param-name>org.richfaces.CONTROL_SKINNING</param-name> <param-value>enable</param-value> </context-param> <filter> <display-name>RichFaces Filter</display-name> <filter-name>richfaces</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>richfaces</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <!-- Faces Servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 23 de 50 Curso JSF <!--Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <login-config> <auth-method>BASIC</auth-method> </login-config> </web-app> managed bean A aplicação "RichFaces Greeter" necessita de um managed bean. Na pasta do projeto criar um novo managed bean com nome de Usuario no pacote demo com o seguinte código: package demo; public class Usuario { private String nome = ""; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Registrando o managed bean no arquivo faces-cofig.xml: <?xml version="1.0" encoding="UTF-8"?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <managed-bean> <description>Bean do Usuario</description> <managed-bean-name>usuario</managed-bean-name> <managed-bean-class>demo.Usuario</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>nome</property-name> <property-class>java.lang.String</property-class> <value/> </managed-property> </managed-bean> </faces-config> O aplicativo "RichFaces Greeter" tem apenas uma página JSP. Criar a página index.jsp na pasta raiz do conteúdo Web e adicionar o seguinte código: SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 24 de 50 Curso JSF <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <!-- RichFaces tag library declaration --> <%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%> <%@ taglib uri="http://richfaces.org/rich" prefix="rich"%> <html> <head> <title>RichFaces Greeter</title> </head> <body> <f:view> <a4j:form> <rich:panel header="RichFaces Greeter" style="width: 315px"> <h:outputText value="Seu nome:"/> <h:inputText value="#{usuario.nome}"> <f:validateLength minimum="1" maximum="30"/> </h:inputText> <a4j:commandButton value="Obter Saudação" reRender="greeting"/> <h:panelGroup id="greeting"> <h:outputText value="Olá, " rendered="#{not empty usuario.nome}"/> <h:outputText value="#{usuario.nome}"/> <h:outputText value="!" rendered="#{not empty usuario.nome}"/> </h:panelGroup> </rich:panel> </a4j:form> </f:view> </body> </html> A aplicação utiliza três componentes RichFaces: rich:panel utilizado como um contêiner visual para a informação; a4j:commandButton com suporte embutido para Ajax que permite prestar uma saudação dinâmica após um respose e a4j:form auxilia ao botão executar a ação. Observamos, que a biblioteca RichFaces deve ser declarado em cada página JSP. Para Facelets devemos adicionar as seguintes linhas para declaração da biblioteca de tag: <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> ... </ui:composition> Demonstração dos Componentes RichFaces possui diversos componentes e tem mais de 20 atributos específicos, além de atributos gerais que podem ser substituídos. No entanto, no uso comum dos componentes não são difíceis de configurar, como a maioria dos atributos com padrões razoáveis. Vejamos alguns desses componentes a seguir. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 25 de 50 Curso JSF Calendar: Um componente pop-up que permite seleções de data. Pick List: Uma seleção e ordenação componente. Lista de Escolha que pode mover os itens entre as áreas disponíveis e selecionadas, para cima e para baixo na área selecionada. AutoComplete: Substituto para o componente de entrada Suggestion Box que fornece sugestões clicáveis para preencher ou completar uma entrada. Tab Panel: um componente de saída que cria páginas com guias. Accordion: Substituto para o componente de entrada Panel Bar. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 26 de 50 Curso JSF Collapsible Panel: Substituto para o componente Simple Toggle Panel. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 27 de 50 Curso JSF 6. Primefaces PrimeFaces é um projeto de extensão que tem o objetivo ser uma biblioteca de componentes JSF leve e rápida, sendo um conjunto de diversos componentes. Este é um projeto estendido pois define componentes úteis que falta em outras bibliotecas da JSF. Utiliza padrões e é altamente compatível com o framework JSF. A extensão PrimeFaces não é somente um conjunto de componentes, conversores e comportamentos para o cliente. Também consiste de plugins úteis para o framework Maven e vários add-ons simplificadores para a Web e, especialmente, para o desenvolvimento JSF. A extensão PrimeFaces é um projeto open source que está sob a licença do Apache. Pode- se usá-lo livremente em projetos de código aberto ou comerciais segundo os termos da licença. Características do PrimeFaces Resumidamente PrimeFaces é uma biblioteca de componentes de código aberto para a JSF com mais de 100 componentes. Possui as seguintes características: • Um variado conjunto de componentes de interface para o usuário (DataTable, AutoComplete, HtmlEditor, Charts, entre outros); • Somente a configuração XML é necessária e não há dependências necessárias; • Built-in Ajax baseado no padrão JSF 2.0 Ajax APIs; • Mais de 25 temas internos; e • Documentação com exemplos de código. Aplicativo Exemplo Vamos construir uma aplicação exemplo utilizando a extensão PrimeFaces com as seguintes características: 1. Uma tela de Login que recebe o nome e a senha do usuário para autenticá-lo. 2. Ao ser bem-sucedido o login será exibida uma tela de pesquisa do usuário. Os usuários podem pesquisar outros usuários pelo seu nome. Os resultados da pesquisa serão exibidos em um DataTable com paginação, classificação e filtragem de apoio. 3. Ao clicar em uma linha, os detalhes do usuário serão exibidos em um formulário. Inicialmente, realizar o download da bibliotecas do JSF: http://javaserverfaces.java.net/download.html Copiar os arquivos: jsf-api-X.X.X.jar, jsf-impl-X.X.X.jar e jstl-X.X.X.jar para a pasta: WEB-INF/lib Baixar o PrimeFaces em: SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 28 de 50 Curso JSF http://www.primefaces.org/downloads.html Colocar o arquivo primefaces X.X.X.jar na pasta: WEB-INF/lib Configurar FacesServlet no arquivo web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" > <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern></servlet-mapping> </web-app> Criar um arquivo chamado faces-config.xml na pasta WEB-INF: <?xml version="1.0" encoding="utf-8"?> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0"> <!-- Não há declarações ManagedBean aqui pois usamos anotações @ManagedBean. --> </faces-config> Criar a página index.jsp, que desvia para a tela de login: <jsp:forward page="login.jsf"></jsp:forward> Criar a página login.xhtml: <html xmlns="http://www.w3c.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui"> <h:head> <link type="text/css" rel="stylesheet" href="themes/bluesky/skin.css" /> </h:head> <h:body> <center> <p:panel header="Entrada no Sistema" style="width: 350;"> <h:form> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 29 de 50 Curso JSF <h:panelGrid columns="2" cellpadding="2"> <h:outputLabel for="#{userManagedBean.username}" value="Usuário"/> <h:inputText value="#{userManagedBean.username}" label="UserName"> </h:inputText> <h:outputLabel for="#{userManagedBean.password}" value="Senha"/> <h:inputSecret value="#{userManagedBean.password}"></h:inputSecret> <h:commandButton type="submit" value="Login" action="#{userManagedBean.login}"> </h:commandButton> </h:panelGrid> </h:form> </p:panel> <div><h:messages ></h:messages></div> </center> </h:body> </html> Obter e disponibilizar o tema blusky de pacote PrimeFaces. Criar um arquivo chamado home.xhtml que contém o UserSearchForm, Resultados do dataTable e UserDetails Panel. <html xmlns="http://www.w3c.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui"> <h:head> <link type="text/css" rel="stylesheet" href="themes/bluesky/skin.css" /> </h:head> <h:body> <center> <h:form> <p:panel header="Formulário de Busca para Usuários" style="width: 700;"> <h:form> <h:panelGrid columns="3" cellpadding="2"> <h:outputLabel for="#{userManagedBean.searchUser}" value="Usuário"/> <h:inputText value="#{userManagedBean.searchUser}" label="Usuário"> </h:inputText> <h:commandButton type="submit" value="Search" action="#{userManagedBean.searchUser}"> </h:commandButton> </h:panelGrid> </h:form> </p:panel> <p:dataTable var="user" value="#{userManagedBean.searchUsersResults}" selection="#{userManagedBean.selectedUser}" selectionMode="single" dynamic="true" onRowSelectUpdate="userUpdateForm" onRowUnselectUpdate="userUpdateForm" rowSelectListener="#{userManagedBean.onUserSelect}" rowUnselectListener="#{userManagedBean.onUserUnselect}" paginator="true" rows="5" style="width: 700"> <p:column sortBy="#{user.userId}" filterBy="#{user.userId}"> <f:facet name="header"> <h:outputText value="Id" /> </f:facet> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 30 de 50 Curso JSF <h:outputText value="#{user.userId}" /> </p:column> <p:column sortBy="#{user.username}" filterBy="#{user.username}"> <f:facet name="header"> <h:outputText value="Nome" /> </f:facet> <h:outputText value="#{user.username}" /> </p:column> <p:column sortBy="#{user.emailId}" filterBy="#{user.emailId}"> <f:facet name="header"> <h:outputText value="Email" /> </f:facet> <h:outputText value="#{user.emailId}" /> </p:column> <p:column parser="date" sortBy="#{user.dob}" filterBy="#{user.dob}"> <f:facet name="header"> <h:outputText value="DOB" /> </f:facet> <h:outputText value="#{user.dob}" > <f:convertDateTime pattern="dd/MM/yyyy" /> </h:outputText> </p:column> </p:dataTable> <p:panel id="userDetailsPanelId" header="Detalhes" style="width: 700;"> <h:panelGrid columns="2" cellpadding="2" id="userUpdateForm" border="0" > <h:outputLabel for="#{userManagedBean.selectedUser.userId}" value="ID"/> <h:inputText value="#{userManagedBean.selectedUser.userId}" style="width: 100;" readonly="true"></h:inputText> <h:outputLabel for="#{userManagedBean.selectedUser.username}" value="Usuário"/> <h:inputText value="#{userManagedBean.selectedUser.username}" readonly="true"> </h:inputText> <h:outputLabel for="#{userManagedBean.selectedUser.emailId}" value="Email"/> <h:inputText value="#{userManagedBean.selectedUser.emailId}" readonly="true"> </h:inputText> <h:outputLabel for="#{userManagedBean.selectedUser.gender}" value="Sexo"/> <h:inputText value="#{userManagedBean.selectedUser.gender}" readonly="true"> </h:inputText> <h:outputLabel for="#{userManagedBean.selectedUser.dob}" value="DOB"/> <h:inputText value="#{userManagedBean.selectedUser.dob}" readonly="true"> <f:convertDateTime pattern="dd/MM/yyyy" /> </h:inputText> </h:panelGrid> </p:panel> </h:form> </center> </h:body> </html> Criar a classe de domínio User.java: package x25.com.tutorial; SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 31 de 50 Curso JSF import java.util.Date; public class User { private Integer userId; private String username; private String emailId; private String phone; private Date dob; private String gender; private String address; public User() { } public User(Integer userId, String username, String emailId, String phone, Date dob, String gender, String address) { this.userId = userId; this.username = username; this.emailId = emailId; this.phone = phone; this.dob = dob; this.gender = gender; this.address = address; } // Métodos padrões GET/SET } Criar a classe UserService.java, que atua como uma simulação da tabela na base de dados. package x25.com.tutorial; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; public class UserService { private static final Map<Integer, User> USERS_TABLE = new HashMap<Integer, User>(); static { USERS_TABLE.put(1, new User(1, "Administrator", "admin@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(2, new User(2, "Guest", "guest@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(3, new User(3, "John", "John@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(4, new User(4, "Paul", "Paul@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 32 de 50 Curso JSF USERS_TABLE.put(5, new User(5, "raju", "raju@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(6, new User(6, "raghav", "raghav@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(7, new User(7, "caren", "caren@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(8, new User(8, "Mike", "Mike@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(9, new User(9, "Steve", "Steve@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(10, new User(10, "Polhman", "Polhman@gmail.com","9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(11, new User(11, "Roger", "Rogermoor@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(12, new User(12, "Robin", "Robinhood@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(13, new User(13, "Sean", "Sean@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); USERS_TABLE.put(14, new User(14, "Gabriel", "Gabriel@gmail.com", "9247469543", new Date(), "M", "Hyderabad")); USERS_TABLE.put(15, new User(15, "raman", "raman@gmail.com", "9000510456", new Date(), "M", "Hyderabad")); } public Integer create(User user) { if(user == null) { throw new RuntimeException("Não foi possível criar Usuário. Objeto é nulo"); } Integer userId = this.getMaxUserId(); user.setUserId(userId); USERS_TABLE.put(userId, user); return userId; } public void delete(User user) { if(user == null) { throw new RuntimeException( "Não foi possível excluir o Usuário. Objeto é nulo"); } USERS_TABLE.remove(user.getUserId()); } public Collection<User> getAllUsers() { return USERS_TABLE.values(); } public User getUser(Integer userId) { return USERS_TABLE.get(userId); } public Collection<User> searchUsers(String username) { String searchCriteria = (username == null)?"":username.toLowerCase().trim(); Collection<User> users = USERS_TABLE.values(); Collection<User> searchResults = new ArrayList<User>(); for (User user : users) { if (user.getUsername() != null && user.getUsername().toLowerCase().trim().startsWith(searchCriteria)) { searchResults.add(user); SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 33 de 50 Curso JSF } } return searchResults; } public void update(User user) { if(user == null || !USERS_TABLE.containsKey(user.getUserId())) { throw new RuntimeException( "Não é possível alterar o usuário. Objeto é nulo ou ID [" + user.getUserId() + "] é inválido." ); } USERS_TABLE.put(user.getUserId(), user); } protected Integer getMaxUserId() { Set<Integer> keys = USERS_TABLE.keySet(); Integer maxId = 1; for (Integer key : keys) { if(key > maxId) { maxId = key; } } return maxId; } } Criar a classe UserManagedBean.java: package x25.com.tutorial; import java.util.Collection; import javax.faces.application.FacesMessage; import javax.faces.bean.ApplicationScoped; import javax.faces.bean.ManagedBean; import javax.faces.context.FacesContext; import org.primefaces.event.SelectEvent; import org.primefaces.event.UnselectEvent; @ManagedBean @ApplicationScoped public class UserManagedBean { UserService userService = new UserService(); private String username; private String password; private String searchUser; private Collection<User> searchUsersResults; private User selectedUser; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 34 de 50 Curso JSF } public void setPassword(String password) { this.password = password; } public User getSelectedUser() { if (selectedUser == null){ selectedUser = new User(); } return selectedUser; } public void setSelectedUser(User selectedUser) { this.selectedUser = selectedUser; } public Collection<User> getSearchUsersResults() { return searchUsersResults; } public void setSearchUsersResults(Collection<User> searchUsersResults) { this.searchUsersResults = searchUsersResults; } public String getSearchUser() { return searchUser; } public void setSearchUser(String searchUser) { this.searchUser = searchUser; } public String login() { if ("test".equalsIgnoreCase(getUsername()) && "test".equals(getPassword())) { return "home"; } eles { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage("username", new FacesMessage("Usuário ou senha Inválido")); return "login"; } } public String searchUser() { String username = (this.searchUser == null)? "":this.searchUser.trim(); this.searchUsersResults = userService.searchUsers(username); System.out.println(searchUsersResults); return "home"; } public String updateUser() { userService.update(this.selectedUser); return "home"; } public void onUserSelect(SelectEvent event) { } public void onUserUnselect(UnselectEvent event) { } } Isso é tudo o que precisamos fazer. Execute o aplicativo e veja toda a funcionalidade deste aplicativo junto ao tema blusky. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 35 de 50 Curso JSF 7. Validação e Conversão JavaServer Faces suporta um mecanismo para validar os dados de componentes editáveis. Cada componente em JSF cria mensagens de erro durante o ciclo de vida e pode-se atribui- los ao objeto FacesContext. Assim, cada mensagem está ligada a um componente na árvore de componentes e a mensagem é exibida no modo de exibição no final do Ciclo de Vida da JSF conforme a seguinte figura: Obviamente que diferentes cenários poderiam impactar de forma diferente as descrições do Ciclo de Vida. Devemos observar que os processos de conversão e validação ocorrem nas fases de Aplicar os Valores de Solicitação, Validações do Processo e Retornar a Resposta. Devemos esclarecer uma questão mais básica: o que é conversão? Simplificando, é o processo que garante se o objeto é ou não do tipo certo. Aqui estão duas conversões típicas: • Valor de um tipo String é convertido para um java.util.Date. • Valor de um tipo String é convertido para um Float. Quanto à validação, garante que os dados contém o conteúdo esperado. Aqui estão duas validações típicas: SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 36 de 50 Curso JSF • java.util.Date é MM/aaaa. • Float está entre 1.0F e 100.0F. Fases do Ciclo de Vida O principal objetivo da conversão e validação é assegurar que os valores foram devidamente limpos antes de atualizar os dados do modelo. Posteriormente, quando chega a hora de invocar os métodos da aplicação para realmente realizar algo com esses dados, pode-se seguramente fazer certas suposições sobre o estado do seu modelo. Conversão e validação permite se concentrar na Regra de Negócio ao invés das qualificações tediosas de dados de entrada, tais como dados nulos, qualificadores de tamanho ou limites de alcance, etc Faz sentido, então, que os processos de conversão e validação acontecerem antes dos dados de componente vinculados ao seu modelo do BackBean no modelo de atualização de dados fase do Ciclo de Vida. A conversão ocorre na fase de aplicar valores de solicitação e validação na fase de validação do processo. Sobre o atributo imediato Notamos que os processos de conversão e validação representa o fluxo de aplicação quando o atributo imediato o componente UIInput é definido como false. Foram o atributo definido para a conversão, verdadeira e validação iria ocorrer no início do ciclo de vida, durante a fase de valores aplica-se a requisição (ver a próxima figura). Existem casos em que é útil como o gerenciamento de listas dinâmicas e até mesmo ignorando a validação por completo (quando utilizado com um componente UICommand). A próxima figura mostra onde a Conversão e Validação ocorre no Ciclo de Vida da aplicação JSFforam o atributo imediato definido como verdadeiro. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 37 de 50 Curso JSF Um exemplo de trabalho Daqui em diante vamos utilizar uma aplicação exemplo para demonstrar os conceitos discutidos. A aplicação demonstra as capacidades de conversão e validação. Tenhamos em mente que a aplicação é muito simples e não necessariamente exaustiva: Nosso objetivo não é construir um aplicativo para uso no mundo real, depois de tudo. • Uso do padrão JSF conversores para converter dados de campo de formulário; • Uso de componentes JSF padrão para validar dados de campo de formulário; • Escrever conversores e validadores personalizados; • Registrar conversores e validadores personalizados no arquivo faces-config.xml; • Personalizar mensagens de erro padrão. O aplicativo de exemplo é um simples formulário de registro do usuário. Nosso objetivo é reunir os dados do usuário como nome, idade, endereço de correio eletrônico e número de telefone. Então, vamos mostrar como utilizar a conversão e validação para garantir que os dados coletados são apropriados e corretos. A aplicação utiliza três páginas JSP: • index.jsp que redireciona o usuário para UserRegistration.jsp • UserRegistration.jsp que contém os campos da aplicação de formulários • Results.jsp que notifica o aplicativo no qual o usuário foi registrado Começaremos início com um olhar para as opções de codificação de processos de conversão do JSF. Conversão Como mencionado anteriormente, a conversão é o processo que assegura ao objeto. Podemos utilizar conversores prontos ou personalizados. JSF fornece muitos conversores padrões. Também podemos ligar nosso próprio conversor personalizado, implementar a interface e converter. A seguinte tabela mostra os identificadores do conversor e as classes de implementação correspondentes utilizados pela JSF para uma conversão de dados simples. A maioria das conversões de dados acontece automaticamente. javax.faces.BigDecimal javax.faces.convert.BigDecimalConverter javax.faces.BigInteger javax.faces.convert.BigIntegerConverter javax.faces.Boolean javax.faces.convert.BooleanConverter javax.faces.Byte javax.faces.convert.ByteConverter javax.faces.Character javax.faces.convert.CharacterConverter javax.faces.DateTime javax.faces.convert.DateTimeConverter javax.faces.Double javax.faces.convert.DoubleConverter SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 38 de 50 Curso JSF javax.faces.Float javax.faces.convert.FloatConverter Um conversor para cada ocasião O código abaixo demonstra uma conversão padrão no campo idade do usuário. A tag JSF está configurado como tal: <h:inputText id="age" value="#{UserRegistration.user.age}"/> UserRegistration.user.age representa uma propriedade de valor de ligação que é do tipo inteiro. Para as ligações de ambos os tipos primitivos, BigInteger ou BigDecimal, JSF escolhe um conversor de padrão. No entanto, também podemos usar um conversor específico para granularidade maior usando a tag <f:converter/>, conforme a codificação a seguir: <h:inputText id="age" value="#{UserRegistration.user.age}"> <f:converter id="javax.faces.Short"/> </h:inputText> Embora JSF trata primitivas e como muito bem por padrão, quando se lida com dados de data devemos especificar a tag <f:convertDateTime/>. Esta marca é baseada no pacote java.text e utiliza curto, longo, e os padrões personalizados. Aqui está um exemplo: <h:inputText id="birthDate" value="#{UserRegistration.user.birthDate}"> <f:convertDateTime pattern="MM/yyyy"/> </h:inputText> Este exemplo demonstra como usar a tag <f:convertDateTime/> para garantir que a data de nascimento do usuário é conversível em um objeto de data no formatado como “MM/AAAA” (mês/ano). Além de converter formatos de data e hora, JSF fornece um conversor especial para lidar com números como porcentagens ou moeda. Este conversor lida com o agrupamento (como vírgula), número de dígitos decimais, símbolos de moeda, entre outros. Por exemplo, o uso de <f:convertNumber/> seguinte é uma técnica para lidar com moeda: <h:inputText id="salary" value="#{UserRegistration.user.salary}"> <f:convertNumber maxFractionDigits="2" groupingUsed="true" currencySymbol="$" maxIntegerDigits="7" type="currency"/> </h:inputText> Conversores Personalizados Conversão de dados personalizado é necessário se você precisa converter os dados de campo em um objeto de valor específico do aplicativo, como nos exemplos a seguir: • String para o objeto Telefone (Telefone.ddd, Telefone.numero) • String para o objeto Nome (Nome.principal, Nome.apelido) • String para o objeto Produto (Produto.numero, Produto.revisao) Para criar um conversor personalizado, você deve fazer o seguinte: • Implementar a interface Converter (javax.faces.convert.Converter) SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 39 de 50 Curso JSF • Implementar o método getAsObject, que converte um campo (String) em um objeto (por exemplo, Telefone). • Implementar o método getAsString, que converte um objeto (por exemplo Telefone) em uma String. • Cadastrar seu conversor personalizado no contexto Faces. • Insirir o conversor em sua JSP com a tag <f:converter/>. Veja por si mesmo como essas etapas se encaixam no ciclo de aplicação JSF. JSF chama o método getAsObject do conversor personalizado durante a fase de aplicar valores pedido. Este é o lugar onde o conversor deve converter o valor String da requisição para o tipo de objeto desejado, e então retornar o objeto para o armazenamento no componente JSF correspondente. Quando o valor for processado de volta para o ponto de vista, JSF chama o método getAsString na fase da renderização da resposta. Isto significa que o conversor é também responsável pela transformação dos dados de objetos de volta para uma representação de sequência. Passo 1: Implementar a interface Converter. import javax.faces.convert.Converter; import org.apache.commons.lang.StringUtils; ... public class TelefoneConverter implements Converter { ... } Passo 2: Implementar o método getAsObject que converte uma String para um objeto da classe Telefone. public class TelefoneConverter implements Converter { ... public Object getAsObject( FacesContext context, UIComponent component, String valor) { if (StringUtils.isEmpty(valor)) { return null; } Telefone fone = new Telefone(); String [] foneComps = StringUtils.split(value," ,()-"); String codPais = foneComps[0]; fone.setCodPais(codPais); if ("1".equals(codPais)) { String ddd = foneComps[1]; String prefixo = foneComps[2]; String numero = foneComps[3]; fone.setDDD(ddd); fone.setPrefixo(prefixo); fone.setNumero(numero); } else { SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 40 de 50 Curso JSF phone.setNumero(valor); } return fone; } } Passo 3: Implementar o método getAsString que converte a classe Telefone para uma String. public class TelefoneConverter implements Converter { ... public String getAsString(FacesContext context, UIComponent component, Object value) { return value.toString(); } } public class Telefone implements Serializable { ... public String toString(){ if (countryCode.equals("1")){ return codPais + " " + ddd + " " + prefixo + " " + numero; } eles { return numero;} } } Passo 4: Registrar o conversor personalizado com o contexto. Isso pode ser executado em uma das seguintes maneiras. A primeira opção é registrar a classe TelefoneConverter com o ID de (por exemplo) x25.TelefoneConverter. Este ID será então utilizado pela tag <f:converter/> em suas páginas JSP. <converter> <converter-id>arcmind.TelefoneConverter</converter-id> <converter-class>x25.com.tutorial.TelefoneConverter</converter-class> </converter> Alternativamente, pode-se registrar a classe TelefoneConverter para lidar com todos os objetos Telefone automaticamente, como mostrado a seguir. <converter> <converter-for-class>x25.com.tutorial.Telefone</converter-for-class> <converter-class>x25.com.tutorial.TelefoneConverter</converter-class> </converter> Passo 5: Usa o conversor em seus JSPs. A execução do seguinte passo depende da opção de qual registo foi escolhido. Ao optar por registrar a classe TelefoneConverter com o ID de x25.TelefoneConverter, então utiliza-se a tag <f:converter/> como mostrado abaixo. <h:inputText id="telefone" value="#{RegistroUsuario.usuario.telefone}"> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 41 de 50 Curso JSF <f:converter converterId="x25.TelefoneConverter" /> </h:inputText> Se optar por registrar a classe TelefoneConverter para lidar com todos os objetos Telefone automaticamente, então não será necessário usar a tag <f:converter/> em seus JSPs. Aqui está o código para o Passo 5, sem a tag conversor. <h:inputText id="phone" value="#{RegistroUsuario.usuario.telefone}"> [ Veja só sem conversor !] </h:inputText> Validação Existe quatro formas de validação dentro JSF: • Componentes Built-in de validação • Validação em nível de aplicativo • Componentes personalizados de validação (que implemente a interface Validator) • Métodos de validação através de BackBeans Validação e o Ciclo de Vida da JSF e seus componentes Vejamos um estudo de caso do Ciclo de Vida para o campo nome do nosso formulário de cadastro. As referências de código são destinas a ser interpretadas como um pseudocódigo. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 42 de 50 Curso JSF Aqui está uma lista dos componentes de validação padrão fornecidos pelo JSF: • DoubleRangeValidator: valor local de componentes deve ser do tipo numérico, e estar em um intervalo especificado pelos valores mínimos e/ou máximo. • LongRangeValidator: valor local de componentes deve ser do tipo numérico e conversível para o tipo long; deve estar no intervalo especificado pelos valores mínimos e/ou máximo. • LengthValidator: Tipo deve ser String; o tamanho deve estar no intervalo especificado pelos valores mínimos e/ou máximo. Padrão de Validação Em nosso aplicativo exemplo a idade do usuário pode ser de qualquer tipo inteiro válido (byte, short, int). Porque não faz sentido permitir que uma idade de, digamos, -2, vamos adicionar uma validação para o campo. Este é um código de validação simples para garantir a integridade do modelo de dados para o campo idade: <h:inputText id="idade" value="#{RegistroUsuario.usuario.idade}"> <f:validateLongRange maximum="150" minimum="0"/> </h:inputText> Podemos especificar restrições quanto ao comprimento do campo nome. Podemos realizar isso da seguinte forma: <h:inputText id="nome" value="#{RegistroUsuario.usuario.nome}"> <f:validateLength minimum="2" maximum="25" /> </h:inputText> A estratégia de Conversão e Validação permite que facilmente e rapidamente começar (conversores padrão, validação, validação in-line) durante a fase de prototipação, e migrar para soluções de produção mais sofisticadas (objetos personalizados, mensagens personalizadas) durante as fases de desenvolvimento posterior. Ao longo de tudo isso, ciclo de vida da aplicação JSF fornece uma infraestrutura confiável para garantir a integridade do modelo de dados. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 43 de 50 Curso JSF 8. JSF e Spring Antes de entrar em detalhes como é realizada a Integração Spring-JSF, é importante conhecer um pouco dos detalhes básicos. Lado Spring Spring é um framework que suporta de Inversão de Controle (IoC). IoC permite separar vários componentes que se encaixam em um aplicativo. Na terminologia do Spring isto é um Spring Bean que são nada mais que classes regulares java. É possível externalizar o estado dos objetos do Bean, especificando-os no arquivo padrão XML. Um Spring Bean tem um ciclo de vida que passa por várias fases. IoC do Spring é responsável por ler o arquivo XML e construir o Spring Beans a partir da informação de meta-dados diferentes. Assim, a principal responsabilidade da IoC é fazer com que os Spring Beans disponível para o aplicativo cliente. E no núcleo do IoC fornecer uma ligação entre Spring Beans. Assim, em vez de códificar o aplicativo manualmente gerenciamos o relacionamento entre os Beans, sendo que o problema e manter este. Vejamos o seguinte Bean exemplo: <bean id="pessoaBean" class="x25.com.tutorial.Pessoa"> <property name="nome"> <value>Anônimo</value> </property> </bean> O exemplo acima define um Spring Bean do tipo Pessoa com um identificador chamado pessoaBean. Também define uma propriedade simples chamada nome com valor anônimo. Também é possível relacionar valores compostos (como referências a outro objeto) ou conjuntos de valores (array, mapa, lista) como o seguinte trecho de código irá mostrar: <bean id="funcionario1" class="x25.com.tutorial.Funcionario"> <property name="nome"> <value>Func1</value> </property> </bean> <bean id="funcionario2" class="x25.com.tutorial.Funcionario"> <property name="nome"> <value>Func2</value> </property> </bean> <bean id="gerente1" class="x25.com.tutorial.Gerente"> <property name="nome"> <value>Gerente1</value> </property> <property name="funcionarios"> <ref bean="funcionario1"/> <ref bean="funcionario2"/> </property> </bean> Observamos no exemplo acima, a declaração de dois objetos Funcionário com os SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 44 de 50 Curso JSF identificadores funcionario1 e funcionario2. Esses dois objetos de funcionário estarão associados com um objeto de Gerente. Este é um exemplo de uma relação composta, uma vez que estamos relacionando Gerente com Funcionário. Isto é conseguido através da tag de referência dentro da declaração de propriedade. Lado Java Server Faces Depois de ter visto sobre como IoC do Spring gerencia e mantém os Spring Beans, vamos ver uma visão geral sobre a gestão da Java Server Faces sobre seus componentes. JSF é responsável por fornecer um componente de desenvolvimento orientado para a camada de interface do usuário em uma aplicação Web. A pedido do cliente é mapeada diretamente para uma ação na camada Web, o que significa que o mecanismo de manipulação de eventos se assemelha ao que vemos nas bibliotecas SWING ou AWT. Se o mecanismo de manipulação de eventos da SWING é para aplicações desktop, em seguida, a arquitetura JSF orientada evento é para aplicações Web. Semelhante aos Spring Beans, em JSF temos é chamado de Managed Beans ou BackBeans. Estes beans são responsáveis pela manipulação de todos os tipos de ações em uma aplicação Web. Como um componente da interface do usuário associado a uma determinada ação e facilmente configurável no arquivoXML. O código a seguir mostra a declaração de um Managed Bean da JSF. <managed-bean> <managed-bean-name>timerBean</managed-bean-name> <managed-bean-class> x25.com.tutorial.TimerBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> Um Managed Bean é também uma classe Java regular em JSF e está configurado no arquivo faces-config.xml e disponibilizado para o aplicativo pela JSF. Spring Beans no ambiente JSF Agora que vimos os beans na visão do Spring e da JSF, vamos ver sobre Integração e qual o componente fica integrado. Spring utiliza Spring Beans e JSF os Managed Beans. Spring fornece suporte, de tal modo que um Spring Bean torna-se visível para o ambiente JSF. Precisamente, o Spring Bean que configuramos no arquivo XML pode ser visto diretamente no faces-config.xml como se fosse um bean gerenciado pela JSF. <bean id="pessoaBean" class="x25.com.tutorial.Pessoa"> <property name="nome"> <value>Anônimo</value> </property> </bean> O código acima define um Spring Bean. Agora, consideremos o seguinte trecho: <managed-bean> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 45 de 50 Curso JSF <managed-bean-name>pessoaBean</managed-bean-name> <managed-bean-class> x25.com.tutorial.Pessoa </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> Utilizamos o Spring Bean de Pessoa que foi previamente determinado na configuração do Spring para a JSF. Apoio da API para a integração Retornando o foco para a API da Distribuição do Spring que estão relacionados com JSF para o apoio à integração. A API do Spring contém diversas classes de suporte para a Integração de JSF e estão disponíveis nos pacotes: • org.springframework.web.jsf • org.springframework.web.jsf.el Para realizar a integração, precisamos conhecer sobre os Spring Resolvers. No contexto JSF, resolver um processo de identificação de um objeto através de um determinado símbolo. Mais especificamente, um identificador do framework JSF constrói e associa o objeto do identificador. Vamos retornar à declaração do Managed Beans, <managed-bean> <managed-bean-name>timerBean</managed-bean-name> <managed-bean-class> x25.com.tutorial.TimerBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> Na declaração acima, temos um identificador (ou variável) chamado timerBean. O objetivo da implementação de um JSF Resolver que deve associar um objeto do tipo x25.com.tutorial.TimerBean para timerBean. Vejamos o que acontece quando tentamos identificar uma variável que não é gerida pelo contexto da aplicação JSF, mas no contexto de uma aplicação Spring. A implementação JSF simplesmente lança um erro informando que a variável não pode ser resolvida. Não importa se a implementação JSF conhece ou não sobre os Beans que são mantidos no Contexto da aplicação Spring. Assim, a fim de resolver as variáveis no contexto da aplicação Spring, temos que substituir a implementação JSF para resolver a implementação do Spring Resolver. A implementação do Spring tenta resolver as variáveis do contexto do aplicativo. Em vez de definir um Resolver personalizado, a distribuição do Spring vem com um Resolver variável pré- definido denominado "org.springframework.web.jsf.DelegatingVariableResolver". SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 46 de 50 Curso JSF 9. JSF e Seam 2 Seam é um framework de aplicação para Enterprise Java. Define um modelo de componente uniforme para toda a lógica de negócios em sua aplicação. Um componente Seam pode ser stateful, com o estado associado a qualquer um dos vários contextos bem definidos, incluindo o de longa duração, persistente contexto de processo, as empresas e ao contexto de conversação, que é preservado através de múltiplas solicitações Web em uma interação do usuário. Não há distinção entre os componentes ou camadas de apresentação e componentes de lógica de negócios no Seam. Pode-se colocar a camada em seu aplicativo da forma como a arquitetura foi concebida, ao invés de ser forçado a encaixar a arquitetura no framework. Ao contrário de uma simples plataforma Java EE ou componentes Java EE. Os componentes do Seam podem acessar simultaneamente o estado associado com a solicitação da Web, realizada em recursos transacionais (sem a necessidade de propagar o estado do pedido via web manualmente parâmetros do método). Integração com JSF com EJB 3.0 JSF e EJB 3.0 são dois dos novos recursos do Java EE. EJB3 é um novo modelo de componentes para o negócio do lado do servidor e pela lógica de persistência. Enquanto isso, JSF é um grande modelo de componente para a camada de apresentação. Infelizmente, nem o modelo de componente é capaz de resolver todos os problemas em computação, por si só. Na verdade, JSF e EJB3 funcionam melhor utilizados em conjunto. Mas a especificação Java EE não fornece uma maneira padrão para integrar os dois modelos de componentes. Felizmente, os criadores de ambos os modelos previram esta situação e desde os pontos de extensão padrão para permitir a extensão e integração com outros frameworks. Seam unifica os modelos de componentes de JSF e EJB3, eliminando código de junção, e permite que o desenvolvedor pense sobre as Regras do Negócio. É possível escrever aplicações Seam, onde "tudo" é um EJB. Isto pode ser surpresa se está acostumado a pensar em EJBs como granulação, os chamados objetos "pesados". No entanto, versão 3.0 mudou completamente a natureza dos EJBs a partir do ponto de vista do provedor. Um EJB é um objeto de granulação fina, não sendo mais complexo do que uma anotação em um JavaBean. Seam incentiva a uso dos Session Beans com o uso da ação da JSF. Integração com AJAX Seam suporta o melhor fonte aberto baseado em soluções AJAX: JBoss RichFaces e ICEfaces. Estas soluções permitem adicionar a capacidade AJAX para a interface do usuário sem a necessidade de escrever qualquer código JavaScript. Alternativamente, Seam fornece um camada de construção remota JavaScript que permite SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 47 de 50 Curso JSF chamar componentes de forma assíncrona do lado cliente, JavaScript, sem a necessidade de uma camada de ação intermediária. Bijeção A noção de Inversão de Controle ou IoC existe tanto na JSF quanto na EJB3, bem como em numerosos chamados "recipientes leves". A maioria destes recipientes enfatizam a IoC que implementem serviços. Mesmo quando a IoC suporta o tipo statefull (tal como no JSF), é praticamente inútil o tratamento do estado da aplicação porque o âmbito da aplicação do componente statefull não pode ser definido com flexibilidade suficiente, e porque os componentes pertencentes aos âmbitos mais amplos não pode ser injetado em componentes pertencentes a âmbitos mais estreitos. Bijeção difere de IoC por ser mais dinâmico, contextual e bidirecional. Pode-se pensar nisso como um mecanismo de variáveis contextuais (nomes nos vários contextos ligados ao segmento atual) para os atributos do componente. Bijeção permite a automontagem de componentes statefull pelo contêiner. Permite um componente de forma segura e manipula facilmente o valor de uma variável de contexto, apenas atribuindo-o a um componente. Seam funciona em qualquer servidor de aplicação Java EE, inclusive no Tomcat. Se o seu ambiente suporta ou não a EJB 3.0 é possível usar ogerenciamento de transação do Seam com JPA ou Hibernate3 para persistência. Ou, implantar o JBoss incorporado no Tomcat, e obter suporte total para a EJB 3.0. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 48 de 50 Curso JSF 10. Formulário Master/Detail Em Componentes de Negócios, um relacionamento master-detail refere-se a duas instâncias de exibição de um objeto que são relacionados por um link de visualização. Um link de visualização representa uma relação entre dois ou mais objetos, que normalmente é, mas não necessariamente, com base em uma chave estrangeira que liga as tabelas de dados subjacentes. Os links de associação criam uma única linha de instância do objeto de exibição (o objeto principal) com uma ou mais linhas de outra instância do objeto de exibição (o objeto detalhe). Por exemplo: Nota Fiscal e Itens da Nota, Funcionário e Dependentes, Ordem de Pagamento e Itens de Pagamento. Vejamos como configurar um relacionamento entre Departamento que está relacionado com as Avaliações de um Grupo escrita por Funcionários. DepartmentForm.jsp <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:q="http://www.qualcomm.com/cas" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="template.jsp"> <ui:define name="title">Formulário de Departmento</ui:define> <ui:define name="content"> <h:form id="departmentForm"> <h:panelGrid id="panelGrid" columns="3" cellpadding="4" cellspacing="0" styleClass="formPanelGrid" rowClasses="#{rowClasses}"> <q:fields fieldNames="name" entity="#{DepartmentCRUD.entity}"/> </h:panelGrid> Funcionários<br /> <q:genericSubForm listing="#{DepartmentCRUD.entity.employees}" listingFieldNames="lastName,phone" linkFieldName="firstName" subForm="#{DepartmentCRUD.subForms.employeeSubForm}"> </q:genericSubForm> <br /> Avaliações do Grupo<br /> <q:genericSubForm listing="#{DepartmentCRUD.entity.assessmentList}" listingFieldNames="rating" linkFieldName="groupName" linkFieldNotEditable="true" subForm="#{DepartmentCRUD.subForms.assessmentSubForm}"> <q:dropdown fieldName="group" entity="#{subForm.entity}" /> </q:genericSubForm> <br /> <q:addUpdate crud="#{DepartmentCRUD}"/> SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 49 de 50 Curso JSF </h:form> </ui:define> </ui:composition> </html> Observe as duas tags genericSubForm que realizam as tarefas de incluir, atualizar e consultar dentro do DepartmentForm.jsp para Funcionário e Avaliações. SGAS 910, B loco D, sa las, 237 a 243, Mix Park Sul – Asa Sul , Bras í l ia /DF CEP: 70.390-100 – Fone/Fax: (61) 3244-2510 – 3242-4339 50 de 50 1. JavaServer Faces Características da JSF 2. Ajax com JSF Enviar uma solicitação do Ajax Renderizar a visão parcial Processar a visão parcial Outro Exemplo 3. Navegação Navegação estática e dinâmica Navegação Estática Navegação Dinâmica Outros detalhes Especificar wild-cards 4. Facelets Por que usar Facelets? JSF 2 Templating com exemplo Facelets 1. Layout do modelo 2. Cabeçalho, Conteúdo e Rodapé 3. Utilizando template 5. Richfaces Baixar os RichFaces Adicionar as bibliotecas RichFaces para o projeto Registrar o RichFaces no web.xml managed bean Demonstração dos Componentes 6. Primefaces Características do PrimeFaces Aplicativo Exemplo 7. Validação e Conversão Fases do Ciclo de Vida Sobre o atributo imediato Um exemplo de trabalho Conversão Um conversor para cada ocasião Conversores Personalizados Validação Validação e o Ciclo de Vida da JSF e seus componentes Padrão de Validação 8. JSF e Spring Lado Spring Lado Java Server Faces Spring Beans no ambiente JSF Apoio da API para a integração 9. JSF e Seam 2 Integração com JSF com EJB 3.0 Integração com AJAX 10. Formulário Master/Detail