JSF é um framework que foi criado para o desenvolvimento web de forma ágil. Anteriomente ao JSF o desenvolvimento WEB seguia o modelo de desenvolvimento de SERVLET, com isto o forma de programação tornava-se totalmente diferente de aplicações Desktop. O modelo de programação do JSF visa abstrair as questões referentes a programação WEB, facilitando o desenvolvimento e fazendo com que o desenvolvedor mantenha o foco na codificação das regras da aplicação. Além disto a complexidade das interfaces gráficas com o usuário, que tem se tornado cada vez mais complexas, faz com que se torne necessário prover o dinamismo das aplicações Desktop para as aplicações Web, o que não é facil utilizando somente HTML, já o JSF cria abstrações que tornam o desenvolvimento de aplicações ricas muito mais fácil.
Ciclo de Vida
Como foi dito, JSF trabalha de abstraindo a questão do protocolo HTTP. Todo o mapeamento de campos HTML para os objetos Java é feito de forma transparente, assim como os eventos de botão e suas ações e as validações de campo. Para que isto aconteça existe todo um ciclo de vida de uma requisição feita por JSF. O desenvolvedor não é obrigatório a conhecer profundamente o funcionamento interno do JSF, mas é um diferencial muito importante, ter um conhecimento sobre o ciclo de vida, sabendo a ordem de execução e o que acontece em cada uma destas fases. Este conhecimento permite que sejam construídas aplicações melhores, pois o desenvolvedor sabe com detalhes que operações estão acontecendo em cada fase, tornando mais fácil, inclusive, detectar um erro ao se identificar em qual fase ele ocorreu. A figura a seguir apresenta o ciclo de vida do JSF, logo a seguir temos a explicação de cada fase.
Restore View (Restaurar Visão)
No JSF a view representa uma árvore com todos os componentes de uma página e a principal função da fase Restore View é inicializar o ciclo de vida de processamento da requisição, tentando obter a informação de estado para construir a árvore de componentes que representa a requisição. Uma requisição chega através do controlador FacesServlet, que examina e extrai o ID da view. Com este ID é feita um busca, na sessão do usuário, pela view e caso não seja encontrada, é criada uma. Caso seja a primeira vez que o usuário faz a requisição da página, não existirão dados submetidos pelo usuário, então o JSF vai pular as próximas fases, indo direto para a Render Response que é a ultima fase. Caso não seja a primeira requisição da página, o JSF aplicará na view os dados informados pelo usuário e seguirá para a próxima fase, Apply Request Values. Apply Request Values (Aplicar Valores do Request)
Nesta fase o valor local de cada componente é atualizado pela requisição atual. Os componentes precisam ser restaurados ou criados e seus valores são recuperados, na maioria das vezes através dos parâmetros da requisição, mas também podem ser recuperados de cookies, cabeçalhos e da sessão HTTP. Outra função desta fase é fazer a conversão de dados, de modo que os valores passados na requisição, sejam convertidos em seu tipo esperado. Nesta fase atuam os conversores, que são responsáveis por este trabalho e caso ocorra um erro é criada uma mensagem que é colocada na fila de mensagens para ser mostrada ao usuário na fase Render Response. Esta fase pode se comportar de maneira um pouco diferente se a propriedade immediate estiver com o valor 'true'; neste caso, além da conversão dos dados é assumida a tarefa de validação dos dados que é de responsabilidade da fase Process validation. Caso ocorra um erro na conversão ou validação, também é gerada e enfileirada uma mensagem na fila de mensagens. Process Validation (Processar Validações)
Nesta fase, a árvore de componentes é percorrida e é feito um teste para saber se o valor é aceitável. A responsabilidade de validação pode ser atribuída ao próprio componente, ou a um ou mais validadores registrados. Caso todos os componentes sejam validados com sucesso, o processo avança para fase update model, mas caso um ou mais componentes possuam valores inválidos, é gerada uma mensagem de erro para cada componente e o JSF pula para a fase render response que mostrará a view atual com todas as mensagens de erro.
Update Model Values (Atualizar Valores do Model)
Aqui são atualizadas as propriedades, dos Managed Beans, que possuem ligação com algum componente. Como esta fase só é alcançada caso não ocorra nenhum erro de validação ou conversão, pode-se assegurar que os valores que serão atualizado estão válidos. Vale ressaltar que mesmo os valores estando válidos com as regras de conversão e validação, nada impede que eles estejam inválidos para alguma regra de negócio da aplicação. Um exemplo prático é uma validação de CPF, que pode comumente usar um algorítimo para checar se o número informado é um numero de CPF no formato válido, mas para nossa regra de negócio pode não bastar o número possuir um formato válido, sendo obrigatório que este número represente um CPF existente. Invoke Application (Invocar Aplicação)
Ao chegar nesta fase temos a certeza que nossos dados foram convertidos, validados e usados para atualizar os Managed Beans, então é agora que o JSF executa as lógicas de negócio da aplicação. Os eventos de ação padrão de cada componente e os que foram restaurados na primeira fase, serão agora enviados aos ouvintes de ação correspondentes. Primeiro serão executados os eventos de ação recuperados na fase restore view, depois o JSF executará os eventos padrão e depois que tudo isso é feito, a requisição segue para a próxima fase. Render Response (Renderizar Resposta)
Chegamos na última fase do ciclo de vida da requisição sabendo que todo o processamento de nossa requisição foi feito, faltando apenas mostrar o resultado ao usuário. Mostrar o resultado ao usuário é a principal função desta fase, mas ela também grava o estado da view, para que ela possa ser recuperada na fase restore view caso seja necessário. Podemos ressaltar que nesta fase os conversores precisam trabalhar de maneira inversa ao que ocorre na fase apply request values. Aqui os dados são convertidos em String, utilizando uma formatação que o usuário entenda.
Conceitos e componentes
Como a maioria das tecnologias, o JSF possui um conjunto próprio de termos, que formam a base conceitual para os recursos que proporciona. São muitos termos como componentes de interfaces (UI), validores, renderizadores, Managed Beans, entre outros, que serão encontrados por quem começar a desenvolver utilizando JSF. Antes de nos aprofundarmos em cada peça deste quebra cabeça, podemos ter uma idéia geral da função de cada um nos próximos tópicos. Componentes UI Um objeto sem estado de conversação associado, mantido no servidor, que fornece uma funcionalidade específica para interagir com um usuário final. Componentes UI são JavaBeans com propriedades, métodos e eventos. Elas são organizadas em uma estrutura, que é uma árvore de componentes geralmente apresentados como uma página. Renderizadores Responsável por exibir um componente da UI e transformar uma entrada do usuário em um valor do componente. Renderizadores podem ser projetados para funcionar com um ou mais componentes UI, um componente UI pode ser associado a diversos renderizadores. Managed Beans Uma especialização do JavaBeans que coleta valores a partir de componentes da UI e implementam métodos dos eventos dos ouvintes. Eles também podem possuir referências a elementos da UI. Navegação A capacidade de passar de uma página para a próxima. JSF possui um poderoso sistema de navegação que é integrado com os ouvintes dos eventos. Validadores Responsável por garantir que o valor digitado por um usuário é aceitável. Um ou mais validadores podem ser associados com um componente da UI. Mensagens Informações que são exibidas de volta para o usuário. Em qualquer parte da requisição (Managed Beans, validadores, conversores, e assim por diante) mensagens de erro podem ser geradas ou podem ser exibidas informações para o usuário. Conversores Converte o valor de um componente para String e também executa a operação reversa. Um componente UI pode ser associado com apenas um conversor. Eventos e Listeners JSF usa o modelo JavaBean de evento/listener(também usado pelo Swing). Componentes UI (e outros objetos) geram eventos e listeners podem ser registrados para lidar com esses eventos.
Primeiro Projeto
Para começar a programar em JSF vamos criar um projeto Hello World. Um projeto JSF é basicamente um projeto Web padrão com as devidas libs do framework. Além disto é necessário configurar o web.xml para receber requisições JSF e configurar um descritor do JSF (facesconfig.xml) Para facilitar o desenvolvimento utilizaremos o Eclipe (atualmente versão Helios), pois esta IDE possui muitos facilitadores para a criação de JSF. Também utilizaremos o plugin do Eclipse Jboss Tools, este possui ferramentas que agilizam muito o desenvolvimento, como por exemplo a paleta de componentes Rich e os templates de arquivos .xhtml. Como servidor utilizaremos o Tomcat 7. Após baixar e descompactar o Eclipse, vamos criar um projeto novo. Este deve ser um Dynamic Web Project como mostra a figura abaixo:
A proxima tela pergunta sobre os caminhos do projeto, mantenha como está e click next. Logo aparece a tela de configuração do contexto WEB, mantenha como está e clique next. A tela que aparece neste momento nos permite buscar as libs de implementação do JSF. Utilizaremos o projeto MOJARRA. É possivel baixar as libs diretamente desta tela, clicando no botão do disquete, no lado direito desta tela.
Feito isto é só clicar em finish e o projeto estará criado.
Com isto teremos um projeto com a seguinte estrutura:
Nesta estrutura temos o web.xml com a configuração do JSF e o arquivo descritor do JSF (faces-config.xml). Nossos arquivos xhtml ficarão no diretório WebContent, e serão processados pelo JSF. Agora vamos dar uma olhada nos arquivos criados e entender como funcionam.
web.xml
O web.xml irá conter a informação do servlet JSF e as configurações de mapping Hello WorldFaces Servletjavax.faces.webapp.FacesServlet 1Faces Servlet*.jsfState saving method: 'client' or 'server' (=default). javax.faces.STATE_SAVING_METHOD clientjavax.servlet.jsp.jstl.fmt.localizationContext resources.application com.sun.faces.config.ConfigureListener
faces-config.xml
O Faces-config contém as informações de mapeamento do JSF, neste arquivo serão configurados os Managed Beans (JSF 2 permite fazer está configuração por Annotation), as regras de navegação, os conversores e validadores customizados assim como os phase listeners. Entraremos em detalhes sobre cada configuração mais adiante. No momento vamos apenas visualizar a estrutura básica do arquivo.
Página de welcome page
Na configuração da aplicação web é informado quais são os arquivos de welcome. Isto indica qual arquivo deve ser carregado quando chamarmos a aplicação não indicando caminho. Por exemplo quando chamarmos http://www.minha-aplicacao.com.br/. Infelizmente no JSF não podemos fazer uma chamada direta a um arquivo html o jsp. Ao invés disto devemos fazer uma chamada ao mapping definido no web.xml. Para resolver este problema é possível criar um arquivo html que irá redirecionar para o JSF, fazendo com que o JSF processe a requisição e seguindo o clico de vida. Abaixo segue o documento html que podemos criar para evitar este problema, ele se chamará index.html e ficará no diretório WebContent da aplicação: <meta http-equiv="Refresh" content= "0; URL=helloworld.jsf"/> Iniciando Aplicação
Por Favor, aguarde enquanto a aplicação é iniciada.
Por fim podemos criar o arquivo xhtml, que receberá a requisição e montará a página. Um arquivo xhtml segue um padrão para importação de taglibs e é muito semelhante a jsp, com apenas algumas diferenças. Poderia ser utilizada a notação de JSP, entretanto xhtml é mais atualizado e para facelets é necessário o uso desta formatação. A caixa abaixo mostra o exemplo de arquivo xhtml, neste caso helloworld.xhtml. A unica coisa que esta página faz é escrever Hello World na tela.
Navegação
Agora digamos que seja necessário adicionar um link nesta pagina para outra página, isto é feito com regras de navegação, antes do JSF 2, era necessário adicionar uma regra dentro do facesconfig.xml. com o JSF 2, foi criada a facilidade de regra de navegação implicita, onde o nome da regra sendo o mesmo do arquivo .xhtml, não há necessidade de declaração. O exemplo abaixo mostra como seria a declaração de regra de navegação (está ainda é valida no JSF 2.0 e pode ser utilizada em casos que se necessita de uma regra mais complexa do que a navegação implícita) /helloworld.xhtmlproximo/cadastro.xhtml
Declaração de regras de navegação no faces-config.xml
logo o arquivo .xhtml com o link ficaria assim (cabe lembrar que sempre é necessário ter um form para adicionar um link ou button de navegação):
"http://www.w3.org/TR/
Já no JSF 2 podemos fazer uso na navegação implícita, neste caso não colocaríamos nenhuma configuração no faces-config.xml. E no .xhtml apontaríamos o action para o nome do .xhtml sem a extensão, conforme mostrado abaixo:
"http://www.w3.org/TR/
Mapeamento Form para Java
O próximo passo é fazer com que os valores do formulário sejam mapeados em objetos Java. Para isto temos os chamados Managed Beans. Um managed bean nada mais é do que uma classe java com attributos e seus respectivos getters/setter. Além de métodos actions chamados nos cliques de botão ou outras ações disparadas pela tela. Para indicar que uma classe java é um managed bean existem duas formas. A primeira forma é mapeando esta classe no faces-config.xml, esta forma era a maneira de se fazer até o JSF 1.2. A segunda maneira é utilizando annotations, está forma foi adicionada na versão 2 do JSF e facilita muito no reconhecimento das classes. Ambas as formas podem ser utilizadas no JSF 2, já anotações não podem ser utilizadas em JSF 1.2. A seguir serão apresentadas as duas formas. usuariocom.diehl.teste.bean.UsuarioBean request
Mapeamento no arquivo faces-config.xml @ManagedBean(name="usuario") @RequestScoped
public class UsuarioBean { private String nome; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; }
}
Mapeamento por anotações Tendo definido o managed bean, precisamos verificar como "linkar" os campos do formulário com os atributos da classe Java. Isto é feito utilizando uma anotação específica do JSF: ● #{bean.nome} ● #{bean[nome]} Ambas as sintaxes são válidas e serão melhor detalhadas a frente. O arquivo cadastro.xhtml com o formulário ficará desta forma então:
"http://www.w3.org/TR/
Digite seu nome:
Como no command button estamos apontando para um action chamado sucesso, precisamos criar este arquivo. Neste apenas mostraremos o valor que foi digitado pelo usuário na página anterior. Bem-vindo
Navegações condicionais
Até agora vimos navegações estáticas, sempre apontando para um determinado xhtml. Também é possível chamar métodos de dentro do managed bean usando o atributo de um commandButton ou commandLink. Estes métodos apenas não devem receber nenhum parâmetro e devem retornar um String ou void. A string que ele deve retornar é o nome da regra de navegação que deve ser redirecionada. Caso a String seja nula ou uma regra inexistente, o sistema voltará para o mesmo xhtml que
requisitou a página, da mesma forma isto ocorrerá se tivermos retorno void. Vamos supor então que precisamos decidir qual página mostrar de acordo com o que o usuário digitou na pagina cadastro.xhtml. Para fazer isto criaremos um novo método no UsuárioBean, este será chamado de avancar, conforme mostrado abaixo. public String avancar() { if ("invalido".equalsIgnoreCase( nome)) { return "falha"; } else { return "sucesso"; } }
Com isto estamos decidindo que se o usuário digitar invalido no campo, mostraremos uma pagina de falha, caso contrário mostraremos a de sucesso. No cadastro.xhtml precisamos mudar o action do commandButton para #{usuario.avancar}.
Também precisamos criar um xhtml de falha (falha.xhtml).
"http://www.w3.org/TR/
não é um valor válido
Exercicios 1. Implementar uma página para simulação de cadastro de Alunos, com os seguintes dados: ● Nome; ● Sobrenome; ● Data de nascimento (campo textual para ser convertido posteriomente para Date
utilizando DateFormat) ● Endereço; ● Telefone; Teremos duas telas, uma chamada cadastro.xhtml e outra resposta.xhtml. Na tela resposta.xhtml devemos informar uma mensagem de sucesso, informar o nome completo do aluno, sua idade, endereço e telefone. 2. Sem consultar a apostila tente desenhar o fluxo do ciclo de vida do JSF; 3. Descreva cada fase do ciclo de vida do JSF e suas principais características
Managed Beans
Objetivos ●
Mostrar a importância de um Java Bean ao JSF
●
Mostrar como registrar um Bean no JSF
●
Ver como ligar as propriedades de um Bean nas Tags JSF
●
Mostrar o que são os Backing Beans
●
Ver em que tipo de escopo podemos registrar um Bean no JSF
●
Mostrar os tipos de expressões de ligação de valor
●
Ver como funciona a comunicação entre Beans
Entendendo a importância de JavaBean no JSF
O principal tema referente ao design de aplicações web é a separação entre a apresentação e a lógica de negócios. O JSF utiliza os beans para realizar essa separação. As páginas JSF fazem referência às propriedades dos beans e a lógica de programação fica contida no código de implementação do bean. De acordo com a especificação Java Beans, um Java Bean é um “componente de software reutilizável que pode ser manipulado por uma ferramenta de construção”. À primeira vista, um bean parece ser um objeto. Entretanto, os beans servem a um propósito diferente. Os objetos são criados e manipulados dentro de um programa Java quando o software chama construtores e invoca métodos. Entretanto os beans podem se configurados e manipulados sem programação. No contexto do Java Server Faces, beans são muito mais do que componentes de interface do usuário. Utiliza-se os beans sempre que é preciso conectar classes Java com páginas web. Como vimos no capitulo anterior ao anotarmos uma classe como @ManagedBean, estamos indicando ao JSF que deve ser criado um objeto desta classe e que deve estar disponivel para acesso pelos componentes JSF. Nas aplicações JSF os bean são normalmente usados para: ● Componentes da interface do usuário; ●
●
Definir o comportamento de um formulário web, acesso a serviços externos como banco de dados (os chamados backing beans); Objetos de negócio cujas propriedades são exibidas nas páginas web;
Propriedades de um Bean
Um bean deve seguir algumas convenções especificas definidas, para expor a camada de apresentação (.xhtml) seus atributos. O padrão a ser seguido é o seguinte: ● A classe sempre dever ter um contrutor padrão, ou seja, um contrutor sem parâmetros. Isto é necessário pois quem instância um Managed Bean é sempre o JSF. os atributos que forem expostos devem conter seus respectivos métodos getter e setter. Por exemplo: Se tivermos o atributo private String nome; Devemos ter os métodos private String getNome() { return nome;} e public String setNome (String nome) { this.nome = nome;}. Este é um padrão amplamente adotado em Java, logo a maioria das ferramentas IDE já possuem ferramentas que geram automaticamente estes métodos. No exemplo a seguir podemos ver como a propriedade nome pode ser ligada no campo do .xhtml. ●
O código acima indica que o método getter getNome do bean mapeado com o nome user, deve ser chamado quando o componente for renderizado (mostrado na tela), e o método setter setNome deve ser chamado quando for processada a resposta do usuário. Backing Beans
Em alguns casos é conveniente desenvolver um bean que contenha alguns ou todos os objetos componentes de um formulário web. Um bean desse tipo é chamado de backing bean do formulário web. Veja o exemplo abaixo:
public class UsuarioBean implements Serializable { private UIInput nomeField;
Neste caso o atributo link estará diretamente ligado a um campo do .xhtml através de um atributo binding, como mostrado abaixo:
Com isto você tem um controle sobre o campo do formulário, podendo controla-lo através deste atributo. Geralmente isto não é necessário, mas o mecanismo foi criado para casos em que está manipulação é necessária. Escopos dos Beans
Ao definir um Managed Bean também se define em que escopo ele deve atuar. Cada bean deve ser definido o escopo de acordo com a natureza do bean. Os escopos existentes são: ● Request ● View (Novo, existente apenas a partir do JSF 2) ● Session ● Application Vamos entender agora cada um destes escopos. Escopo Request (requisição)
Neste escopo é utilizado para beans que não necessitam armazenar dados entre requisições, pois ele começa quando um requisição HTTP é submetida e termina quando a resposta é enviada ao cliente. Escopo View
Este escopo foi adicionado na versão 2, para preencher a lacuna entre o escopo de requisição e o de sessão. Neste escopo os valores são mantidos entre requisições enquanto este estiver navegando para o mesmo .xhtml. Isto é muito util para páginas precisam manter os dados mesmo após uma requisição, como por exemplo páginas de listagem, que devem manter os dados até que o usuário troque de página. Uma peculiaridade deste escopo é que o bean terá que implementar Serializabe, uma vez que ele guarda o objeto para a proxima requisição. Escopo Session
O escopo de sessão guardará o objeto seguindo o mesmo padrão de session do Servlet. Isto quer dizer que enquanto o usuário manter o browser ligado com a sessão válida os valores permanecerão os mesmos. Funciona da mesma forma que Session de Servlets. Escopo Application
Este é o mais amplo dos escopos, assim como em Servlet, este escopo mantem os dados durante toda a existência da aplicação, isto quer dizer que este objeto será compartilhado entre todos os usuários. Deve se ter cuidado ao utilizar este escopo, pois não há separação dos dados entre as requisições de usuários diferentes.
Configurando Beans
Como vimos anteriormente, existem duas forma de configurar os beans, estas formas são por Annotations e por faces-config.xml. Apenas JSF 2 tme anotações, então quando se está trabalhando com versões anteriores a unica forma de configuração é pelo arquivo facesconfig.xml.
Configuração por anotações
Para anotar um managed Bean possuímos basicamente as seguintes anotações: ● @ManagedBean(name="") -> Anotação que indica que este objeto é um ManagedBean e deve ser controlado pelo JSF, o parâmetro que ele recebe é o nome do ManagedBean que será utilizado no .xhtml para variáveis de ligação; ●
@RequestScope -> Indica que o bean terá o escopo de request;
●
@ViewScope -> Indica que o bean terá o escopo de view;
●
@SessionScope -> Indica que o bean terá o escopo de session;
●
@ApplicationScope -> Indica que o bean terá o escopo de application.
A seguir temos um exemplo de Bean anotada, está bean terá nome de usuário e escopo de sessão. Nenhuma configuração adicional é necessária no arquivo de xml. @ManagedBean(name="usuario") @SessionScoped public class UsuarioBean { private String nome; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; }
}
Configuração por faces-config.xml
A segunda forma de configurar um bean é utilizando o arquivo faces-config.xml. Esta forma é válida tanto para JSF 1.2 quando JSF 2. Neste modo de configuração temos uma classe Java normal, apenas seguindo os padrões de construtor e getters/setter explicados anteriormente. Em adição a isto temos a configuração deste bean no faces-config.xml, onde será indicado o nome e escopo. Podemos ver no exemplo abaixo a mesma configuração mostrada acima por anotações, porém agora utilizando o faces-config.xml. Classe Java: public class UsuarioBean { private String nome; public String getNome() { return nome;
} public void setNome(String nome) { this.nome = nome; }
O arquivo WEB-INF/faces-config.xml é o padrão utilizado para descritor de configurações do JSF. No entanto, é possível também colocar informações de configuração nos seguinte lugares: ● Nos arquivos /META-INF/faces-config.xml, dentro de quaisquer arquivos JAR carregados pelo classloader do contexto externo. Usa-se esse mecanismo quando se trabalha com componentes reutilizáveis em um arquivo JAR. ●
Arquivos listados no parâmetro de inicialização java.faces.CONFIG_FILES dentro de / WEB-INF/web.xml. Como no exemplo:
Nesta seção, é vista a sintaxe de expressões de ligação de valor detalhadamente. Vamos entender então a expressão na forma a.b. Neste momento, assume-se que já é conhecido o objeto a que “a” faz referencia. Se “a” é um array, uma lista ou um map, então algumas regras especiais devem ser aplicadas (veja a próxima sessão). Agora, se “a” é qualquer outro objeto, então “b”deve ser o nome de uma propriedade de “a”. O significado exato de a.b depende se a expressão é usada em modo rvalue ou modo lvalue. Esta terminologia é usada na teoria das linguagens de programação para denotar que uma expressão do lado direito de uma equação é tratada diferentemente de uma expressão do lado esquerdo. Considere a equação: left=right; O compilador gera códigos para as expressões left e right. A expressão right é avaliada como rvalue e gera um valor. A expressão left é avaliada em modo lvalue e armazena um valor. O mesmo acontece quando é usada uma expressão de ligação de valor em uma componente de interface de usuário: Quando o campo texto for renderizado, a expressão user.nome é avaliada em modo rvalue e o método getNone é chamado. Durante a decodificação, a mesma expressão é avaliada em modo lvalue e o método setNome é chamado.
A expressão a.b em modo rvalue é avaliada chamando-se o getter da propriedade, enquanto que a.b em modo lvalue chama o setter da propriedade. Usando chaves
Como em JavaScript, é possível usar chaves em vez da notação com pontos. Como é possível ver abaixo, as três expressões têm o mesmo significado: ● a.b ● a["b"] ● a['b'] Por exemplo, user.senha, user[“senha”] e user[‘senha’] são expressões equivalentes. Mas por que escrever user[“senha”] se user.senha é muito mais fácil e digitar?
São estes os motivos: ● Quando é acessado um array, list ou mapa, a notação [] é mais intuitiva;
●
É possível usar a notação [] com strings que contenham pontos ou traços, exemplo msgs[“error.senha”];
●
A notação [] permite computar dinamicamente uma propriedade, exemplo a[b.nome].
Usando expressões para Map e List
É possível acessar valores de atributos Map e List de Managed Beans. JSF consegue, automaticamente, chamar os métodos necessários das interfaces para buscar ou settar os valores. Por exemplo, seja m um objeto de qualquer classe que implementa a interface Map, então m[“key”] é uma ligação ao valor associado. Em modo rvalue, o valor m.get(“key”) é recuperado. Em modo lvalue, a declaração m.put(“key”, right) é executada. Acima right é o valor “do lado direito” que é atribuído a m.key. É possível acessar um valor de qualquer objeto de uma classe que implemente a interface List. Deve-se especificar um índice inteiro para a posição da lista. Por exemplo, a[i] ou a.i liga o i-ésimo elemento da lista a. Neste caso i pode ser um inteiro ou uma string que possa ser convertida em inteiro. Usando expressões compostas
É possível utilizar um conjunto limitado de operadores dentro de expressões de ligação de valor: ● Operdores aritiméticos: +, -, *, /, %. Os dois últimos operadores possuem as variantes alfanuméricas div e mod. ●
Operadores relacionais <, <=, >, >=, ==, != e suas variantes alfanuméricas lt, le, gt, ge, eq, ne (as quatros primeiras são requeridas por motivos de segurança relativo ao XML).
●
Operadores lógicos &&, ||, ! e as suas variantes alfanuméricas and, ou, not (a primeira variante é requerida por motivos de segurança do XML).
●
O operador empty. A expressão empty a é true se a for null, um array ou String de tamanho 0, ou uma Collection ou Map de tamanho 0.
Operador de seleção ternária ?. A precedência dos operadores segue as mesmas regras do Java. Geralmente não deve-se fazer a maior parte da computação de expressões nas páginas web, pois isso viola a separação entre a apresentação e a lógica de negócios. Temos como exemplo de uso destes operadores, as regras especificas de apresentação, como por exemplo regras de apresentação de campos ou geração de textos para a tela. O exemplo abaixo mostra que um texto deve ser apresentado apenas quando o atributo do bean estiver setado para mostrar. A maioria das tags de JSF possuem o atributo rendered, que indica se o componente deve ser mostrado na tela ou não. ●
Outro exemplo é a concatenação de atributos para apresentação na tela, como mostra o exemplo abaixo:
Usando expressões de ligações de método.
Este tipo de ligação é utilizada para chamar ações da bean, neste caso a expressão de ligação é mapeada diretamente para o nome do método no bean. Abaixo temos um exemplo típico de ligação de método:
Código do .xhtml public String logar () { //TODO implementar regras de negócio para login return "sucesso-login"; }
Método no Managed Bean Os atributos de componentes que aceitam este tipo de ligação são: ● action ● validator ● actionListener ● valueChangeListener
Comunicação entre Beans
Algumas vezes é necessário acessar dados de um Managed Bean dentro de outro. Um exemplo é se tivermos um UsuarioBean que seja de sessão. Neste bean teremos todos os dados do usuário logado, com isto ao chamar um método de negócio que necessite do ID do usuário, por exemplo, precisamos recuperar o dado deste UsuarioBean. Para que isto seja feito podemos utilizar ManagedProperties, podemos fazer isto de duas formas, usando a Anotação @ManagedProperty por faces-config.xml.
Usando anotação ManagedProperty
Esta anotação indicará que um atributo do seu bean será mapeado a partir de uma variável de ligação. O exemplo abaixo mostra como a classe CadastroBean receberá o Managed Bean usuario: @ManagedBean(name="cadastro") @RequestScoped public class CadastroBean { @ManagedProperty (value="#{usuario}") private UsuarioBean usuario; public void setUsuario(UsuarioBean usuario) { this.usuario = usuario; }
}
Com este código o atributo usuário terá a referência ao bean.
Mapeando managed-property via faces-config.xml
A segunda maneira de gerar esta referência é utilizando mapeamento por faces-config.xml. Desta forma temos que indicar qual atributo do ManagedBean deverá receber o bean de acordo com a variável de ligação. O Exemplo abaixo mostra o mesmo exemplo apresentado acima, entretando com o uso de faces-config.xml. cadastrocom.diehl.bean.CadastroBeanrequestusuario#{usuario}
Mapeamento por faces-config.xml public class CadastroBean { private UsuarioBean usuario; public void setUsuario(UsuarioBean usuario) { this.usuario = usuario; }
}
Classe da bean sem as anotações.
Navegações
Objetivos ●
Entender como funcionam as navegações
●
Ver navegações estáticas
●
Ver navegações dinâmicas
●
Ver redirecionamento de páginas
●
Ver regras de redirecionamento coringas
●
Entender navegação implícita do JSF 2
Navegação Estática
Consideremos o que acontece quando o usuário de uma aplicação web preenche um página. Toda a utilização ou modificação acontece dentro do navegador do usuário. Quando ele clicar em um botão que envia os dados do formulário, estas modificações são transmitidas ao servidor. Nesse momento, a aplicação web analisa os dados do usuário e deve decidir qual página JSF será utilizada para renderizar a resposta. O handler de navegação é responsável por este processo. Em aplicações simples, a navegação entre páginas é estática. Ou seja ao clicarmos em um determinado botão sempre terá uma página fixa para renderizar a resposta. A configuração da navegação estática fica no arquivo faces-config.xml, ou pode ser feita de forma implícita como será mostrado adiante. Veja o exemplo abaixo:
O valor do atributo action deve ser igual ao outcome da regra de navegação configurada para este botão, veja abaixo: /index.xhtmllogin/welcome.xhtml
A regra acima diz, simplesmente, que a ação de login será encaminhar para /welcome.xhtml caso tenha ocorrido dentro da página /index.xhtml. Observe que as strings from-view-id e to-view-id devem começar com uma “/”. A extensão deve coincidir com a extensão do arquivo (.xhtml), não com a extensão da URL. Se escolhermos as strings com cuidado, podemos agrupar várias regras de navegação. Por exemplo, poderíamos ter botões com a ação logout espalhados por todas as páginas de uma aplicação. Faríamos com que todos estes botões naveguem para a página logout.jsp apenas configurando a seguinte regra:
logout/logout.xhtml
A regra acima se aplica a todas as páginas porque não foi especificado nenhum elemento fromview-id. Podemos, ainda, unir regras de navegação com o mesmo from-view-id. Como no exemplo abaixo: /index.xhtmllogin/welcome.xhtmlcadastro/cadastro.xhtml
Navegação dinâmica
Na maioria dos casos precisamos de mais que apenas navegação estática, precisamos decidir para onde ir de acordo com regras de negócio. Para isto existe a navegação dinâmica. Esta é basicamente implentada em métodos de action (aqueles chamados pelo atributo action na view). Estes métodos de action devem retornar um String que é o nome do from-outcome. Com isto o JSF saberá qual página deve ser renderizada. Pra implementarmos a navegação dinâmica, o botão de submissão deve ter uma referencia a um método, veja o exemplo abaixo:
No managed bean o método de action será: public String logar () { if (logado) { return "sucesso-login"; } else { return "falha-login"; } }
Com isto a decisão de qual página deve ser apresentada estará definida no Managed Bean, que só mostrará sucesso caso o usuário esteja logado. Em resumo, abaixo estão listados os passos que são executados sempre que o usuário clica em um botão de comando cujo atributo action seja uma referência a um método: ● O bean especificado é recuperado; ●
O método referenciado é chamado;
●
A string resultante é enviada ao handler de navegação;
●
O handler procura a página seguinte.
Redirecionamento
Se adicionarmos um elemento “redirect” após to-view-id, o container JSP termina a requisição atual e envia um redirecionamento HTTP ao cliente. A resposta do redirecionamento diz ao cliente qual URL usar para a próxima página. Redirecionar um página é um processo mais lento que reencaminhar (forwarding), porque é preciso mais uma viagem de ida e volta ao navegador. No entanto o ato de redirecionar dá ao navegador a chance de atualizar o seu campo de endereço. Abaixo um exemplo do uso do redirect: /helloworld.xhtmlproximo/cadastro.xhtml
Usando Coringas
Podemos usar coringas no elemento from-view-id de uma regra de navegação, veja exemplo: /secure/* ...
A regra acima se aplica a todas as páginas que comecem com o prefixo /secure/. Somente é permitido usar um único * e ele deve estar no fim da string ID. Se houver mais regras de coringas coincidentes, a combinação mais longa é usada. Navegação implícita no JSF 2
A partir do JSF 2 foi adicionado a navegação implícita. Este recurso permite as regras de navegação sem a configuração no arquivo faces-config.xml. O funcionamento deste é bem simples, a navegação é feita utilizando o nome do arquivo .xhtml, a única coisa que deve ser feita é utilizar na action o mesmo nome do arquivo .xhtml sem a extensão. Veja o exemplo abaixo:
logo deverá existir o seguinte arquivo: WebContent/cadastro.xhtml Caso o arquivo esteja em uma sub-pasta, devemos utilizar a seguinte notação:
Neste exemplo deveremos ter o arquivo WebContent/public/cadastro.xhtml.
Mensagens
Objetivos ●
Trabalhar com mensagens em JSF
●
Entender o funcionamento do mecanismo de mensagens
●
Trabalhar com mensagens a partir do código Java.
Ententendo as mensagens no JSF
Durante o ciclo de vida JSF, qualquer objeto pode criar uma mensagem e adiciona-la a uma fila de mensagens mantida pelo contexto dos arquivos de configuração do JSF. No final do ciclo de vida, na fase de Renderizar Resposta, podemos exibir mensagens em um .xhtml. Estas mensagens podem estar associadas a um campo específico ou então ser uma mensagem global. Existem quatro tipos de mensagens no JSF, estes são: ● Informação ●
Advertência
●
Erro
Fatal Todas as mensagens podem conter um resumo e um detalhamento. entretanto no .xhtml pode ser configurado o que deve ser mostrado. Um exemplo poderia ser resumo "Dados inválidos" e o detalhamento poderia ser "O valor deve conter apenas caracteres alfanuméricos". Para mostrar as mensagens são utilizadas duas tags que são: ● h:messages - Mostra todas as mensagens que foram adicionadas na fila de mensagens durante o ciclo de vida JSF. ●
●
h:message - Mostra uma única mensagem para o um componente definido. for desta tag indica de qual campo devem ser apresentadas as mensagens.
o atributo
Carregar mensagens de um arquivo Resource Bundle
Os arquivos de resource bundle (.properties) geralmente são usados para armazenar as mensagens estáticas e mensagens de erro de uma aplicação JSF. Para carregar o resource bundle com dados estáticos pode-se: ● Registrar o resource bundle na aplicação: adicionando o resource bundle dentro do arquivo de configuração do JSF; ●
Carregando o resource bundle: em cada página com a tag loadBundle. Como no exemplo:
O atributo basename corresponde ao caminho completo do arquivo .properties, que nesse caso ele está dentro do pacote messages e possui o nome de Resources. O atributo var é um alias (atalho) para a instância do objeto resource bundle. Ele é utilizado dentro das tags da página corrente. Para referenciar dados estáticos de um resource bundle utiliza-se expressões de valores como mostrado abaixo:
Muitas vezes em resource bundles as chaves dos valores utilizam "." (ponto). Neste caso devese utilizar a notação com parênteses :
Referenciando mensagens de erro
O JSF possui mensagens de erro padrão para as validações e conversões, que podem ser customizadas pelo desenvolvedor.
Componentes JSF
Objetivos ●
Conhecer as tags do JSF
●
Criação de formulários
●
Uso de painéis
Tags do JSF
A criação de .xhtml requer conhecimento das tags do JSF e de HTML. Para utilizarmos as tags do JSF precisamos importa-las, na definição do arquivo .xhtml. A geração feita pelo plugin JBoss Tools, já faz a inserção das principais bibliotecas. Vamos ver a estrutura básica do .xhtml > > > > >
Como pode ser visto na tag html as bibliotecas são carregadas, neste exemplo foram carregas as bibliotecas de html, core e facelets. Conforme o uso de outros componentes é necessário fazer a carga da biblioteca específica. As tags fundamentais só existem para dar suporte as tags HTML. A tabela abaixo mostra estas tags. Tag
Descrição
Facet Atribute Param Acti ActioonLis nListe tene nerr valueChangeListene r Converter conv convert ertDa DateT teTim imee Conv Conver ertN tNum umbe berr Validator validateDoubleRang e Vali Valida date teLe Lenngth gth valida validateL teLong ongRan Range ge
Adiciona uma faceta a umcomponente Adiciona um atributo (key/value) a um componente Adiciona um parâmetro a um componente Adi Adicion cionaa um lis listen tener de ação ação a um comp compon onen ente te
LoadBundle Selectitems Selectitem Verbatim
Adiciona um listener de mudança de valor a um componente Adiciona um conversor arbitrário a um componente Adici Adicion onaa um um conv conver erso sorr de data data e hor horaa a um um compo compone nent ntee Adic Adicio iona na um conv conver erso sorr numé numéri rico co a um comp compon onen ente te Adiciona um validador a um componente Valida uma range dupla para um valor de um componente Val Valida ida a exte extens nsão ão de um val valor or de um comp compon onen ente te Valida Valida uma rage rage long longaa para para um um valo valorr Carrega um resource bundle, armazena propriedades como um Mapa Especifica itens para um componente select one ou select many Especifica um item para um componente select one ou select many Adiciona código markup a uma página JSF
As tags HTML do JSF representam o seguintes tipos de componentes: ● Inputs ●
Outputs
●
Comandos
●
Seleção
Outros A categoria outros inclui formulários, mensagens e componentes que geram layout para outros componentes. ●
A tabela abaixo mostra as tags HTML. Tag
Descrição
Form InputText InputTextarea InputSecret InputHidden OutputLabel OutputLink
Formulário HTML Controle de entrada de texto de uma única linha Controle de de en entrada de de te texto de de vá várias lilinhas Controle de entrada de senha Campo escondido Rotulação de outro componente para melhor acessibilidade Âncora HMTL Tag igual ao outputText, mas que formata mensagens me nsagens compostas Saída de texto de uma única linha Botões: su submit, re reset ou ou pu pushbutton Link que age como um pushbutton Exibição da mensagem mais recente de um componente Exibição de todas as mensagens Exibição de uma imagem Cai Caixa de list listag agem em para para sele seleçã çãoo de de um um úni único co item tem Menu para seleção de um único item Conjunto de botões de radio
OutputFormat OutputText commandButton CommandLink Message Messages GraphicImage sel selectO ectOne neLi List stbo boxx SelectOneMenu SelectOneRadio selectBooleanCheckbo x select selectMa Many nyCh Check eckbo boxx sele select ctMa Many nyLi List stbo boxx selectManyMenu PanelGrid PanelGroup DataTable
Caixa de verificação Conj Conjun unto to de de caix caixas as de de veri verifi fica caçã çãoo Caix Caixaa de de lis lista tage gem m par paraa sel seleç eção ão de vári vários os iten itenss Menu para seleção de vários itens Tabela HTML Dois ou mais componente que são dispostos como um só Controle de tabela com muitas funções
Atributos comuns Existem 3 tipos de atributos que são compartilhados na maioria das tags de componentes HTML, estes 3 tipos são: básicos, HTML 4.0 e eventos DHTML. Vamos ve-los a seguir:
Atributos básicos
Os atributos básicos são aqueles de controle do JSF ou de estilos. Segue a tabela abaixo com eles: Atributo
Descrição
Id
Identificador de um componente Referência a um componente que pode ser usado em um backing bean Atributo boolean; se falso interrompe a renderização Nome da classe CSS Um valor de um componente, normalmente uma ligação de valor ligação a um método que reponde a mudanças de valor Nome da classe do conversor Nome da classe de um validador que é criado e vinculado a um componente Atributo booleano; se verdadeiro, exige a inserção de um valor no campo associado
Binding Rendered StyleClass Value valueChangeListener Converter Validator Required ID
O atributo ID funciona como um identificador único do componente, com ele é possível referenciar tanto no .xhtml quanto no Java o componente. O ID de componente deve ser sempre único, do contrário o JSF irá lançar uma exceção. Implicitamente todos os componentes tem um ID, caso não seja setado o atributo, o JSF gerará um ID automatico. Além disto o ID pode ser utilizado para referenciar o componente a partir de um Javascript. Isto é muito útil em alguns casos em que se deseja criar script customizados em sua página. Um exemplo do uso necessário de ID é na apresentação de uma mensagem de erro específica para um campo. Neste caso a tag message referenciará um ID do componente, como mostrado abaixo:
É possível também acessar o componente no contexto Java utilizando o ID informado. Isto é feito como mostra o exemplo abaixo: UIComponent nome = FacesContext.getCurrentInstance ().getViewRoot(). findComponent("form:campoNome");
Binding
É possível criar um componente no Managed Bean que será a representação do componente do .xhtml. Este tipo de ligação se dá pelo atributo Binding. Na seção de Backing Beans foi mostrado um exemplo de como este atributo funciona. Value e ValueChangeListener
O Atributo value existe nos componentes que apresentam dados na tela ou componentes de formulário. Neste atributos pode-se colocar uma variável de ligação para qualquer atributo do Managed Bean que contenha getter/setter. Este valor será convertido para String e apresentado no componente. Já o ValueChangeListener irá usar uma variável de ligação que aponte para um método do Managed Bean, com isto este método será chamado quando o componente html sofrer alteração de valor. Cabe salientar que este método é chamado apenas após a submissão do form e não no evento onchange DHTML.
Converter e Validator
Estes atributos indicam qual será o componente de validação e de conversão. Estes componentes fazem o trabalho de converter o valor do formulário, que é sempre String, na representação correta do Managed Bean, e ainda validar se o valor informado é válido ou não. Rendered e styleClass
O atributo rendered é utilizado quando temos que suprimir algum componente da tela condicionalmente. ele espera uma expressão de ligação que deve retornar true ou false. Em caso de false o componente não é renderizado na tela. Já o styleClass é simplesmente a representação do atributo class de código HTML padrão, ele indica qual classe CSS deve ser utilizada no componente.
Atributos HTML 4.0
As tags HTML JSF têm atributos pass-through HTML 4.0 apropriados. Os valores desses atributos são enviados diretamente ao elemento HTML gerado. Por exemplo, gera o seguinte HTML: . Perceba que o atributo size é passado diretamente para o HTML. O atributos do HTML 4.0 estão definidos na especificação HTML, que você pode acessar na Internet em http://www.w3.org/TR/REC-html40. Este site é um excelente recurso para estudos aprofundados sobre o HTML.
Atributos Eventos DHTML
Os scripts cliente são úteis para vários tipos de tarefas, como por exemplo a validação de formulários, e esses são fáceis de usar com o JSF. O JSF oferece suporte aos atributos de eventos DHTML para quase todas as tags HTML JSF, veja a tabela abaixo com o atributos existentes. Atributo
O elemento perde foco O valor do elemento muda O botão do mouse é c1icado sobre o elemento O botão do mouse é c1icado duas vezes sobre o elemento O elemento recebe foco Uma tecla é pressionada Uma tecla é pressionada e subseqüentemente solta Uma tecla é solta O botão do mouse é pressionado sobre o elemento O botão do mouse se move sobre o elemento O mouse sai da área do elemento O mouse se move para cima do elemento O botão do mouse é solto O formulário é resetado (limpo) Algum texto é selecionado em um campo de entrada O formulário é submetido
Uso dos componentes com Javascript O JSF é baseado em componentes do lado do servidor, entretanto também é possível utilizar script do lado cliente para tarefas específicas. O exemplo abaixo mostra como um javascript consegue acessar os dados de um campo JSF. Digite seu nome: <script language="javascript"> function msg(formulario) { alert(formulario[ "cadastroForm:campoNome" ].value); return false; }
Exibindo imagens Existe uma tag no JSF que gera o HTML . Logo para exibir imagens do sistema esta deve ser usada, conforme mostrada abaixo:
Componentes de Formulário
A montagem de formulários deve ser feita com a utilização dos componentes JSF especificos. A seguir veremos cada um destes componentes e como Utiliza-los. InputText
Utilizado para gerar um campo texto de formulário. Gera um html do tipo: A tag a ser utilizada é:
/>
InputSecret
Este componente renderiza um campo de senha no HTML. Um campo senha é como um campo texto só que apresenta uma mascará (*) ao invés do conteúdo que está sendo digitado. Gera um código html do tipo: A tag a ser utilizada é: InputTextarea
Um textarea é um campo para digitar textos grandes pois ele possui mais do que uma linha. Basicamente é uma caixa onde pode ser colocado texto. Gera um código html do tipo: A tag a ser utilizada é: InputHidden
Campo invisível no formulário que serve apenas para passar atributos não controlados pelo usuário através do formulário. Gera um código html do tipo: A tag a ser utilizada é: Checkboxes Existem dois tipo de tags para criar componentes checkbox no JSF. Um para checkbox simples outra para grupos de checkboxes. Checkbox Simples
Estes são os checkboxes de apenas uma opção do tipo sim ou não. Um exemplo de um destes checkboxes é um campo do tipo "Deseja receber e-mail com informações?" neste caso a resposta do usuário é sim ou não. Este tipo de campo será mapeado para um atributo no Managed Bean do tipo boolean. O uso da tag é o seguinte:
Checkbox Multiplo
Este componente gera um grupo de checkboxes, cada uma representa uma opção e no Managed Bean este componente é representado por um List. Todas as opções selecionadas são adicionadas a esta lista. O exemplo abaixo mostra a configuração deste componente.
Na parte Java o atributo a ser mapeado seria: private List checkboxComposto ;
No caso acima as opções estão descritas no próprio .xhtml. Caso as opções sejam dinâmicas, elas podem ser carregadas de um Managed Bean. Basta que este tenha uma List como mostra o exemplo abaixo: