I need to publish notification events to external systems over JMS, when data is updated. Id like this to be done within the same transaction as the objects are committed to the database to ensure integrity.
The ApplicationLifecycle events that spring-data-rest emits seemed like the logical place to implement this logic.
@org.springframework.transaction.annotation.Transactional
public class TestEventListener extends AbstractRepositoryEventListener<Object> {
private static final Logger LOG = LoggerFactory.getLogger(TestEventListener.class);
@Override
protected void onBeforeCreate(Object entity) {
LOG.info("XXX before create");
}
@Override
protected void onBeforeSave(Object entity) {
LOG.info("XXX before save");
}
@Override
protected void onAfterCreate(Object entity) {
LOG.info("XXX after create");
}
@Override
protected void onAfterSave(Object entity) {
LOG.info("XXX after save");
}
}
However, these events happen before and after the tx starts and commits.
08 15:32:37.119 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX before create
08 15:32:37.135 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
08 15:32:37.432 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
08 15:32:37.479 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX after create
What extension point does spring-data-rest have for adding behaviour that will execute within the spring managed transaction?
I use aop (pointcut and tx advice) to solve this problem:
and aop-config.xml:
This is the same as having controller methods annotated with @Transactional.
The solution described by phlebas work. And I also think "Run event handler within a same transaction" should be a feature which should be provided by Spring Data Rest. There are many common use cases to need to split logic to sepreate eventHandler. just like "triggers in database". The version show below is same as phlebas solution.
I have not worked on spring-data-rest, but with spring, this can be handled the following way.
1) Define custom TransactionSynchronizationAdapter, and register the bean in TransactionSynchronizationManager.
Usually, I have a method registerSynchronizaiton with a @Before pointcut for this.
2) And, implement Override method as follows