spring transaction management Propagation.REQUIRES_NEW not working

5.3k Views Asked by At

My Service Class.

@Service
@Transactional(value = "transactionManager", readOnly = true, propagation = Propagation.REQUIRED)
public class DeviceServiceImpl{

@Transactional(readOnly = false)
public void blockAllDevices(){

    createSmsDeviceBlock();

}


public void createSmsDeviceBlock(){

    addToLogTables();

    smsService.sendSms();
}


@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
public void addToLogTables(){
         try {
          //save object with DAO methods...
        } catch (Exception e) {
          throw new ServiceException(ServiceException.PROCESSING_FAILED, e.getMessage(), e);
        }
}

}

From my controller , service method blockAllDevices() getting called. addToLogTables() method is marked as Propergation.REQUIRED_NEW, but the problem is with the addToLogTables() method new transaction not getting created and existing transaction is using.

The thing i want to do is, the transaction on addToLogTables() method should be commit before execute smsService.sendSms() method.

My problem here, if transaction failed to commit , on method addToLogTables() method, it should not execute smsService.sendSms() method.

1

There are 1 best solutions below

3
On

That's not a Propagation.REQUIRES_NEW issue. It's an issue with how @Transactional proxying works.

When Spring proxies your bean that's annotated with @Transactional, it basically wraps it in a proxy object and delegates to it after opening the transaction. When the delegated call returns, the proxy either commits or rolls back the transaction.

For example, your bean is

@Autowired
private DeviceServiceImpl deviceService;

Spring is actually going to inject a wrapper proxy.

So when you do

deviceService.blockAllDevices();

you are invoking the method on the proxy which has the transactional behavior. However, in blockAllDevices(), you are doing

createSmsDeviceBlock();

which is actually

this.createSmsDeviceBlock();

where this is referring to the actual object, not the proxy, so there is no transactional behavior.

This is further explained in the documentation.

You'll have to rework your design.