2

I have problem with session in hibernate:

INFO: Starting ProtocolHandler ["http-bio-8080"]
2013-09-10 16:23:11 org.apache.catalina.startup.Catalina start
 INFO: Server startup in 4000 ms
2013-09-10 16:23:13 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/portal] threw          exception [Request processing failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here] with root cause
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
    at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
    at com.myportal.portal.model.HibernateDao.getSessionFactory(HibernateDao.java:31)
    at com.myportal.portal.model.HibernateDao.testowa(HibernateDao.java:46)
    at com.myportal.portal.controllers.HomeController.home(HomeController.java:35)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

I've read something about this problem but the solutions don't work in my case.

My Dao class:

package com.myportal.portal.model;
import org.hibernate.classic.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.myportal.portal.entity.User;

@Repository
@Transactional(propagation=Propagation.REQUIRED)
public class HibernateDao {
    @Autowired
    private SessionFactory sessionFactory;


    public HibernateDao()
    {

    }
    public HibernateDao(SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }
    private Session getSessionFactory()
    {
        return sessionFactory.getCurrentSession();
    }

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

    public void testowa()
    {
        User u = new User();
        //SessionFactory sf = getSessionFactory();
        //Session s = sf.openSession().beginTransaction()

        // problem with this
        Session session = getSessionFactory();
        //session.save(u);

    }
}

root-context.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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->


<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/hibernate1"/>
    <property name="username" value="root2"/>
    <property name="password" value=""/>
    <property name="initialSize" value="5"/>
    <property name="maxActive" value="10"/>
</bean>    

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <property name="packagesToScan" value="com.spoleczniak.projekt.model"/>
   <property name="hibernateProperties">
       <props>
           <prop key="dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
           <prop key="show_sql">true</prop>
       </props>
   </property>
</bean>

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

     <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

</beans>

servlet-context.xml

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
    <context:annotation-config/>
<context:component-scan base-package="com.myportal.portal" />

    <!-- 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>

I use it like this:

@Controller
public class RegisterController {

    @Autowired
    private HibernateDao hibernateDao;

    @RequestMapping(value="/register")
    public String registerForm()
    {
        hibernateDao.testowa();
        return "register";
    }
}

How can I fix it?

I change DAO and create UserService, but error still appears :

DAO:

@Repository
public class HibernateDao {
    @Autowired
    private SessionFactory sessionFactory;


    public HibernateDao()
    {

    }
    public HibernateDao(SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }
    private Session getSessionFactory()
    {
        return sessionFactory.getCurrentSession();
    }

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

    public void testowa()
    {
        User u = new User();
        //SessionFactory sf = getSessionFactory();
        //Session s = sf.openSession().beginTransaction()

        // problem with this
        Session session = getSessionFactory();
        //session.save(u);

    }
} 

UserService:

@Service
public class UserService {

    @Autowired
    private HibernateDao hibernateDao;


    @Transactional
    public void addContact() 
    {
        hibernateDao.testowa(); 
    }
}

Controller:

@Controller
public class RegisterController {

    @Autowired
    private UserService userService;

    @RequestMapping(value="/register")
    public String registerForm()
    {
        userService.addContact();
        return "register";
    }
}
user2784083
  • 23
  • 1
  • 1
  • 4

3 Answers3

7

What's happening is your servlet-context.xml is overwriting beans in your root-context.xml because it's declaring a component-scan for the package containing the @Repository class. In servlet-context.xml, you have

<context:component-scan base-package="com.myportal.portal" />

while your HibernateDao class is in com.myportal.portal.model. This ApplicationContext will create a HibernateDao bean without transaction management, since it doesnt have <tx:annotation-driven>. The HibernateDao bean that is autowired in your @Controller is this one, not the one from the root-context.xml (which has transaction management).

To fix this, you will want to start by adding

<context:component-scan base-package="com.myportal.portal.model" />

to your root-context.xml and removing <context:annotation-config/> (it is redundant). You then want to modify the component-scan in the servlet-context.xml to something more specific that doesn't contain the package of the @Repository classes

<context:component-scan base-package="com.myportal.portal.controllers" />

that package would contain your @Controller classes. You also don't need the <context:annotation-config>.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Ok, I changed it.Now I have problem with creating been: Error creating bean with name 'hibernateDao' defined in file [I:\Spring\vfabric-tc-server-developer-2.8.1.RELEASE\base-instance\wtpwebapps\portalSpol\WEB-INF\classes\com\myportal\portal\model\HibernateDao.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/util/TraceClassVisitor – user2784083 Sep 16 '13 at 15:39
  • I added asm and cglib dependency and this error disappeared. Now I have:No mapping found for HTTP request with URI [/portal/] in DispatcherServlet with name 'appServlet'. So I think that doesn't see my controllers (controllers are in this package). before modification it worked fine. – user2784083 Sep 16 '13 at 16:08
  • ok, now it works fine. Thanks for your help, your advices are helpful for me. – user2784083 Sep 16 '13 at 16:40
0
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

This means that there is no current transaction within that thread.

As you corrected me the class is annotated with @Transactional but I see that it does not implement an interface. It may happen that the generated proxy does not expose the annotation as happens when you annotate a controller without it implementing an interface.

See why CGLIB proxies do not retain certain annotations.

Community
  • 1
  • 1
ElderMael
  • 7,000
  • 5
  • 34
  • 53
  • Oh right, did not read the code fully. But I now checked that the DAO object is not implementing an interface. Maybe the proxy generated does not expose the annotation in runtime. – ElderMael Sep 16 '13 at 14:41
  • The initialization step would have complained if CGLIB was missing from classpath. – Sotirios Delimanolis Sep 16 '13 at 14:43
  • It's not like CGLIB is not there, but that CGLIB creates subclasses to make proxies and subclasses do not retain annotations if you did not annotated the annotation with @Inherited – ElderMael Sep 16 '13 at 14:50
  • The proxy doesn't need to have the annotation, it's built because of the annotation. The proxy just has the functionality. – Sotirios Delimanolis Sep 16 '13 at 14:51
0

During beans instantiation servlet-context.xml is read and beans with @Controller, @Service, @Repository are instantiated.

Now when application-context.xml (which has <tx:annotation-driven />) is read the beans are already there and so doesn't get transactional behavior. Make the package in servlet-context.xml specific to UI like controller/ Or exclude the Service, Repository package from component-scan.

<context:component-scan base-package="com.java.controllers"/> 
Jason Aller
  • 3,541
  • 28
  • 38
  • 38