Reputation: 34705
I wondering it is possible to configure spring in way to fire particular method on end transaction?
For example I have service class with method
@Service
public class service implements IService
{
@Resource
private EntityDao entityDao;
@Resource
private SomeService someService;
@Transactional
@Override
public void doThings()
{
entityDao.doSmthOnDb();
someService.thisMethodFiresOnEndOfTransaction();
}
}
and second service class
@Service
public class secondService implements ISecondService
{
@Resource
private IService service;
@Transactional
@Override
public void method()
{
service.doThings();
/*
some other code that can break transaction
*/
}
}
so if I call secondService.method()
I want that someService.thisMethodFiresOnEndOfTransaction()
will be fire only if transaction end successfully.
Is it possible in spring?
Upvotes: 1
Views: 3695
Reputation: 1494
In Spring Boot, if you want to run a method at the end of a transaction, you can utilize the @Transactional annotation along with the TransactionSynchronizationManager class to register after-commit hooks
@Service
public class MyService {
@Transactional
public void myTransactionalMethod() {
// Your transactional code here...
// Register after-commit hook
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
runAfterTransaction();
}
});
}
public void runAfterTransaction() {
// Your after-commit logic here...
System.out.println("This method runs after the transaction is successfully committed!");
}
}
Upvotes: 1
Reputation: 3207
Not sure, if it's good idea to delegate this to spring when you can add new bean as indirection layer between those services and delegate this thing to it.
But if you really don't have choice or want to do it with Spring, you can specify your own PlatformTransactionManager
, which will delegate all calls to default manager, but also intercepts successful commit()
calls.
Example:
public class MyTransactionalManager implements PlatformTransactionManager {
// ... implementation via delegation skipped here
@Override
public void commit(TransactionStatus status) throws TransactionException {
defaultManager.commit(status);
// You might want to check status.isRollbackOnly() here
someService.thisMethodFiresOnEndOfTransaction();
}
Now you can either replace default transaction manager in your application (then ::thisMethodFiresOnEndOfTransaction will be called after each transaction) or add it in context with some qualifier, then you should write something like this:
@Override
@Transactional(value = "myManager", rollbackFor = ...)
public void method()
(And in the end of the answer I still think this is flawed approach and implementing it via just another bean is far better)
Upvotes: 2