JSF Mini Livro – Dicas, conceitos e boas práticas

Evite @SessionScoped. Veja todos os tipos de Escopo

Diversos tutoriais na internet utilizam ManagedBean do tipo @SessionScoped para facilitar o entendimento do leitor. Apesar desse tipo de escopo ser bastante prático e útil ele aloca os dados na memória do servidor. A cada objeto/lista colocado em um @ManagedBean de sessão é mais um pedaço da memória do servidor ocupada.

Para ter uma boa aplicação utilizando JSF é fundamental entender o funcionamento de cada escopo. Vejamos a seguir a definição de cada escopo do JSF:

  • @RequestScoped – funciona como uma requisição “get/post” HTTP onde os dados recebidos são processados e uma resposta é enviada ao cliente; após o envio da respostas os dados do request são apagados da memória do servidor. Esse escopo tem um funcionamento simples, mas gera o pequeno desconforto de que o desenvolvedor precisará escrever todos os dados necessários para o JSF criar o objeto no ManagedBean na chamada de uma action. Em uma tabela (datatable) com todos os usuários cadastrados do sistema e com um botão para detalhar, seria necessário colocar um campo hidden contendo o id do usuário para que ao clicar no detalhar o ID do objeto fosse enviado e localizado na base. Esse tipo de escopo é thread safe e pode ser utilizado junto do CDI (Contexts andDependency Injection). O RequestScoped deixa a memória do servidor livre toda vez que termina uma requisição (para ver como utilizar essa abordagem com datatable, clique aqui).
  • @ApplicationScoped – ao definir um ManagedBean como ApplicationScoped esse ManagedBean estará sempre disponível entre todos os requests/responses de todos os usuários de sua aplicação. Esse tipo de ManagedBean é ideal para conter combos, listas e objetos de configurações por exemplo. Esse escopo não é thread safe e pode ser utilizado com CDI. Caso seja necessária alguma informação de um ManagedBean @ApplicationScoped antes que a primeira página seja construída, basta adicionar o seguinte parâmetro na anotação @ManagedBean: “@ManagedBean(eager=true)”. O atributo “eager” fará com que o servidor instancie o ManagedBean antes que chegue alguma requisição para essa classe.
  • @SessionScoped – guarda todos os objetos/atributos/listasdo ManagedBean na memória do servidor. Quanto maior a quantidade de usuários maior será memória que o servidor terá que gerenciar. A cada nova sessão HTTP criada no servidor, um novo ManagedBean com todos os seus atributos será alocado na memória do servidor, ou seja, seu funcionamento é semelhante ao funcionamento do HttpSession. Fique atento ao seguinte fato: Um ManagedBean do tipo SessionScoped não é thread safe e pode ser utilizado com CDI. Se o usuário abre a aba X e realiza uma consulta, como a consulta está demorando ele abre uma nova aba (chamaremos de Y) e altera algum resultado que tenha vindo. Ao retornar para a aba X ele terá uma tela com valores desatualizados podendo gerar comportamentos inesperados em seu ManagedBean.
  • @ViewScoped – podemos dizer que esse tipo de escopo está localizado entre os escopos: Request e o Session. Enquanto o usuário estiver na página os dados desse MB estarão vivos no servidor. Ao sair da página os dados dessa página serão eliminados da memória. Esse tipo de escopo é muito indicado para aplicações que utilizam Ajax. Toda vez que um “pop up/dialog” fosse exibido bastaria utilizar os dados que estão na memória do ManagedBean. Ele é thread safe, mas não funciona com CDI (para ver um exemplo com essa abordagem, clique aqui.
  • @ConversationScoped – esse tipo de ManagedBean é de uso exclusivo para aplicações CDI e é thread safe. Ele funciona como o ViewScoped, mas com a diferença de que o início e o fim da conversa com a requisição do usuário é feito de modo programático, ou seja, o desenvolvedor terá que iniciar e finalizar da “conversa”. Somente após o comando para liberar a memória é que o ManagedBean irá liberar os recursos alocados. Para utilizar esse tipo de função é necessário seguir os seguintes passos:
    • Criar um arquivo chamado beans.xml dentro da pasta “src/META-INF/”
    • Utilizar a anotação “javax.enterprise.context.ConversationScoped”.
    • Injetar um objeto do tipo javax.enterprise.context.Conversation.
    • Chamar os métodos conversation.begin() e conversation.end() para iniciar e finalizar o ManagedBean. Repare que parece bastante com uma conexão de banco de dados onde precisamos ter a certeza de que iniciamos e fechamos a conexão. O código abaixo traz um exemplo de como funcionaria um ManagedBean do tipo Conversation:
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;

@Named()
@ConversationScoped
public class CarroMB {

	@Inject
	private Conversation conversation;

	private enum Status {
		PODE_INICIAR, PODE_FINALIZAR, NADA
	};

	private Status statusDaConversacao;

	public void usarCarro(String comando) {

		if (statusDaConversacao.equals(Status.PODE_INICIAR)) {
			conversation.begin();
		}

		// trabalha informações

		if (statusDaConversacao.equals(Status.PODE_FINALIZAR)) {
			conversation.end();
		}
	}

	// outros métodos
}

Uma pergunta que pode vir à mente do desenvolvedor é: “Ao utilizar Ajax em um botão e se o usuário clicar demasiadas vezes nesse botão, continuo tendo a garantia do thread safe?”.

A resposta é sim. Na especificação do JSF (referência 13.3.2) diz que todas as requisições Ajax têm que ser colocas em uma fila antes de serem enviadas para o servidor. Será enviada para o servidor uma requisição, e quando essa requisição voltar a requisição seguinte será enviada.

97 thoughts on “JSF Mini Livro – Dicas, conceitos e boas práticas

  1. Show de bola Esse Mini Livro em JSF.
    Mais um post excelente que contribui bastante com a galera que utiliza jsf.
    Vai ser de grande ajuda nos meus trabalho e estudos.
    Um Abraço

  2. Muito bom o post, seu blog é referencia em vários aspectos quando a conversa é JEE, tanto pela didática quanto pelo nivelde utilidade do conteudo exposto. Parabéns

  3. Opa!O post está muito bom! Podes colocar os códigos fontes do mesmo?
    Quando eu executo o projeto no eclipse, ele mostra a página sem o css e o facelets.
    Na pasta /lib estão os seguintes arquivos: jstl-1.2.jar e javax.faces-2.1.12.jar

    Um abraço

    • Rafael, bom dia.

      Esse post foi criado para a revista então as instruções foram criadas justamente para não precisar de fonte.

      Você está chamando a página pela url com “/faces/” ?

      Se sim, seu web.xml está maepado com o “/faces/” ? Quando fiz o tutorial o próprio eclipse criou o web.xml com essa configuração já ativa.

      Se não tiver mapeado lá, posso alterar e coloca-lo aqui. [=

      Aqui tem um exemplo pronto que você pode baixar que utilizar o facelets: http://uaihebert.com/?p=1414

      Obrigado pela visita.

      • Caro Hebert,
        Não estou chamando a a página pela url “/faces”. eu sempre marco “.jsf” no eclipse.

        O interessante é quando eu marco a opcao preview para ver a página ele mostra tudo certinho, na hora de rodar a aplicação, ele apenas mostra a página com texto plano.

        Me tire uma dúvida, se eu colocar no welcome-file-list que a página index é xhtml, o tomcat vai carregar normalmente ou tem que ser .html?

        Eu te pergunto, pois eu criei uma index.xhtml e o tomcat me deu o erro 404. Mesmo colocando no web.xml que poderia ser ela a página inicial.

        Tive que renomear para index.html para que a página fosse encontrada, mas mesmo assim, não carregou os estilos da página e nem o facelets.

        Abraço

        • Rafael, bom dia.

          Você precisa verificar o web.xml se *.jsf está presente.

          Se você realizar o download do código presente nesse post (http://uaihebert.com/?p=1414), você encontrará o modo correto que funciona.

          E para o facelets funcionar, a página precisa ser xhtml. [=

          Até a próxima

  4. Hebert boa tarde tudo bem?

    Viu eu nao entendi o que vc fez no @requestscoped , vi lá sobre o inputhidden
    mas como vc faz pra que a proxima pagina tenha o objeto carregado sendo que neste escopo ele zera.

    Parabens pelo mini livro , vc é o cara! your are the man!!

  5. Muito bom. Gostei muito.
    Podia gravar umas vídeos aulas pra gente e disponibilizar de alguma forma que ganhe também, algo como a devmedia, sei lah… xD

    • Anderson, boa tarde.

      Eu já pensei nisso. Estive inclusive estudando para fazer vídeo aulas, o problema foi tempo e máquina.

      O PC que eu tenho em minha casa que era capaz de fazer isso estragou. =/

      E o tempo que eu tinha disponível faleceu. Aí já viu né. =/

  6. Opa, ótimo post!

    Realmente bem completo, com vários detalhes que muita gente por aí não conhece, com certeza vai ajudar muita gente (inclusive eu, rs).

  7. Muito bom o conteúdo. Claro, prático e está me ajudando demais a aprender JSF.

    Eu vi uma abordagem para as bibliotecas que eu achei interessante. Vi num artigo do BalusC no StackOverflow. (http://stackoverflow.com/questions/11988415/what-is-the-jsf-resource-library-for-and-how-should-it-be-used)

    Nele o autor ao invés de criar as bibliotecas por tipo de recurso, ele cria por temas. No atributo library ele coloca o tema (ex: default) e no atributo name ele coloca o tipo de recurso antes do nome (ex: css/main.css)

    Os diretórios: ao invés de resources/css, resources/img etc., fica resources/default/css, resources/default/img etc. e resources/seutema1/css, resources/seutema1/img.

    Sucesso e um abraço.

    • Fernando, bom dia.

      Infelizmente não tenho.

      Levei dias escrevendo, formatando e editando o post. E depois levei mais tempo ainda para traduzir para o inglês.

      Não tenho tempo suficiente para passar tudo para PDF, pois tenho estudado muito esses dias.

      Obrigado pelo apoio.

  8. Boa meu caro ! Excelente post! Bom para me atualizar com o JSF ! Só uma pequena correção ortográfica no seu post, na página 15 temos o seguinte trecho:

    … valores e uma nova negação não será iniciada; caso o retorno seja a String “cachorroCadastro.xhtml” uma nova navegação será iniciada

    “negação” seria “navegação”, correto ? :)

    Grande abraço !

  9. Realmente Fantastico Parabéns. Vou já ler o de
    JPA Mini Livro – Primeiros passos e conceitos detalhados, muito obrigado pela contribuição.

    • David, bom dia.

      Sou o cara não, falta muito ainda! =D

      Apenas tenho exercitado a cuca pesadamente e postado aqui! Valeu pela atenção.

  10. Mt bom post amiguinho :D. Só ficou feio nesse post a frase: “Real Madrid, Campeão!”.
    Háááá >: ) agora ja sei tudo sobre JSF, ja da até para tirar a minha poderosa certificação e n escutar mais vc falando: “Querer estudar para certificação que é bom nada ne ? ” rsss

    Parabéns mais uma vez pelo post e sucesso !!!

    • Carutcho, boa tarde.

      Agradeço o apoio e pode ter certeza que após sua primeira certificação eu vou ficar te cutucando com: “Estudar para a segunda certificação nada né?!”.

      >= )

      Valeu pela visita mano! o_

  11. Parabéns pelo excelente artigo uaihebert.
    Você teria como detalhar mais um pouco sobre o escopo @ApplicationScoped?
    Tenho a seguinte situação: Há uma lista de Exercício(item 1, item 2, item N) acessível a vários usuários e cada item só pode ser respondido por uma pessoa(qualquer pessoa). O Problema: fazer com que quando uma pessoa abrir um item, por exemplo, os demais usuários não devem poder acessá-la simultaneamente. Poderia criar uma managedBean @ApplicationScoped com um ArrayList de item “em aberto”. Mas não sei como fazê-lo.
    Alguma ideia? Se possível uma implementação já feita por alguém…
    Agradeço!

    • Olá, tudo bem?

      No seu caso o ApplicationScoped não é ideal.

      O ApplicationScoped deve ser utilizado com informações que não são específicas a um usuário, ou seja, os dados lá não devem pertencer ao usuário A ou B.

      Imagine um combo de cidades que qualquer usuário do sistema poderia ver os dados.

      Espero ter ajudado [=

  12. A mensagem de erro retornada pela validação que é mostrada na tela antes mesmo de ser carregada a página não precisa de um execute?

      • Hebert, boa noite.

        A minha duvida era a seguinte, na parte de validação com o ajax em que o erro após uma validação aparece sem ter de recarregar a página não é preciso colocar o execute na tag ajax para as informações serem mandadas para o bean que possui a validação?

          • Opa, o,o vamos la professor, não houve resultado algum sem o execute e então coloquei o execute para levar as informações e ai funcionou com pois o action mesmo só funciona quando é submetido, (ACHO EU). Vlw ai velho to aprendendo bastante com seus posts, principalmente como utilizar os primefaces.

  13. Boa Noite!

    Tenho um template definido assim:

    Sistema

    Quando acesso qualquer p:menuitem ele recarrega toda página..
    Tem como carregar somente o layoutUnit do conteudo?? Via ajax sei la.
    Qualquer ajuda é bem vinda, links etc. Nos formularios também qualquer ação ele
    recarrega tudo.

    Felipe

    • Felipe, bom dia.

      Não vi sua mensagem antes pois ela entrou no spam. O.o

      Infelizmente aqui não é um bom local para colocar código, as tags morrem. =/

      Tente postar sua dúvida no GUJ, o povo lá é gente boa. [=

  14. Opa blza

    Cara tava usando o Netbeans.. ai mudei tudo blza. Ficou redondo até o fato de alguma coisa setada com acento dentro do java começou a ficar algo parecido com isso

    Mostrando 1 até 1 de 1 registros

    Essa mensagem é montada a partir de uma consulta. Pelo que notei só em códigos java esse problema.
    O que seria?

    • Felipe, boa noite.

      Você está com problema de enconding.

      Clique com botão direito em cima do projeto e vá em properties. Já na opção resources veja se está UTF-8, se não marque e reinicie o Eclipse.

      Veja c funciona. [=

  15. Testei aqui, na página index funciona perfeitamente.

    Mas sempre que eu tento usar o template em outro arquivo, dá erro (só mostra o texto, sem estilo nenhum). O que pode ser?

    • Rodrigo, boa tarde.

      Verifique se o caminho do template está correto, se seu arquivo do template contém h:head e h:body. Veja também se a URL que você está digitando no browser se o seu final está mapeado no web.xml.

  16. Primeiramente,

    Parabéns pelo o seu post, já adotei algumas práticas.

    O endereço do meu sistema aparece da seguinte forma:

    “www.endereco.com.br/sistema/faces/index.xhtml”

    Só que quando eu apago o /faces/ e abro o meu código fonte, ele exibe todos meus códigos, comentários (mesmo com aquela configuração no web.xml), chamada dos métodos…

    Tem alguma sugestão, dica ou não tem jeito?

  17. Olá uaihebert, me diz uma coisa, não tenho experiencia com JSF e estou ajudando um amigo com uma aplicação que ele desenvolveu.

    Ele hospedou em um host com tomcat e 128MB memória. Está tendo problemas com memória, poucos acessos e o servidor fica sem memória. Ele usa em pelo menos 2 MBeans a @SessionScoped. Poderia ser por isso o alto consumo de memória? Ou 128 mega é pouco para JSF 2?

    • Romarcio, bom dia.

      Realmente a quantidade de memória está baixa.

      Até consultei com amigos sobre essa quantidade e eles falaram a mesma coisa.

      Outro detalhe é que mesmo que se a aplicação tivesse um MB do tipo @SessionScoped, apenas esse cara já seria capaz de estourar a memória. [=

      Obrigado pela confiança, até mais. [=

      • Valeu pela ajuda Hebert. Tinha dúvida se o @SessionScoped poderia ser o vilão nesse caso, mas parece que não era o único.

        O cara tava usando JDBC puro com JNDI, e as conexões não eram fechadas mesmo chamando o close, e em um certo ponto a app travava. Como ele usou Spring Security, aproveitei e passei toda a parte de conexões para controle do Spring com JdbcTemplate e pelo menos testando em casa o problema foi resolvido.

        Mas existe 2 @SessionScoped na aplicação, vou alerta ele para que modifique isso.

        Obrigado!

        • Opa, por nada.

          Só para deixar claro, não creio que o problema seja SessionScoped, mas sim como ele é utilizado.

          Se ele for utilizado para conter listas, muitos valores em memória aí sim ele poderá atrapalhar a memória.

          Obrigado pela visita. =D

  18. Ainda não li tudo, mas pelo que eu já vi estou achando excelente.
    Você poderia fazer também um mini livro de JPA.

    • Marcelo, boa noite.

      Já existe aqui no blog um mini livro de JPA. Existe também um chamado Consultas e Dicas só com diversas funções de Pesquisa no JPA.

      Até mais.

  19. Hebert , tenho uma dúvida, para um caso de um método synchronized que efetua a persistência no banco neste caso a melhor forma de garantir que somente uma requisição será executada por vez é utilizando o @ApplicationScoped na classe onde o método se encontra? ou não há a necessidade disso!?

    Obrigado e parabéns pelo site.

  20. Parabéns pelo artigo Hebert.

    Eu estou com uma dúvida aqui, pelo que andei testando, no ViewScoped o MB não é eliminado da memória quando você fecha a página, só quando você faz um redirect dessa página. Isso é um comportamento que não tem como ser controlado?

    • Cleiton, boa tarde.

      Um jeito de controlar seria reduzindo o tamanho do tempo de sessão (3min por exemplo), e após fazer isso, você colocaria uma chamada Ajax de curtos períodos (2 em 2 min por exemplo) apenas para manter a sessão ativa.

      Espero ter ajudado, Obrigado pela visita.

  21. Hebert gostaria de parabenizá-lo pelo excelente trabalho que vc tem feito no Brasil, compartilhar o conhecimento e ajudar as pessoas é algo muito raro em um mundo tão egoísta como temos observado. Parabéns pela didática e o detalhamento passo a passo no seu material que ajuda todos os níves de estudantes. Qeu Deus abençoe muito a sua vida em todos os sentidos. Um abraço e parabéns pela iniciativa, tem me ajudado demais tb no trabalho.

    • Bruno, boa noite.

      Fico feliz que estou conseguindo ajudar.

      Valeu mesmo pelo apoio e pela força.

      Deus abençoe aí.

      Obrigado pela visita, e desculpe a demora em responder. Estive

    • João, boa tarde.

      Eu não tenho o material em PDF, dá muito trabalho já criar o post e seria tempo d+ em criar o PDF.

      Obrigado pela visita.

  22. Oi, estou começando agora com JSF e achar um material legal não é fácil. Mas sua iniciativa é ótima , ta me ajudando bastante. Obrigada.

    • Luciana, boa noite.

      Primeiro, me perde a demora em responder. Estou muito pegado no trabalho, para você ter idéia, estou te respondendo dele enquanto um deploy não termina.

      Obrigado pelo apoio, fico feliz em saber que estou ajudando. (:

  23. Muito bom!
    O que me deixou com dúvida foi esse arquivo, “faces-config.xml”. Meu projeto não conta com este arquivo. Seria o web.xml? OBS: Estou desenvolvendo em JSF 2.2

    Outra coisa, se eu for trabalhar com vários idiomas, terei vários arquivos um para cada idioma. Como ficaria o EL acessando diferentes arquivos?

    • Guerino, boa noite.

      Primeiro, me perde a demora em responder. Estou muito pegado no trabalho, para você ter idéia, estou te respondendo dele enquanto um deploy não termina.

      Esse arquivo não é mais obrigatório nas versões mais novas do JSF, por isso que seu projeto não tem.

      Quando você for usar com muitas linguagens sua EL continuará do mesmo modo. Você pode adicionar quantos arquivos quiser, isso nunca influenciará sua EL.

      Espero ter ajudado, obrigado pela visita.

Leave a Comment