JavaServer Faces (JSF)
Padrão Java EE para desenvolvimento web baseado em componentes mantido pelo JCP.
JSF 1 - 2004
JSF 2 - 2009
Especificação JSF 2 - JSR-314 -> JSF Mojarra - http:/javaserverfaces.java.net/
-> Apache Myfaces - http://myfaces.apache.org
Extensões JSF Componentes mais sofisticados - Prime Faces
- RichFaces
- iceFaces
JSF 1 utilizava mto o arquivo faces-config.xml
JSF 2 encoraja o uso de anotation, por isso este arquivo quase não é utilizado.
-WebContent
+META-INF
- WEB-INF
- lib
javax.faces-2.1.14.jar -> Mojara
Ao enviar a request o tomcat delega a mesma para a servlet, O servlet(papel de controlador) decide qual página deve chamar.
Indica que a classe será gerenciada pelo JSF:
@ManagedBean
public class LivroBean{
private String titulo;
public void setTitulo(String titulo){
this.titulo = titulo;
}
public void getTitulo(){
}
public void gravar(){
}
}
No arquivo xhtml chama a 'classe.metodo' - Expression language
<h:inputText id="titulo" value="#{livroBean.titulo}"/>
MVC
Model - class Livro Model fala com view por @ManagedBean
View - xhtml
Controller - Servlet
Ciclo de vida de componentes JSF
Basicamente o dado que saiu da tela e foi pro back se mantem lá, e ai retorna e volta pra tela, por isso a tela continua com o dado aparecendo mesmo depois da request enviada
A árvore de componentes (ou seja, a sua tela) fica salva na HttpSession. Como a HttpSession é um objeto exclusivo do usuário no lado do servidor, cada usuário terá guardadas a(s) sua(s) tela(s) em memória. Por isso o JSF é stateful (mantém o estado da tela entre requisições).
Devemos lembrar que ligamos o h:inputText ao modelo pela expression language. Quando usamos a expressão, o h:inputText passa o valor recebido para o modelo e chama o setter da classe Autor. Mas o input não só passa o valor, como também pede o valor do modelo antes de renderizar o HTML. A ligação é bidirecional, por exemplo:
<h:inputText value="#{autorBean.autor.nome}" />
Quando instanciamos um novo autor, o input recebe um Autor sem nenhum valor.
O h:selectOneMenu é o componente próprio para a renderização de um combobox.
Adicionamos o componente f:selectItems dentro do h:selectOneMenu, e usamos os atributos value, var, itemLabel e itemValue para respectivamente, recuperar os autores provindos do managed bean, nomear a variável que representará o autor, definir o texto que será mostrado nas opções e o valor das opções.
Qual é o efeito de anotar o LivroBean com @ViewScoped?
A instância de LivroBean existirá enquanto a tela existir.
Caso esta anotação não esteja presente, uma instância diferente de LivroBean será usada à cada requisição.
Qual é o escopo padrão adotado por um ManagedBean?
escopo da requisição (RequestScoped)
Por padrão um ManagedBean adota o escopo da requisição (@RequestScoped).
Além dos escopos de requisição (@RequestScoped) e da tela (@ViewScoped) JSF também dá suporte ao escopo da sessão (@SessionScoped) e escopo da aplicação (@ApplicationScoped), tudo configurável pelas anotações.
Que componentes utilizamos para criar uma tabela de dados?
Utilizamos o componente h:dataTable referenciando a lista de dados pelo atributo value. Dentro do h:dataTable, utilizamos o h:column para definir as colunas que existirão na nossa tabela. No nosso exemplo, utilizamos também o h:outputText para renderizar os dados do autor dentro do h:column. Por exemplo:
<h:dataTable value="#{livroBean.autoresDoLivro}" var="autor">
<h:column>
<h:outputText value="#{autor.nome}"/>
</h:column>
</h:dataTable>
Escopos JSF
@RequestScoped
É o escopo padrão caso você não informe um, ele funciona como um simples HTTP request, é descartado ao fim de cada requisição, o ManagedBean não manterá seu estado entre as solicitações/requisições HTTP que o usuário fizer.
A cada requisição uma nova instância do ManagedBean sera criada, usada e descartada, desta maneira não há compartilhamento das informações do ManagedBean entre as requisições.
@SessionScoped
Tem o mesmo comportamento da sessão web (HttpSession), o estado do ManagedBean é mantido até o fim da sessão do usuário. É preciso ter muito cuidado ao utilizar o SessionScoped, pois ele será mantido em memória até que o usuário termine a sessão. Imagine uma aplicação com 1000 sessões de usuários ativos, e cada sessão mantendo um ManagedBean com escopo SessionScoped, imagine agora que cada ManagedBean tem uma lista com 300 objetos, seriam 300000 objetos mantidos em memória.
Ele é ideal para guardar informações da sessão, dados do usuário, páginas acessadas, horários etc.
@ViewScoped
É um tipo de escopo que fica entre o RequestScoped e o SessionScoped. O MangedBean vai manter seu estado enquanto o usuário permanecer na mesma página. Qualquer navegação para outra página ou até mesmo um redirect para a mesma página ocasionara o fim do ManagedBean
É um escopo muito útil para páginas com várias chamadas AJAX, podendo abrir vários dialogs ou fazer varias requisições que os dados serão mantidos, desde que não haja nenhuma navegação para qualquer página, inclusive a atual.
É preciso ter em mente que usando esse tipo de escopo estamos suscetíveis a problemas que podem ocorrer com relação ao acesso de vários usuários ao banco de dados simultaneamente. Imagine que o usuário Carlos abre um produto para editar, e antes de finalizar a edição ele sai para tomar água deixando a tela aberta, nesse intervalo o usuário Raul acessa o sistema em outro computador e edita o mesmo produto e salva, quando Carlos voltar para finalizar a edição, as alterações do Raul serão perdidas. Em alguns frameworks como o JPA esse problema é facilmente tratado através do “lock otimista” e “lock pessimistic”, mas isso é assunto para outro post.
@ConversationScoped
Só pode ser usando com CDI, e controle é feito manualmente, ele funciona basicamente como uma transação de banco de dados. São necessários comandos para iniciar e para finalizar o seu ciclo de vida. O ManagedBean do tipo ConversationScoped tem apenas dois estados, transient e long running. O estado será transient antes do início e após o fim da conversação.
É ideal para telas que realizam muitas chamadas AJAX, e os dados precisam ser mantidos até um determinado momento, é possível navegar entre diferentes páginas que os objetos serão mantidos. Caso a sessão do usuário ter-
mine, o ManagedBean do tipo ConversationScoped será eliminado da sessão.
@AplicationScoped
Funciona como um Singleton, ou seja mantem apenas uma única instância na memória em toda a aplicação, todo usuário tem acesso ao mesmo ManagedBean, logo não é aconselhável guardar informações de usuários com ApplicationScoped.
As vezes é necessário que um ManagedBean com esse escopo seja iniciado antes de todos os outros, para isso basta adicionar a seguinte configuração: “@ManagedBean(eager = true)”, com isso ele sera iniciado antes que o usuário entre em qualquer tela da aplicação.
@Dependent
Só pode ser usando com CDI, este escopo não possui um comportamento próprio, ele vai herdar o comportamento do ManagedBean em que for injetado.
@NoneScoped
Dura apenas um chamada da EL e depois é eliminado da memória.
É um escopo extremamente curto, e será usado em tarefas muito especificas.
Ciclo de vida de componentes
A especificação define 6 fases. Para visualizar e acompanhar o ciclo de vida podemos plugar uma classe chamada automaticamente pelo JSF quando uma fase inicia ou acaba. Criaremos esse PhaseListener para entender o ciclo de vida.
1º Fase RESTORE VIEW - recuperada a arvore de componentes da sessao
2º Fase APPLY REQUEST VALUES - os componentes receberam os parâmetros da requisição
3º Fase PROCESS VALIDATIONS - todos os dados foram convertidos e validados
Como nenhum erro ocorreu nessa fase o controlador continua na próxima
4º Fase - UPDATE MODEL VALUES - o modelo será atualizado com os valores convertidos da fase anterior
5º Fase - INVOKE APPLICATION - opera sob os dados convertidos - atraves de expression language
6º Fase - RENDER RESPONSE - devolve a resposta ao usuário