Files
spring-boot-demo/core-events
Claude d6b76c57db Add core-events module: @EventListener, @TransactionalEventListener phases and async listeners on Boot 4.1
Thirteen captured transcripts: a listener is a blocking method call, ordering and chaining, SpEL conditions,
generic-event erasure, every transaction phase on commit and rollback, what an AFTER_COMMIT listener can
write, which exceptions reach the publisher, async listeners on platform and virtual threads, and the
annotations behind Spring Modulith's @ApplicationModuleListener.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uu7q8vPeREyT4218EJPzz1
2026-09-24 07:08:47 +00:00
..

core-events

Companion project for the article Spring Application Events: @EventListener, @TransactionalEventListener and Async Events on ankurm.com.

Every console block quoted in the article came out of output/. Transcripts 01-11 are written by the test suite (so a claim that stops being true turns the build red); 12-13 are read out of jars by scripts/capture-facts.sh.

There is deliberately no docs/ folder: the deeper material lives in collapsible "going deeper" sections inside the article itself, next to the paragraph each one extends.

Versions

Spring Boot 4.1.1
Spring Framework 7.0.9
JDK 25 (Temurin 25.0.4.1+1)
Maven 3.9
H2 the version Boot 4.1.1 manages
Spring Modulith (javap only) 2.1.1

Quickstart

export JAVA_HOME=/path/to/jdk-25
mvn test                  # runs the scenarios and rewrites output/01-11
./scripts/run-all.sh      # everything, including 12-13 (needs network access to Maven Central once)

Source layout

Each scenario is its own package with its own @SpringBootApplication, which scans only that package, so a scenario starts with exactly the beans it shows and nothing else.

Package What it holds
basics/ OrderService publishes an OrderPlaced record; two listeners; the publisher blocks
ordering/ @Order across two beans, an event returned from a listener, a listener that throws
conditional/, badcondition/ SpEL conditions, and one that names a property that does not exist
generics/ Created<T> and its erasure problem, and ResolvableTypeProvider
tx/ one listener per transaction phase, a publisher that commits or rolls back, fallbackExecution
txwrite/ an AFTER_COMMIT listener that writes: nothing declared, REQUIRES_NEW, plain @Transactional
asyncdemo/ @Async listeners, the thread they land on, and what they see of the publisher's transaction
asyncplain/ the same @Async listener in an application that forgot @EnableAsync
support/ Trace (the in-memory log the tests print), Modes, and Visibility (asks "could another connection see this row?")

Captured output

File What it shows
01-publish-is-a-method-call.txt a listener runs on the publisher's thread, before publishEvent returns
02-order-and-chaining.txt @Order across beans, an event returned from a listener, and a throwing listener stopping the rest
03-conditional-listeners.txt which SpEL-conditioned listeners ran for four events; the failure for a misspelled property
04-generic-events-and-erasure.txt a generic event that reaches no listener, and the ResolvableTypeProvider fix
05-transaction-phases-commit-and-rollback.txt every phase for a commit and for a rollback, with row visibility from another connection
06-no-transaction-drops-the-event.txt publishing outside a transaction, and fallbackExecution
07-after-commit-writes.txt an AFTER_COMMIT listener that inserts, declared three ways
08-exceptions-and-transactions.txt which listener's exception reaches the caller, and what it does to the row
09-async-listener-threads.txt an @Async listener on a platform thread, on a virtual thread, and with @EnableAsync forgotten
10-async-and-the-transaction.txt what an async listener can see of the publisher's transaction
11-async-exceptions.txt an async listener's exception: not the publisher's problem, but logged
12-modulith-application-module-listener.txt the annotations @ApplicationModuleListener is made of
13-transaction-cleanup-calls.txt the calls DataSourceTransactionManager makes when it cleans up