Dúvida Injeção de Dependencia no Hibernate [RESOLVIDO]

Pessoal bateu uma dúvida e como vocês são mais experientes preciso de ajuda; Estou utilizando a injeção de depencias para abrir a conexão e transação do hibernate. Defini como @ApplicationScoped, a minha dúvida é, quais os riscos de eu ter apenas uma transação para a aplicação inteira? Isso é bom ou ruim? É praticamente um singleton correto?

[code]package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenSessionFactory implements ComponentFactory<SessionFactory>
{
private SessionFactory factory;

@PostConstruct
public void open()
{
	try
	{
		ApplicationLog.getInstance().info(this, "Criando Fábrica do Hibernate");
		AnnotationConfiguration configuration= new AnnotationConfiguration();
		configuration.configure();
		factory=configuration.buildSessionFactory();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
		factory=null;
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this,e.getMessage());
		factory=null;
	}
}


@PreDestroy
public void close()
{
	try
	{
		ApplicationLog.getInstance().info(this, "Encerrando Fábrica do Hibernate");
		this.factory.close();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this,e.getMessage());
	}
	finally
	{
		this.factory=null;
	}
}

public SessionFactory getInstance() 
{
	return factory;
}

}[/code]

[code]package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenSession implements ComponentFactory<Session>
{
private SessionFactory factory;
private Session session;

public OpenSession(SessionFactory factory)
{
	this.factory=factory;
}

@PostConstruct
public void open()
{
	ApplicationLog.getInstance().info(this, "Criando Session do Hibernate");
	try
	{
		this.session=this.factory.openSession();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this,e.getMessage());
	}
}
@PreDestroy
public void close()
{
	try
	{
		ApplicationLog.getInstance().info(this, "Encerrando Session do Hibernate");
		this.session.close();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this,e.getMessage());
	}
	finally
	{
		this.session=null;
	}
}

public Session getInstance() {
	return session;
}

}[/code]

[code]package br.com.eplus.hibernate;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;
import br.com.eplus.util.ApplicationLog;

@Component
@ApplicationScoped
public class OpenTransaction implements ComponentFactory<Transaction>
{
private Session session;
private Transaction transaction;

public OpenTransaction(Session session)
{
	this.session=session;
}

@PostConstruct
public void open()
{
	ApplicationLog.getInstance().info(this, "Abrindo transação do Hibernate");
	try
	{
		this.transaction=session.beginTransaction();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this,e.getMessage());
	}	
}

@PreDestroy
public void close()
{
	ApplicationLog.getInstance().info(this, "Fechando transação do Hibernate");
	this.transaction=null;
}

public Transaction getInstance() {
	return this.transaction;
}

}
[/code]

[code]package br.com.eplus.dao;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import br.com.caelum.vraptor.ioc.Component;
import br.com.eplus.model.Usuario;
import br.com.eplus.util.ApplicationLog;

@Component
public class UsuarioDao
{
private final Session session;
private final Transaction transaction;

public UsuarioDao(Session session, Transaction transaction)
{
	this.session=session;
	this.transaction=transaction;
}

public void salvarUsuario(Usuario u)
{
	try
	{
		ApplicationLog.getInstance().info(this, "Salvando novo usuário");
		session.save(u);
		transaction.commit();
	}
	catch(HibernateException h)
	{
		ApplicationLog.getInstance().error(this, h.getMessage());
	}
	catch(Exception e)
	{
		ApplicationLog.getInstance().error(this, e.getMessage());
	}		
}	

}[/code]

Creio que se vc trabalhar com uma só session para toda aplicação como controla a tentativa de manipular o mesmo registro? Porque os usuários que desejam manipular este registro estão na mesma session. Por isto creio que o correto é manter o scopo de sessão ( SessionScoped ).

Se você for deixar a transação aberta, não vejo como boa prática. Não vejo qual o ganho disso.

Só tome cuidado com o conceito. O @ApplicationScoped não é thread safe.

Esse post pode te ajudar a entender melhor o conceito de @ApplicatioinScoped: http://uaihebert.com/?p=1596&page=7

Legal o link jakefrog. Seria interessante então eu utilizar uma única SessionFactory para toda a aplicação
(@ApplicationScoped) e @RequestScoped para Transaction e Session (deixando o spring abrir e fechar estes dois a cada requisição)?

Se você está utilizando o Spring, por que você não usa o próprio sistema de transação dele?

Vou deixar que alguém que entenda melhor de Spring opine aqui. [=

Na verdade é o vraptor, mas acredito que o ioc dele é feito pelo Spring.

Bom vou partir da idéia que a SessionFactory busca as configurações do Hibernate e eu só preciso fazer isso uma vez, por isso vou deixar como @ApplicationScoped (economizo tempo e memória). Os demais eu vou deixar como @RequestScoped, onde o vraptor gerencia eles por si próprio, no fim as sequências ficaram:

12:21:43,701 INFO [OpenSessionFactory ] Criando Fábrica do Hibernate
12:21:55,560 INFO [OpenSession ] Criando Session do Hibernate
12:21:55,634 INFO [OpenTransaction ] Abrindo transação do Hibernate
12:21:56,006 INFO [UsuarioDao ] Salvando novo usuário
12:21:56,418 INFO [OpenSession ] Encerrando Session do Hibernate
12:21:56,422 INFO [OpenTransaction ] Fechando transação do Hibernate