Olá Pessoal,
Tenho uma aplicação rodando com VRaptor 3.3.1, onde as Transações são gerenciadas pelo Spring.
Entro no formulario para cadastrar um produto novo, então o form envia os dados para o metodo adiciona() da controller, e depois de adicionar ele redireciona para o metodo lista().
(Aplicação da apostila FJ-28 da Caelum)
No momento em que ele vai redirecionar par ao metodo lista() da controller, ele da o WARN abaixo:
20:46:01,863 WARN [CommonAnnotationBeanPostProcessor] Invocation of destroy method failed on bean with name 'criadorDeSession': org.hibernate.SessionException: Session was already closed
Alguem saberia me dizer como evitar isto ? ou se esse WARN deve ser ignorado ???
Abaixo, arquivos do projeto:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:/hibernate.cfg.xml</value>
</property>
</bean>
</beans>
CriadorDeSession.java
@Component
public class CriadorDeSession implements ComponentFactory<Session> {
private final SessionFactory factory;
private final Proxifier proxifier;
private Session sessionDoSpring;
private Session session;
public CriadorDeSession(SessionFactory factory, Proxifier proxifier) {
this.factory = factory;
this.proxifier = proxifier;
}
@PostConstruct
public void abre() {
this.session = proxifier.proxify(Session.class, new MethodInvocation<Session>() {
public Object intercept(Session proxy, Method method, Object[] args, SuperMethod superMethod) {
sessionDoSpring = SessionFactoryUtils.doGetSession(factory, true);
return new Mirror().on(sessionDoSpring).invoke().method(method).withArgs(args);
}
});
}
public Session getInstance() {
return this.session;
}
@PreDestroy
public void fecha() {
//this.session.close(); - desta forma não aparece o WARN no console, mas as sessoes vao ficando abertas até estourar o pool de conexoes.
if(this.sessionDoSpring != null) {
this.sessionDoSpring.close();
}
}
}
ProdutosController.java
@Resource
public class ProdutosController {
private ProdutoDAO produtoDAO;
private Result result;
private Validator validator;
@Autowired
public void setProdutoDAO(ProdutoDAO produtoDAO) {
this.produtoDAO = produtoDAO;
}
@Autowired
public void setResult(Result result) {
this.result = result;
}
@Autowired
public void setValidator(Validator validator) {
this.validator = validator;
}
@Post
@Path("/produtos")
@Transactional
public void adiciona(Produto produto) {
// Hibernate Validator
validator.validate(produto);
validator.onErrorUsePageOf(this).formulario();
produtoDAO.salva(produto);
produtoDAO.flush(); // Coloquei o flush() da Session aqui p/ acompanhar se o WARN era antes ou depois do insert.
result.redirectTo(this).lista(); // No modo debug, o WARN ocorre exatamente nesta linha. O Insert já foi executado.
}
@Put
@Path("/produtos/{produto.id}")
@Transactional
public void altera(Produto produto) {
// Hibernate Validator
validator.validate(produto);
validator.onErrorUsePageOf(this).edita(produto.getId());
produtoDAO.altera(produto);
result.redirectTo(this).lista();
}
@Delete
@Path("/produtos/{id}")
@Transactional
public void remove(Long id) {
Produto produto = produtoDAO.carrega(id);
produtoDAO.remove(produto);
result.redirectTo(ProdutosController.class).lista();
}
@Get
@Path("/produtos")
public List<Produto> lista() {
return produtoDAO.listaTudo();
}
@Get
@Path("/produtos/novo")
public void formulario() {
// Direciona para WEB-INF\jsp\produtos\formulario.jsp
}
}