Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Session found for current thread (Spring 3.1.X and Hibernate 4)

I'm trying to set up my project using Spring 3.1 and Hibernate 4. I've been following some tutorials online. I'm getting a strange error that according to the spring forums should have been fixed with Spring 3.1. Spring Bug Tracker

When my service calls getCurrentSession(), it throws the following exception:

org.hibernate.HibernateException: **No Session found for current thread**] with root cause org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) at
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:881)

****EDIT: updated my spring-dao.xml according to the Spring Spring 3.1 Documentation for Transactions. I've tried swapping out my datasource with a org.apache.commons.dbcp.BasicDataSource. Are there any properties I am missing from my configuration that could be causing this? ****

Here's my spring-dao.xml:

 <!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />   

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <value>hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect</value>
    </property>
</bean>

<!-- Declare a datasource that has pooling capabilities-->   
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
            destroy-method="close"
            p:driverClass="${app.jdbc.driverClassName}"
            p:jdbcUrl="${app.jdbc.url}"
            p:user="${app.jdbc.username}"
            p:password="${app.jdbc.password}"
            p:acquireIncrement="5"
            p:idleConnectionTestPeriod="60"
            p:maxPoolSize="100"
            p:maxStatements="50"
            p:minPoolSize="10" />

<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" 
            p:sessionFactory-ref="sessionFactory" />

My User bean (User.java)

package com.foo.lystra.beans;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="users")
public class User implements Serializable {
private static final long serialVersionUID = -5527566191402296042L;

@Id
@Column(name = "idusers")
private Integer user_id;

@Column(name="login_name")
private String loginName;

@Column(name="password")
private String password;

@Column(name="role")
private String role;

@Column(name="congregation_id")
private Integer congregation_id;

public Integer getUser_id() {
    return user_id;
}
public void setUser_id(Integer user_id) {
    this.user_id = user_id;
}
public String getLoginName() {
    return loginName;
}
public void setLoginName(String loginName) {
    this.loginName = loginName;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public String getRole() {
    return role;
}
public void setRole(String role) {
    this.role = role;
}
public Integer getCongregation_id() {
    return congregation_id;
}
public void setCongregation_id(Integer congregation_id) {
    this.congregation_id = congregation_id;
}

public String toString() {
    return "user_name: " + this.loginName + " congregation_id: " + this.congregation_id.toString();
}
}

And finally my service...

package com.foo.lystra.services;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.foo.lystra.beans.User;
import com.foo.lystra.beans.Congregation;

@Service("congregationUserService")
@Transactional
public class CongregationUserService {
protected static Log logger = LogFactory.getLog(CongregationUserService.class);

@Resource(name="sessionFactory")
private SessionFactory sessionFactory;

public List<User> getAllUsers() {
    logger.debug("getting all users");

            //Exception is thrown on this next line:
    Session session = sessionFactory.getCurrentSession();

    Query query = session.createQuery("FROM users");
    return query.list();
}
}

I realize that my datasource is probably not getting used. If I have forgotten to include any configurations I can update this post. Also if the Tomcat startup logs are needed I can provide them as well.

like image 981
It Grunt Avatar asked Jan 13 '12 06:01

It Grunt


5 Answers

I have the same problem in a web application. The problem is with which exist in both configuration files: application-context.xml and webmvc-context.xml. The webmvc-context.xml is loaded after application-context.xml. I think the DAO class is loaded first with transactional references when the application-context.xml is loaded, but it is replace with another object, without transactional references, when webmvc-context.xml is loaded. Any way, I resolve the problem with specific packages scanned:
<context:component-scan base-package="com.app.repository" />
for application-context.xml, and
<context:component-scan base-package="com.app.web" />
for webmvc-context.xml.

like image 182
Vali Avatar answered Nov 16 '22 15:11

Vali


I had this problem with spring-4.0.6 and hibernate-4.3.6.

Solution is to move all annotation-driven, component-scan, annotation-driven directives from root-context.xml to servlet-context.xml:

<mvc:annotation-driven />
<context:component-scan base-package="ru.dd.demo" />
<tx:annotation-driven transaction-manager="transactionManager" />

dataSource, sessionFactory and transactionManager can be still defined at root-context.xml.

like image 35
user3418209 Avatar answered Nov 16 '22 13:11

user3418209


Is it a web application? If so consider using OpenSessionInViewFilter. Cause I believe when using currentSession (which is bound to current thread) there must be a point in the code that unbinds the session from the thread.

I'm not sure whether transaction manager does this or not.

like image 22
Amir Pashazadeh Avatar answered Nov 16 '22 15:11

Amir Pashazadeh


I had the same error as yours.

This is a bug which is not solved yet.

https://jira.springsource.org/browse/SPR-9028

Try to change hibernate jar files to 3.6. because Spring uses it.

http://mvnrepository.com/artifact/org.springframework/spring-orm/3.1.0.RELEASE

here Spring 3.1 artifact and dependencies

like image 2
erencan Avatar answered Nov 16 '22 15:11

erencan


As stated in Spring Reference (3.2.x):

In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

So Beans defined or scanned with <context:component-scan> will be visible in your controllers so you can @Autowired them, but will be not visible in other applicationContext* files, so unless <tx:annotation-driven/> has been not defined in DispatcherServlet's config, @Transactional won't work.

So I'm guess that probably you have a <context:component-scan> in your DispatcherServlet's config and <tx:annotation-driven/> declaration in you applicationContext*.xml, so @Autowired works fine, but @Transactional is not.

like image 1
Mateusz Szulc Avatar answered Nov 16 '22 13:11

Mateusz Szulc