I am implementing a Saga.
After a SomthingCreated
event is published and then Something
is retrieved on the other process.
The problem is that SomthingRepository.findById(somthingCreated.id())
returns null on the other process because the Something
object is not inserted on DB yet.
@Transactional
public String createSomething(long userId, String name) {
String somethingId = somethingRepository.newSomethingId();
Something something = new Something(userId, name);
somethingRepository.save(something);
System.out.println("save:"+System.currentTimeMillis());
return somethingId;
}
the SomthingCreated
event is published after save() using Aspect
@After("execution(* com.some.something.application.*.*(..))")
public void publish() {
DomainEventPublisher.instance().commitPublishing();
System.out.println("publish:"+System.currentTimeMillis());
}
And then, the message consumer invokes application logic.
@Transactional
public String handle(SomthingCreated somthingCreated) {
System.out.println("handle:"+System.currentTimeMillis());
Something something = somethingRepository.findById(somthingCreated.id());
something.do(); //<-- NULLPointerException
}
I think
The execution time is like this,
save:1643092272658
publish:1643092272852
handle:1643092272870
(the interval between publish
and handle
is faster than the interval between save
and publish
although the event passed the network!)
What is that I am missing. I am using JPA and RabbitMQ on Spring.
The repository is like this,
@Repository
public class JpaSomethingRepository implements SomethingRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public void save(Something something) {
entityManager.persist(something);
}
How can I solve this problem?
I could add sleep-method on handle-method and It works but It seems ugly.
I am using entityManager.persist() with @Transactional but why it is not inserted to DB in the same transaction?
Thank you for your answer in advance.
It was because of the order in which the advice
of AOP was applied.
I read this @Tansactional and @Aspect ordering
And then, I added the code below to configure the Aspect order.
@EnableAspectJAutoProxy
@EnableTransactionManagement(order = 2)
@Aspect
@Order(1)
public class EventProcessor {
...
@After("execution(* com.some.somethin.application.*.*(..))")
public void publish() {
DomainEventPublisher.instance().commitPublishing();
}
}
I applied for the order so that more inner @transactional proxy is executed first and then the EventProcessor
proxy publish event.