org.hibernate.HibernateException: No session currently bound to execution context

chrisjleu picture chrisjleu · Dec 7, 2009 · Viewed 7.6k times · Source

I'm trying to integrate Spring Security with Hibernate. I'm new to both technologies so I'm almost certainly taking too many steps at once here, but I'm at the point where I want to authenticate a user from the database. I think this is certainly more a Hibernate problem that a Spring Security one but I mention it to give some context. Below is the error message and the code. Can anyone spot something?

org.hibernate.HibernateException: No session currently bound to execution context
    org.hibernate.context.ManagedSessionContext.currentSession(ManagedSessionContext.java:74)
    org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622)
    com.vicinity.dao.hibernate.GenericHibernateDAO.findByCriteria(GenericHibernateDAO.java:99)
    com.vicinity.dao.hibernate.HibernateUserDAO.getUserByLogin(HibernateUserDAO.java:35)
    com.vicinity.service.PersistentUserManager.loadUserByUsername(PersistentUserManager.java:67)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    $Proxy31.loadUserByUsername(Unknown Source)
    org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:83)
    org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:125)
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:121)
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:139)
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:98)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
    org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:108)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:150)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)

Configuration of the DAO and transaction management:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="hibernateUserDAO" class="com.vicinity.dao.hibernate.HibernateUserDAO">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userManagerTarget" class="com.vicinity.service.PersistentUserManager">
    <property name="userDAO" ref="hibernateUserDAO" />
</bean> 

<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
        <ref local="transactionManager" />
    </property>
    <property name="target">
        <ref local="userManagerTarget" />
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="loadUserByUsername">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

Here is the class that implements the UserDetailsService which is called to authenticate the user. This makes a call to the DAO, see the line userDAO.getUserByLogin(login);:

@Service("userManager")
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public class PersistentUserManager implements UserManager, UserDetailsService {

        @Override
        public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException, DataAccessException {
            User user = userDAO.getUserByLogin(login);

            if (null == user) {
                logger.error("User with login: " + login + " not found in database");
                throw new UsernameNotFoundException("user not found in database");
            }

            org.springframework.security.core.userdetails.User springUser;

            springUser = new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), true,
                    true, true, true, new ArrayList<GrantedAuthority>());

            return springUser;
        }
    }

Here is the DAO which reads from the database. Note that I'm trying to take advantage of the 'GenericDAO pattern':

@Repository("userDAO")
public class HibernateUserDAO extends GenericHibernateDAO<User, Long> implements UserDAO {

    public HibernateUserDAO() {
        super(User.class);
    }

    @Override
    public void createUser(User user) {
        super.makePersistent(user);
    }

    public User getUserByLogin(String login) {
        if (null == login) {
            throw new IllegalArgumentException("You must provide a username if you want to get the user.");
        }

        List<User> users = findByCriteria(Restrictions.eq("login", login));

        // TODO, might need to check here if there are more than one user with the same username
        if(users == null || users.size() == 0) {
            return null;
        } else {
            return users.get(0);
        }
    }
}

Here's the class where the error occurs, the line Criteria crit = getSessionFactory().getCurrentSession().createCriteria(getPersistentClass());:

public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {

    private Class<T> persistentClass;

    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    protected List<T> findByCriteria(Criterion... criterion) {
        Criteria crit = getSessionFactory().getCurrentSession().createCriteria(getPersistentClass());
        for (Criterion c : criterion) {
            crit.add(c);
        }
        return crit.list();
    }
}

I have the following in my hibernate configuration (hibernate.cfg.xml) which may be relavent:

<property name="current_session_context_class">org.hibernate.context.ManagedSessionContext</property>

Answer

Bozho picture Bozho · Dec 7, 2009

Try with this property name.

<property name="hibernate.current_session_context_class">
       org.hibernate.context.ManagedSessionContext</property>

However, it is preferable that you configure spring to be in charge of your session and transaction management. You can check this.