Surendra Jnawali
Surendra Jnawali

Reputation: 3240

Spring Hibernate Transaction Rollback Not Working

I am calling 2 different dao method from service layer. The second method throw Null Pointer Exception (Column 'address' cannot be null), but the task done from first method couldn't rollback.
Service Layer

package com.yetistep.dboy.business.impl;
@Service
@Transactional
public class TestServiceImpl implements TestService {
    @Autowired
    TestDaoService testDao;

    @Autowired
    CustomerDaoService customerService;

    @Override
    @Transactional //I supposed propagation control from aop config 
    public Boolean saveMulTransactions(User user, Customer customer) throws Exception {
        testDao.saveUser(user);

        customerService.saveCustomer(customer);

        return true;
    }
}  

//Dao Layer

public class TestDaoServiceImpl implements TestDaoService {
    @Autowired
    SessionFactory sessionFactory;
    Session session = null;
    Transaction tx = null;

    @Override
    public boolean saveUser(User user) throws Exception {
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
        session.save(user);
        tx.commit();
        session.close();
        return false;
    }
}
public class CustomerDaoServiceImpl implements CustomerDaoService{
    @Autowired
    SessionFactory sessionFactory;
    Session session = null;
    Transaction tx = null;
    @Override
    public boolean saveCustomer(Customer customer) throws Exception {
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
        session.save(customer);
        tx.commit();
        session.close();
        return false;
    }
}  

//Controller

public @ResponseBody
    ServiceResponse createAdmin(@RequestBody User user) throws Exception{
        log.debug("Saving User to Database");

        ServiceResponse serviceResponse = null;
        try {
            Customer customer = new Customer();
            customer.setName("Jeka");
            customer.setContact("87897898788978979");
            customer.setContact("Ktm");

            testService.saveMulTransactions(user, customer);
            serviceResponse = new ServiceResponse("User Added Successfully!!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return serviceResponse;
    }  

/Transaction Configuration in xml
//data source and hiibernate config here.....

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

    <!-- MUST have transaction manager, using aop and aspects  -->
    <bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="*" propagation="REQUIRED" rollback-for="Throwable"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="userServicePointCut"
                      expression="execution(* com.yetistep.dboy.business.impl.*ServiceImpl.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
    </aop:config>  

I supposed that, If any method of impl package throws error then rollback should be performed What is the problem please suggest me by answering?

Upvotes: 0

Views: 3815

Answers (1)

M. Deinum
M. Deinum

Reputation: 125212

And why should it roll back... You are opening new sessions yourself and managing transactions yourself also. How should Spring know that.

Your daos are wrong in multiple ways.

  1. Never store the session/transaction in a instance variable
  2. Never use openSession when using Spring to manage your transactions
  3. Never manage your own transactions if you want container managed transactions.

So in short fix your daos.

public class CustomerDaoServiceImpl implements CustomerDaoService{
    @Autowired
    SessionFactory sessionFactory;

    @Override
    public boolean saveCustomer(Customer customer) throws Exception {
        Session session = sessionFactory.getCurrentSession();
        session.save(customer);
        return false;
    }
}  

Is all you need (of course that goes for all your daos).

In addition your config is also wrong, you only need the <tx:annotation-driven /> you don't need the <tx:advice /> and <aop:config /> remove those.

All of this is explained in the reference guide.

Upvotes: 3

Related Questions