Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring transaction management Propagation.REQUIRES_NEW not working

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.

like image 686
Dinesh Appuhami Avatar asked Dec 19 '22 18:12

Dinesh Appuhami


1 Answers

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.

like image 74
Sotirios Delimanolis Avatar answered Mar 23 '23 00:03

Sotirios Delimanolis