Perda de Sessão com JSF e Managed Beans

Olá pessoal!

Estou com um grande problema com relação a perda de sessão em uma aplicação com JSF.

Quando o usuário realiza o login, estou salvando uma instancia do objeto Usuario em um ManagedBean com:

setBean("UsuarioLogado", usuario)

Em minha página inicial tenho um link para uma outra página dentro da aplicação, que, ao tentar recuperar o bean fazendo

(UsuarioLogado) getBean("UsuarioLogado")

está retornando null. Como se o usuário tivesse perdido a sessão nessa passagem do index para essa nova página.

Não perdeu a sessão por tempo de inatividade pois foi o tempo entre o click e a abertura da página.

Se alguém puder me ajudar ficaria mt grato!

Abraços! =)

Adriano, nao entendi direito o porque voce esta salvando essa instancia “dentro” do managed bean. Por um acaso, esse objeto ja nao eh um agregado do seu managed bean? Se sim, seu managed bean esta declarado como no faces-config.xml? Session?

Se o tempo de timeout da sessao estiver muito curta, tente aumentar de repente pra 30 min em seu web.xml dentro da tag .

O que nao ficou claro foi o seguinte: Como voce pode ter certeza que a sessao foi expirada? Acredito que antes mesmo de voce conseguir acessar o seu managed bean para recuperar esse objeto, uma excecao na pagina eh lancada notificando que a sessao do usuario foi expirada, ou seja, se voce esta chegando neste managed bean, na minha opiniao a sessao ainda nao foi expirada. Tem certeza que voce esta setando este objeto no managed bean de escopo correto (Session)?

Passa mais detalhes por favor.

Abracos,

Fala alexmdo, primeiramente obrigado pela atenção. :slight_smile: Vamos lá.

No momento que o Usuario faz o login no sistema, vou ao banco buscando-o pela chave primaria que é o login e caso ele valide a senha, estou chamando este método passando um objeto de UsuarioLogado, que contem - alem de outras informacoes que vou precisar durante a aplicacao - um objeto Usuario (que veio do banco):

public void setUsuarioLogadoBean(UsuarioLogado usuario) { setBean("UsuarioLogado", usuario); }

Meu faces-config.xml tem uma tag assim:

<managed-bean> <managed-bean-name>UsuarioLogado</managed-bean-name> <managed-bean-class>sistema.UsuarioLogado</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>

Ele entra então na página principal do sistema exibindo corretamente todos os dados do Usuário que busco fazendo chamada a

getBean("UsuarioLogado");

Até aí tudo bem. No fluxo da tela de login pra página inicial, o usuário mantido na sessão está sendo obtido de forma correta.

Porém, nessa página, tenho um link para uma outra página. Um link que criei em html mesmo:

<a href......">Alterar meus dados</a>

E quando ele entra nessa página, logo no prerender eu já faço uma outra chamada a getBean. E nesse momento ele retorna null. Como se tivesse a sessão expirada. Mas isso em questão de segundos.

Se precisar de mais informações é só falar.

Mt obrigado!

Entendi.

Olha, talvez o problema esteja neste link, pois acredito que o JSessionId da requisicao pode estar se perdendo. Tenta colocar utilizar o <h:outputLink> colocando value apenas o caminho relativo da pagina (/paginas/???.jsp).

Voce poderia postar a implementacao deste getBean e setBean para analise?

Abracos

Claro que posso. Mas as implementações basicamente são essas:

public UsuarioLogado getUsuarioLogadoBean() { return (UsuarioLogado)getBean("UsuarioLogado"); }

public void setUsuarioLogadoBean(UsuarioLogado usuario) { setBean("UsuarioLogado", usuario); }

Coloquei o link agora em forma de <h:outputLink> e parece ter funcionado!! :smiley:

Pelo menos na primeira vez que cliquei ele funcionou legal e obteve o bean na página seguinte!! Vou fazer mais testes aqui, mas a princípio o problema está resolvido!! Mt obrigado cara!!

Cara, corrigindo. O outputlink não resolveu o problema. Na primeira vez funcionou mas agora voltou a perder o objeto.

Põe o codigo ai, pode ser que assim alguem veja o erro ^^

Bom, vamos lá. Vou tentar detalhar ao máximo aqui.

Meu arquivo faces-config.xml tem a seguinte tag:

&lt;managed-bean&gt; &lt;managed-bean-name&gt;UsuarioLogado&lt;/managed-bean-name&gt; &lt;managed-bean-class&gt;portal.model.rn.login.UsuarioLogado&lt;/managed-bean-class&gt; &lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt; &lt;/managed-bean&gt;

Tenho 3 páginas até o momento: index.jsp -> portal.jsp -> extrato.jsp.

Ao entrar em index.jsp, o usuário faz o login digitando seu login e senha. Na validação estou fazendo:

UsuarioLogado usuarioLogado = new UsuarioLogado(); //Aqui o 'usuario' veio do Banco; usuarioLogado.setUsuario(usuario); //Função do próprio framework JSF; setBean(&quot;UsuarioLogado&quot;, usuarioLogado);

Em seguida disso, o usuário é levado à pagina portal.jsp que tem no prerender a seguinte chamada:

UsuarioLogado u = (UsuarioLogado)getBean(&quot;UsuarioLogado&quot;);

Nesse caso, retorna-se o usuário armazenado em index.jsp; consigo obter tudo dele, direitim. Além disso, no portal.jsp eu tenho:

&lt;h:outputLink value="/portal/faces/extrato.jsp"&gt;Meu Extrato&lt;/h:outputLink&gt;

Quando eu clico nesse link, o prerender do extrato.jsp faz a mesma chamada de getBean que o portal.jsp faz, porém obtendo null! Como se houvesse perda de sessão. Mas já chequei no manager do tomcat e a sessão ainda está lá ativa. Parece que não está mais havendo referência entre o usuário que clicou e sua sessão. Muito estranho.

Deixa eu ver se entendi bem: Voce tem um managed bean UsuarioLogado declarado com escopo de session. Em seu codigo, vc INSTANCIA ele e o seta em algum lugar que ate agora nao consegui ver como foi implementado.

Esta funcao que voce diz ser do proprio framework, na verdade ele nao existe. Ou ao menos eu desconheco. De que classe voce o esta chamando? Pra mim, parece mais uma customizacao feita por alguem.

//Função do próprio framework JSF;
setBean(“UsuarioLogado”, usuarioLogado);

Tudo indica que dentro de uma requisicao pra outra, o atributo nao eh perdido. Ate aonde entendi eh da segunda requisicao em diante que voce esta perdendo o atributo. Isso eh um comportamento perfeitamente normal ao se trabalhar com Request. Ainda assim, como vc disse que esta trabalhando com Session, entao de fato eh estranho.

Enfim, acredito que existe outra forma muito mais simples de resolver este problema. Tenta o seguinte:

class UsuarioLogadoMBean {

  private Usuario usuario;

  // setters e getters

  public void logar() {
    // utilize sua logica dentro do servico
    usuario = usuarioService.obter();
  }

}

// seu xhtml / jsp
<body>
  <h:form>
    <!-- neste ponto, nenhuma customizacao eh necessaria realizar, ja que o managed bean eh de sessao -->
    <h:commandLink action="#{usuarioLogadoMBEan.logar}" 
  </h:form>
</body>

Feito isso, tenta dentro do seu managed bean obter o referido objeto. Uma forma de fazer isso seria atraves do FacesContext.getInstance().getExternalContext().getRequest().getSession().getAttribute(“usuarioLogadoMBean”) (nao tenho certeza se eh nessa ordem as chamadas de metodos), o que acredito que getBean da sua implementacao deve estar fazendo isso.

Outra coisa, voce disse que o outputlink eh utilizado para navegar pra outra pagina. Porque vc nao usa o h:commandLink? Este ai seria o mais aproprieado!

Nao sei se isso ajudaria, mas perde uns 5 minutinhos pra ver.

Abracos

A documentação tá assim:

[quote]protected void setBean(String name, Object value)

Replace the value of any attribute stored in request scope, session scope, or application scope under the specified name. If there is no such attribute, create a new request scope attribute under this name, and store the value there.[/quote]

Já tentei também com o h:commandLink mas esse tá com o mesmo comportamento.

Tentei fazer o que vc sugeriu mas continuou na mesma.

Agora, o mais bizarro eu percebi agora.

Se eu faço o seguinte:

Faço o login > vou pra página do painel > entro no extrato (aqui "perde a sessão") > clico em voltar > dou CTRL + F5 (o browser pergunta se quero reenviar os dados preenchidos, bla bla bla, eu clico em sim) > depois entro no extrato denovo ele pega o UsuarioLogado com o getBean perfeitamente!!! Incrível isso!! Só pra complicar a depuração!! :?

Se for um projeto academico, posta o seu projeto TODO para analisar atravez de um upload. Senão, tenta simular esse comportamento com um File - New Project e posta eset novo projeto pra gente analisar.

Não consigo entender como isso pode dar errado.

Beleza alexmdo. Vou ver se faço isso e, além do upload posso tentar simular minha máquina como servidor.

Outra coisa interessante, monitorei com o Tomcat Manager as sessões abertas. Eu achava que ele estava criando uma nova sessão pois perdia a anterior. Mas a sessão permanece intacta. Parece ser um problema do setBean, getBean. Estranho pois utilizo esses dois métodos em uma outra aplicação e eles estão trabalhando perfeitamente.

Fala pessoal, tá resolvido.

Parei de usar o setBean e o getBean. Isso é implementação do JSF e não vai rolar de tentar mexer. To usando o getSession mesmo que resolve todos os meus problemas.

Mas é isso ae pessoal. Mt obrigado pela ajuda!! Grande abraço!

Posso ressucitar o post?

Estou com um problema parecido.

Tenho um MB e dentro deste tenho um @inject para outro MB.

@ViewController
@SessionScoped
@Name("primeiroMB")
public class primeiroMB

@Inject
private SegundoMB segundoMB;

Em um método eu tento setar um atributo no “segundoMB”. Na linha seguinte do código o atributo continua nulo.

Segundo segundo = this.fachada.buscarSegundo(idSegundo);
this.segundoMB.setBean(segundo);
...

Quando chega em “…” o bean do “segundoMB” continua nulo, mesmo o “buscarSegundo” trazendo o objeto perfeitamente.

Já tentei uma outra abordagem que é setar o “idSegundo” dentro de “SegundoMB” e lá dentro consultar e setar o bean. algo do tipo:

this.segundoMB.setId(idSegundo);
this.segundoMB.Carregar();
...

E no método “Carregar()” algo do tipo:

Segundo segundo = this.fachada.buscarSegundo(idSegundo);
this.setBean(segundo);
...

O estranho nessa abordagem é que enquanto estou dentro de “SegundoMB” tudo funciona perfeitamente. O id setado a partir do “PrimeiroMB” está lá, a consulta funciona e o bean é setado como planejado. Porém ao voltar para “PrimeiroMB”, “SegundoMB” perde todos os valores (o id, o bean, tudo).

Alguém teria noção do que pode ser?