Skip to content

fix: stop WireMock servers when context closes during AOT processing - #200

Merged
tomasbjerre merged 1 commit into
wiremock:mainfrom
moyis:fix/stop-wiremock-on-aot-processing
Jul 13, 2026
Merged

fix: stop WireMock servers when context closes during AOT processing#200
tomasbjerre merged 1 commit into
wiremock:mainfrom
moyis:fix/stop-wiremock-on-aot-processing

Conversation

@moyis

@moyis moyis commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #199

Problem

When a @SpringBootTest class uses @EnableWireMock, Gradle's processTestAot (SpringBootTestAotProcessor) hangs forever. During test AOT processing, the test application context is loaded and closed outside the JUnit lifecycle:

  • TestContextAotGenerator loads the context via refreshForAotProcessing(), which runs prepareRefresh() but never initializes the application event multicaster.
  • When the generator closes the context (try-with-resources), doClose() publishes the ContextClosedEvent into the still-active earlyApplicationEvents set, so it is never delivered.
  • The library's only shutdown hook was an ApplicationListener<ContextClosedEvent>, so the WireMock servers were never stopped and their non-daemon Jetty qtp* threads kept the AOT processing JVM alive after main() returned. Gradle waits on the forked process forever.

Fix

doClose() still destroys singletons even in that path, so each started server is now also registered as a disposable bean in the singleton registry. The existing ContextClosedEvent listener is kept for the regular lifecycle, and both paths route through a single stop method guarded by server.isRunning(), so the server is never stopped twice.

An alternative considered was skipping server startup entirely when running under AOT processing (spring.aot.processing property). Rejected: it would require faking the injected base URL/port properties so context loading still succeeds, and it makes the AOT pass behave differently from a regular context load. Stopping the servers when the context that started them is closed fixes the root cause without behavior divergence.

Testing

  • New regression test AotProcessingTest runs TestContextAotGenerator.processAheadOfTime() against an @EnableWireMock test class — the same context load + close as SpringBootTestAotProcessor, outside JUnit's SpringExtension — and asserts no new non-daemon qtp* Jetty threads survive the context close. Fails without the fix, passes with it.
  • Full ./gradlew build green.
  • Verified end-to-end against the reproducer from WireMock servers are never stopped during Spring test AOT processing, hanging processTestAot forever #199 (https://github.com/moyis/wiremock-aot-bug, Spring Boot 4.1.0, JDK 25): with the released 4.2.1 the AOT processor JVM stays alive indefinitely (jstack shows the WireMock Jetty qtp* threads); with this patch ./gradlew processTestAot completes in seconds — the log shows Jetty shutting down when the AOT context is closed.

@moyis
moyis force-pushed the fix/stop-wiremock-on-aot-processing branch from b9ad4ba to 8aea333 Compare July 13, 2026 16:59
During Spring test AOT processing (SpringBootTestAotProcessor), the test
application context is loaded and closed outside the JUnit lifecycle.
The ContextClosedEvent is never delivered in that case (the event
multicaster is not initialized by refreshForAotProcessing), so the
WireMock servers were never stopped and their non-daemon Jetty threads
kept the AOT processing JVM alive forever, hanging processTestAot.

Singletons are still destroyed when that context is closed, so each
started server is now also registered as a disposable bean. The existing
ContextClosedEvent listener is kept, and both paths are guarded against
double-stop.

Fixes wiremock#199
@moyis
moyis force-pushed the fix/stop-wiremock-on-aot-processing branch from 8aea333 to 9aa48c3 Compare July 13, 2026 17:00
@tomasbjerre
tomasbjerre merged commit 4ebf879 into wiremock:main Jul 13, 2026
2 checks passed
@tomasbjerre

Copy link
Copy Markdown
Collaborator

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WireMock servers are never stopped during Spring test AOT processing, hanging processTestAot forever

2 participants