0

I'm using spring + hibernate + jersey in my application. I want to use transactions so I used spring's @Transactional annotation in my service layer. This is my hibernate.cfg.xml:

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/db</property>
    <property name="hibernate.connection.username">user</property>
  </session-factory>
</hibernate-configuration>

I haven't used session_context here so spring can manage it. In my applicationCOntext.xml, I have defined transactionManager:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db"/>
    <property name="user" value="username"/>
</bean>

<context:annotation-config/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="packagesToScan">
        <list>
            <value>com.hibernate.pojos</value>
        </list>
    </property>
</bean>

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

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

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

All urls matching /api/v1/* map to a servlet named jersey and servlet class used is com.sun.jersey.spi.spring.container.servlet.SpringServlet to which I have passed com.services as package to scan. In this package I have a class:

@Path("/app")
@Component
public class testApi() {
    @Autowired
    private DAOImpl daoimpl;

    @POST
    @Path("/create")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Transactional(rollbackFor = {Exception.class})
    public Map<String,Object> testHello(user u) {
        Map response = daoimpl.save(u);
        return response;
    }
}

The class daoimpl has the sessionFactory autowired and uses sessionFactory.getCurrentSession() method to get session. The method daoimpl.save(obj) just saves it in db. Since I have marked testHello as transactional, I expect a transaction to begin which is managed by spring and then control should go to daoimpl where the actual save happens. But I get save is not valid without active transaction. I have seen lot of posts where session_context is mentioned in hibernate config and because of that, spring is unable to handle transactions. But in my case, I have ensured that I dont provide any session_context. What am I missing? I even tried adding @transactional to DAO since in my sample app, Im just issuing one DB call for a service. But this didnt work either.

coder
  • 1,901
  • 5
  • 29
  • 44

1 Answers1

-1

Well could be that you are specifying a session factory via hibernate.cfg.xml and then again in Spring which gets passed to the transaction manager.

Not sure to be honest however I have never used a hibenate.cfg.xml and then following works for me (with the transactional config added as you have specified). This also gives you the advantage of specifying your connection params as properties and allowing you to easily swap db configs via Spring Profiles or some other mechanism.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
                                                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

        <bean id="sessionFactory"
                class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="packagesToScan">
                        <list>
                                <value>uk.co.xyz.domain</value>
                        </list> 
                </property>
                <property name="hibernateProperties">
                        <props>
                                <prop key="hibernate.show_sql">${hibernate.showsql}</prop>
                                <prop key="hibernate.format_sql">true</prop>
                                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                                <prop key="hibernate.hbm2ddl.auto">${hibernate.ddlauto}</prop> 
                                <prop key="hibernate.cache.use_second_level_cache">${hibernate.enablecache}</prop>
                                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                        </props>
                </property>
        </bean>

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

</beans>

See also here which actually suggests is shouldn't matter:

applicationContext.xml with datasource or hibernate.cfg.xml. Difference?

Community
  • 1
  • 1
Alan Hay
  • 22,665
  • 4
  • 56
  • 110