VRaptor 3 + Hibernate 4

Estou tendo problemas com minha aplicação, estou utilizando VRaptor + Hibernate 4 + Spring 3.

Segue erro:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘hibernateTransactionInterceptor’: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.Session]: : Error creating bean with name ‘br.com.caelum.vraptor.plugin.hibernate4.SessionCreator’: FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘sessionCreator’: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, br.com.caelum.vraptor.plugin.hibernate4.SessionFactoryCreator]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, br.com.caelum.vraptor.plugin.hibernate4.SessionFactoryCreator]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘br.com.caelum.vraptor.plugin.hibernate4.SessionCreator’: FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘sessionCreator’: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, br.com.caelum.vraptor.plugin.hibernate4.SessionFactoryCreator]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, br.com.caelum.vraptor.plugin.hibernate4.SessionFactoryCreator]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1035)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:939)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:332)
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:328)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:274)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1106)
at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:86)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:47)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.environment.EnvironmentInterceptor.intercept(EnvironmentInterceptor.java:37)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44)
at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

E o meu web.xml:

<?xml version="1.0" encoding="UTF-8"?>

teste

vraptor br.com.caelum.vraptor.VRaptor vraptor /* FORWARD REQUEST javax.servlet.jsp.jstl.fmt.localizationContext messages

E o meu applicationContext:

<?xml version="1.0" encoding="UTF-8"?>

<tx:annotation-driven transaction-manager=“transactionManager” />

classpath:/hibernate.cfg.xml

com.mysql.jdbc.Driver jdbc:mysql://localhost/teste root 123456 3 1 15 100 20

<context:component-scan base-package=“com.teste.*.model.dao”>
<context:include-filter type=“annotation” expression=“org.springframework.stereotype.Repository”/>
</context:component-scan>

<context:component-scan base-package=“com.teste.*.model.service”>
<context:include-filter type=“annotation” expression=“org.springframework.stereotype.Service”/>
</context:component-scan>

Minha classe com.teste.framework.dao.DaoSupport:

package com.teste.framework.dao;

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

public class DaoSupport {

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

public SessionFactory getSessionFactory() {
return sessionFactory;
}

/**

  • Abrindo acesso ao session no mesmo pacote, nao somente subclasses.
  • Get a Hibernate Session, either from the current transaction or a new
  • one. The latter is only allowed if the “allowCreate” setting of this
  • bean’s HibernateTemplate is true.
  • @return the Hibernate Session
    */
    public Session getHibernateSession() {
    return getSessionFactory().getCurrentSession();

}

}

E minha classe com.teste.framework.dao.BaseDAO:

package com.teste.framework.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import com.teste.framework.domain.BaseVO;

@Repository
public abstract class BaseDAO {

@Autowired
protected DaoSupport hibernateSupport;

protected Log log = LogFactory.getLog(this.getClass());

private Class type = null;

/**

  • Remove o VO do session cache
  • @param vo
    */
    public void evict(BaseVO vo) {
    this.getSession().evict(vo);
    }

/**

  • Delete the given persistent instance.
  • @param vo
  • @throws HibernateException
    */
    public void delete(T vo) {
    getSession().delete(vo);
    }

/**

  • Delete the given persistent instances.
  • @param entities
  • @throws DataAccessException
  • @see org.springframework.orm.hibernate4.HibernateTemplate#delete(java.util.Collection)
    */
    public void delete(Collection entities) {
    for (T t : entities) {
    this.delete(t);
    }
    }

/**

  • Persist the given transient instance.
  • @param vo
  • @return a chave nova
  • @throws HibernateException
    */
    public Serializable insert(final T vo) {
    return getSession().save(vo);
    }

/**

  • @param vo
  • @return uma instancia conectada da entidade persistida
    */
    @SuppressWarnings(“unchecked”)
    public T update(T vo) {
    return (T) getSession().merge(vo);
    }

public T findById(Serializable id) {
return findById(getParameterizedBaseDomainClass(), id);
}

public void load(T entity, Serializable id) {
getSession().load(entity, id);
}

@SuppressWarnings(“unchecked”)
public T findById(Class<? extends T> clazz, Serializable id) {
return (T) getSession().get(clazz, id);
}

public void refresh(T entity) {
getSession().refresh(entity);
}

public void flush() {
getSession().flush();
}

public void clear() {
getSession().clear();
}

public Object merge(Object entity) {
return getSession().merge(entity);
}

public void persist(Object entity) {
getSession().persist(entity);
}

/**

  • Return all persistent instances of the given entity class. Note: Use
  • queries or criteria for retrieving a specific subset.
  • @return colecao de tipo t
    */
    public List findAll() {
    return findAll(getParameterizedBaseDomainClass());
    }

@SuppressWarnings(“unchecked”)
public List findAll(Class<? extends T> clazz) {
Criteria criteria = getSession().createCriteria(clazz);
return criteria.list();
}

/**

  • @return o tipo VO deste DAO
    */
    @SuppressWarnings(“unchecked”)
    Class getParameterizedBaseDomainClass() {
    return (this.type == null) ? this.type = (Class) BaseDAO
    .getParameterizedClass(this.getClass()) : this.type;

}

public static Class<?> getParameterizedClass(Class<?> c) {
return getParameterizedClass(c, 1);

}

@SuppressWarnings(“unchecked”)
public static Class<?> getParameterizedClass(Class<?> c, int index) {
Type[] types = getParameterizedTypes((Class) c);

return index <= types.length ? (Class<?>) types[index - 1] : null;

}

public static Type[] getParameterizedTypes(Class c) {
Type superClass = c.getGenericSuperclass();
if (!(superClass instanceof ParameterizedType))
superClass = c.getSuperclass().getGenericSuperclass();

return (superClass instanceof ParameterizedType) ? ((ParameterizedType) superClass)
.getActualTypeArguments()
: new Type[] {};
}

/**

  • Return the HibernateTemplate for this DAO, pre-initialized with the
  • SessionFactory or set explicitly.
  • @param hibernateSupport
  • the this.hibernateSupport to set
    */
    public void setHibernateSupport(DaoSupport hibernateSupport) {
    this.hibernateSupport = hibernateSupport;
    }

public Session getSession() {
return this.hibernateSupport.getHibernateSession();
}

}

Todas as outras DAO’s estenderão a baseDAO.

Poderiam me ajudar?

No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [sessionFactory, br.com.caelum.vraptor.plugin.hibernate4.SessionFactoryCreator];

se vc tá usando o spring pra criar a sessionFactory, tem que tirar o plugin do hibernate 4

Lucas! Obrigado pelo resposta tão prontamente e desculpe pelo post repetido…

Para eu utilizar da maneira como o VRaptor funciona, como devo fazer?

Preciso declarar um transactionManager e um sessionFactory no meu applicationContext?
Não preciso da classe DaoSupport então e minha BaseDAO anoto com @Component e recebo a Session no construtor? É isso?
Preciso declarar no web.xml um provider?

As configurações do jeito que estão, funciona normalmente com o Hibernate 3, porém com o 4 não consegui.

Agradeço a ajuda.

se vc vai usar o controle do spring, deveria usar tudo do spring, inclusive transactionManager e sessionFactory…

pra receber Session no construtor vc precisa criar outra classe: https://gist.github.com/3504425

mas vc pode continuar usando o DaoSupport sem problemas, se preferir

Desculpa reviver esse tópico, mas acredito que a classe CriadorDeSession, ão funcione mais. Tem alguma forma de ajeitar ela, porque o codigo que você passou, não roda mais.

se for hibernate 4 mesmo, use esse plugin:

Já tô com o plugin, mas a classe CriadorDeSession não roda mais, porque o metodo doGetSession nao existe na classe SessionFactoryUtils do pacote Hobernate4 do spring.

então apague essa classe, o plugin já faz isso.

Entendi, mas desta forma, eu não posso usar o controle de transações do Spring, correto? Tem algum jeito de contornar isso?

tem… remova o plugin do hibernate 4 e mude o CriadorDeSession para usar a api do spring pra hibernate 4…

se eu não me engano se vc fizer o CriadorDeSession retornar um factory.getCurrentSession() já funciona.