spring-projects / spring-modulith

Modular applications with Spring Boot
https://spring.io/projects/spring-modulith
Apache License 2.0
775 stars 127 forks source link

ApplicationModuleListener is not receiving events as application runs but does on restart #835

Open martyphee opened 5 hours ago

martyphee commented 5 hours ago

Problem seems very similar to #436. This is a bare bone WebFlux application. Just trying stuff out. I went by the code in the examples.

So while the application is running the events are persisted to Postgres with a completion_date as null. The code in the Auditor is never called while the application is running but only on startup.

I've stepped through the code but wasn't quite sure what line TransactionalApplicationListenerMethodAdapter.java:89 was doing (if (TransactionalApplicationListenerSynchronization.register(event, this, this.callbacks)) {).

I've set spring.modulith.republish-outstanding-events-on-restart=true

Any thoughts?

Publisher

@Component
@RequiredArgsConstructor
public class Auction {
    private final Logger logger = LoggerFactory.getLogger(Auction.class);
    private final @NonNull ApplicationEventPublisher events;

    @Transactional
    public Mono<BidRequest> auction(BidRequest bidRequest) {
        logger.info("Auction request in auction: {}", bidRequest);
        return Mono.just(bidRequest)
                .doOnNext((request) -> {
                    logger.info("Auction response: {}", request);
                })
                .doOnNext((request) -> {
                    logger.info("Publishing bid request event: {}", request);
                    events.publishEvent(new BidRequested(UUID.randomUUID(), request));
                });
    }
}

Consumer

@Component
@RequiredArgsConstructor
public class Auditor {
    private static final Logger LOG = LoggerFactory.getLogger(Auditor.class);

    private final ApplicationEventPublisher events;

    @ApplicationModuleListener
    void on(BidRequested event) throws InterruptedException {

        var id = event.id();

        LOG.info("Received order completion for {}.", id);

        // Simulate busy work
        Thread.sleep(50);
//        events.publishEvent(new InventoryUpdated(id));

        LOG.info("Finished order completion for {}.", id);
    }
}
martyphee commented 5 hours ago

This is exhibiting the behaviour.

events.zip