0

I have made a project which is built on Maven+Spring 3.1+Spring MVC 3.1+Hibernate 4.1 In the transaction if I use the code:

Session session=sessionFactory.getCurrentSession();
session.save(user);

It gives the exception at the getCurrentSession():

SEVERE: Servlet.service() for servlet appServlet threw exception
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:1024)
    at com.company.cv.dao.UserDAO.saveUser(UserDAO.java:30)
    at com.company.cv.service.UserService.saveUser(UserService.java:20)
    at com.company.cv.HomeController.saveUser(HomeController.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

But if I use openSession instead of getCurrentSession no exceptions and code transaction completes successfully:

    Session session = sessionFactory.openSession();
    session.save(user);

What is the reason? Thanks for the help

My applicationContext.xml:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/companycv" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
    <list>
        <value>com.company.cv.model.User</value>
    </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

servlet-context.xml:

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

<context:component-scan base-package="com.company.cv" />

My service code:

@Service
public class UserService implements UserServiceIntf{

    @Autowired
    UserDAOIntf userDAO;

    @Transactional
    public void saveUser(User user) {
        userDAO.saveUser(user);
    }
}

My DAO code:

@Repository
public class UserDAO implements UserDAOIntf {

    @Autowired
    SessionFactory sessionFactory;

    public void saveUser(User user) {
        Session session=sessionFactory.getCurrentSession();
        session.save(user);
    }
}
Rupesh Yadav
  • 12,096
  • 4
  • 53
  • 70
yyy
  • 437
  • 2
  • 9
  • 23

3 Answers3

1

You need add @Transactional annotation above your service method calling DAO method save. And since you have txManager defined in your app context you need not to manually manage the transactions.

ant
  • 22,634
  • 36
  • 132
  • 182
  • the thing is I can't get current session factory. But create session is okay. I had annotations and edited the code above. Can you take a look? – yyy Sep 15 '12 at 00:02
  • what do you mean by `I can't get current session factory`? Is it null? Side note why do you have two declarations of dataSource in your appcontext – ant Sep 15 '12 at 00:07
  • When I run Session session=sessionFactory.getCurrentSession() it gives the exception above. If I say Session session=sessionFactory.openSession(); no exceptıons happens and entity is saved. Why getCurrentSession() doesn't work? – yyy Sep 15 '12 at 18:48
1

One thing that I have observed you are doing wrong is that you are mixing the usage of Hibernate transaction API with the Spring managed transactions management abstraction. This is strictly not advised.

Session session=sessionFactory.getCurrentSession();
Transaction tx=session.beginTransaction(); // This is using Hibernate transaction API
session.save(user);
sessionFactory.getCurrentSession().save(user);
tx.commit();// This is using Hibernate transaction API

In the above code you are using hibernate transaction api to manage the transaction along with the Spring transaction management (when you annotate your Service method with transactional annotation)

You need to only use this

Session session=sessionFactory.getCurrentSession();
session.save(user);
sessionFactory.getCurrentSession().save(user);

Also as pointed out by others you have got duplicate datasource definitions listed. And you mention that you can’t get sessionFactory which does not make sense as it is injected via Spring and you say that in the other case you have access to sessionFactory. There is no reason why this should happen.

UPDATE

So you are saying that you do have sessionFactory accessible in both cases but it’s not working in case of getCurrentSession. Having made all the changes suggested, the best advise will be to see what’s happening under the hood by enabling the Hibernate logging and Spring framework logging in log4j configuration ( if you are using log4j) track the relevant activity.

Your log4j configuration file would be something like this

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=<file-path>
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n


# Root logger
log4j.rootLogger=INFO, file

# Hibernate and Spring logging
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.springframework.transaction=DEBUG

This would give you a clear picture.

Shailendra
  • 8,874
  • 2
  • 28
  • 37
  • There is no multiple datasource in my code. It was a copy-paste mistake. I edited my question, the thing is getCurrentSession doesn't work. I have to use openSession instead. – yyy Sep 16 '12 at 19:56
  • Hi, Shailendra. Sorry for the delay but I solved the problem later.The problem was using Hiberante4 as if it was Hibernate3. After looking at the Hibernate4 docs, I realized I have to openSession every time. I always forget to RFM!!!! :D – yyy Mar 22 '13 at 13:23
0

It was because of Hibernate4. If you look at the Hibernate4 DOC like I should have done in the first place ( :D ) Hibernate4 you have openSession every time. I think Hibernate guys made it so that noobies like me will be forced to use new session every time. Because session is not thread safe. FYI Hibernate openSession() vs getCurrentSession()

Community
  • 1
  • 1
yyy
  • 437
  • 2
  • 9
  • 23