Search code examples
javaspringhibernatetransactionsspring-transactions

Hibernate Spring Transactional no transaction is in progress


I'm trying to get hibernate working with spring managed transactions. No matter what I do I always get 'no transaction is in progress' exception. The only thing I don't understand is this:

If I don't call sessionFactory.getCurrentSession() in my @Transactional method, everything goes fine and I can see HibernateTransactionManager transaction lifecycle methods being called - doGetTransaction(...), doCommit(...) etc. and no error is thrown.

When I add sessionFactory.getCurrentSession() in my method I still see doGetTransaction() (obviously), but as soon as getCurrentSession() is called I'm starting to see doRollback() and in the end I'm getting 'no transaction is in progress' exception. I've already spent whole day on it, hope someone helps. Tried changing transaction scope, xml configuration, basically everything I can think of. Using latest spring and hibernate versions (4.3.3 and 5.2.3 respectively)

applicationContext.xml:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/trainings"/>
    <property name="password" value="xxx"/>
    <property name="username" value="xxx"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

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

<context:annotation-config/>

<context:component-scan base-package="webtrainings.beans"/>

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

GenericDAO.java:

@Repository("genericDao")
@Scope(value = "singleton")
public class GenericDAO<T> {

    @Autowired
    private SessionFactory sessionFactory;

    @Autowired
    private ApplicationContext appContext;

    public void getAll(Class<T> clazz) {
        factory.getCurrentSession();
    }
}

MyService.java:

@Service("myService")
@Transactional
public class MyService {

    @Autowired
    GenericDAO genericDAO;

    @Transactional
    public void hehe() {
        genericDAO.getAll(Training.class);
    }
}

HelloController.java:

@Controller
@RequestMapping(value = "/welcome")
public class HelloController {

    @Autowired
    MyService myService;

    @Autowired
    ApplicationContext applicationContext;

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView handleRequestInternal(HttpServletRequest request,
                                              HttpServletResponse response) throws Exception {
        ModelAndView model = new ModelAndView("hello");
        model.addObject("msg", "hello world");
        myService.hehe();

        return model;
    }
}

spring-servlet.xml (mvc):

<context:component-scan base-package="webtrainings.utils"/>

<bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
</bean>

Stacktrace:

javax.persistence.TransactionRequiredException: no transaction is in progress
    org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3430)
    org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1397)
    org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1393)
    org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
    org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
    org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:932)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:487)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    webtrainings.beans.MyService$$EnhancerBySpringCGLIB$$3fca725c.hehe(<generated>)
    webtrainings.utils.HelloController.handleRequestInternal(HelloController.java:32)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:180)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

Solution

  • Apparently the problem is in using Java DCEVM with HotswapAgent. When I remove -XXaltjvm=dcevm -javaagent:C:\hotswap-agent.jar from tomcat run configuration everything works as expected. I guess this is one of the side effects of using "hacky" software. My knowledge in these things is too small to even try to guess what the actual problem is.