[Resolvido]HIBERNATE + VRAPTOR + Session

Olá,

Estou tendo um problema de sessions com o hibernate no vraptor.

Segui a apostila da caelum para criar as sessions:

public class CriadorSession {
	private static SessionFactory sessionFactory;
	private static ServiceRegistry serviceRegistry;
	
	public static Session getSession(){
	    Configuration configuration = new Configuration();
	    configuration.configure();
	    serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
	    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
	    return sessionFactory.openSession();
	}

}

Tenho a seguinte DAO… estou atribuindo no login do usuário as permissões buscando do banco com “session.createCriteria”.

	private final Session session;
	public static final int ADMIN = 1,OTC=2,SHOUSE=3;
	
	/**
	 * Cria Sessão vraptor
	 */
	public DaoGrupoUsuario() {
		this.session = CriadorSession.getSession();
	}
	
	public boolean permissaoAdmin(Usuario logado) {
		if(logado == null)return false;
		return (this.carrega(logado.getIdUsuario(), ADMIN)!=null);
	}
	
	public boolean permissaoOTC(Usuario logado) {
		if(logado == null)return false;
		return (this.carrega(logado.getIdUsuario(), OTC)!=null);
	}	

	public boolean permissaoSHOUSE(Usuario logado) {
		if(logado == null)return false;
		return (this.carrega(logado.getIdUsuario(), SHOUSE)!=null);
	}		
	
	public GrupoUsuario carrega(int idUsuario, int idGrupo){
		return (GrupoUsuario) session.createCriteria(GrupoUsuario.class).add(Restrictions.eq("idUsuario", idUsuario)).add(Restrictions.eq("idGrupo", idGrupo)).uniqueResult();
	}

	public void adiciona(Usuario usuario, int idGrupo) {
		Transaction tx = this.session.beginTransaction();
		GrupoUsuario grupo = new GrupoUsuario();
		grupo.setIdGrupo(idGrupo);
		grupo.setIdUsuario(usuario.getIdUsuario());
		this.session.save(grupo);
		tx.commit();
	}

	public void limpaSession() {
		this.session.flush();
		this.session.clear();
	}

Até aqui tudo bem.

Tenho uma classe UsuarioWeb de SessionScopped

@Component
@SessionScoped
public class UsuarioWeb 
{

	private Usuario logado;
	private final DaoGrupoUsuario daogrupo;
	
	public UsuarioWeb(DaoGrupoUsuario daogrupo){
		this.daogrupo = daogrupo;
	}

	public static final int NIVELADMIN =3,NIVELOTC=2,NIVELSHOUSE=1;
	private int nivelPermissao = 0;

	public int getNivelPermissao() {
		return nivelPermissao;
	}

	public void setNivelPermissao(int nivelPermissao) {
		this.nivelPermissao = nivelPermissao;
	}

	public Usuario getLogado() {
		return logado;
	}

	public void setLogado(Usuario logado) {
		this.logado = logado;
		nivelPermissao= 0;
		this.setAdmin(this.daogrupo.permissaoAdmin(logado));
		this.setOtc(this.daogrupo.permissaoOTC(logado));
		this.setShouse(this.daogrupo.permissaoSHOUSE(logado));
	}
	public void logOut() {
		this.logado= null;
		daogrupo.limpaSession();
	}

PROBLEMA:

  1. Eu acesso o sistema sem permissão ( o metodo carregar , retorna NULL )
  2. Atribuo a permissão no banco de dados com o método adicionar ( via resource jsp )
  3. Faço o usuário fazer logout
  4. Na próxima vez que o usuário faz login o mesmo método da DAO “carrega” novamente do banco a permissão:

i session.createCriteria(GrupoUsuario.class).add(Restrictions.eq(“idUsuario”, idUsuario)).add(Restrictions.eq(“idGrupo”, idGrupo)).uniqueResult();[/i]

Isto deveria retornar o meu bean de acesso, no entanto retorna null . ( consultei no banco e está lá, executei o mesmo SQL do log )

5.Notei que cada vez que eu restarto o servidor ele atualiza esta informação e retorna o GrupoUsuario correto.

Não sei se o problema está no SessionScopped, pois nas demais consultas o createCriteria funciona corretamente.

Fiz outro teste ao contrário.

Loguei com um usuário que tinha permissão
Removi a permissão do banco de dados
Fiz logOff
Loguei novamente para saber se a consulta iria retornar null, para minha surpresa a consulta retornou que o usuário tinha a permissão ainda (mesmo não estando no banco de dados)
Restartei o servidor
Loguei e a consulta retornou null ( sem permissão )

Li em um post que o hibernate faz cache das entidades, mas o que não entendo é porque a DAO consultando do controller sem sessionscoped ele atualiza normal e retorna certo.

O que será que estou fazendo de besteira?

Hoje somente para testes tentei fazer o seguinte:

Removi a anotação @SessionScoped e consegui retornar meu objeto de acesso GrupoUsuario se atualizando normalmente.

Acho que o problema está em utilizar chamar uma classe Dao para consulta dentro de um objeto que é @SessionScoped. O hibernate não retorna o valor atualizado do banco sem que eu reinicie o servidor.

Tentei fazer a query no braço e também não muda o valor retornado após alterado no banco de dados.

Ao fazer logout e login eu limpo a session do hibernate, mas não adianta, o valor continua o mesmo do ultimo lido na linha tabela.

public GrupoUsuario carrega(int idUsuario, int idGrupo){
		String gruposusuarios = "SELECT * FROM GRUPO_USUARIO WHERE idUsuario=:idUsuario AND  idGrupo=:idGrupo"; 

		Query sqlQuery = this.session.createSQLQuery(gruposusuarios).addEntity(GrupoUsuario.class).setParameter("idUsuario",idUsuario).setParameter("idGrupo", idGrupo);
		GrupoUsuario grupo = (GrupoUsuario) sqlQuery.uniqueResult();
		return grupo;

Eu queria fazer a consulta no banco e guardar em sessão os privilégios a que este usuário tem grupo de acesso. Vou tentar fazer a leitura chamando sempre no login, mas não dentro do objeto session scoped, mas sim no meu controller do usuário.

Resolvido o problema.

Solução:

Não utilizar acesso a classe Dao dentro de objetos que estejam anotados @SessionScoped.

Não entendi o porque…

Código da classe alterada

@Component
@SessionScoped
public class UsuarioWeb 
{

	private Usuario logado;
	private List<GrupoUsuario> gruposAcesso;
	public static final int NVADMIN = 3,NVOTC=2,NVSHOUSE=1;

	private int nivelPermissao = 0;

	public int getNivelPermissao() {
		return nivelPermissao;
	}

	public void setNivelPermissao(int nivelPermissao) {
		this.nivelPermissao = nivelPermissao;
	}

	public Usuario getLogado() {
		return logado;
	}

	public void setLogado(Usuario logado,List<GrupoUsuario> gruposAcesso) {
		this.logado = logado;
		this.gruposAcesso = gruposAcesso;
		nivelPermissao= 0;
		this.setAdmin(permissao(DaoGrupoUsuario.ADMIN));
		this.setOtc(permissao(DaoGrupoUsuario.OTC));
		this.setShouse(permissao(DaoGrupoUsuario.SHOUSE));
	}
	
	private boolean permissao(int idGrupo) {
		for (Iterator<GrupoUsuario> iterator = gruposAcesso.iterator(); iterator.hasNext();) {
			GrupoUsuario grupoacesso = (GrupoUsuario) iterator.next();
			if(grupoacesso.getIdGrupo() == idGrupo){
				return true;
			}
		}
		return false;
	}

	public boolean isLogado(){
		return logado != null;
	}
	
	public String getNome(){
		return logado.getNome();
	}

	public void logOut() {
		this.logado= null;
	}
.
.
.
.
}