Skip to content

Commit c87510e

Browse files
mvysnyclaude
andcommitted
Document shutdown semantics in README
The Enter / Ctrl+C / SIGTERM behavior was only described indirectly as a test scenario in CONTRIBUTING.md. Add a "Shutting down" subsection under "Running your apps" that covers: - What run() actually does (block on stdin + shutdown hook). - Which launch methods give you clean contextDestroyed firing (IDE main, mvnw exec:java, unzipped prod zip, systemd, docker stop) vs. which may force-kill (gradle run, docker kill, SIGKILL). - The start()/stop() escape hatch for tests that want to drive the lifecycle themselves. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7b41a71 commit c87510e

1 file changed

Lines changed: 24 additions & 0 deletions

File tree

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,30 @@ When deploying your app to production: see the "Production" chapter below. In sh
201201
1. Build your app in production mode, via `./gradlew clean build -Pvaadin.productionMode` or `./mvnw -C clean package -Pproduction`.
202202
2. The build of your app should produce a zip file; unzip the file and launch the run script.
203203

204+
### Shutting down
205+
206+
`VaadinBoot.run()` blocks until either **Enter** is pressed on stdin or the JVM
207+
receives a shutdown signal (SIGINT/SIGTERM — Ctrl+C, `docker stop`,
208+
`systemctl stop`). Both paths converge on `stop()`, which waits for the web
209+
server to shut down and fires `@WebListener.contextDestroyed` on your context
210+
listeners.
211+
212+
What actually works depends on how the app was launched:
213+
214+
- **IDE `main()`, `./mvnw exec:java`, unzipped production zip** — both Enter
215+
and Ctrl+C work cleanly.
216+
- **`./gradlew run`** — no stdin, so Enter doesn't work. Ctrl+C exits the
217+
process, but Gradle may force-kill before the JVM shutdown hook runs, so
218+
`contextDestroyed` isn't guaranteed to fire. For a clean-shutdown check,
219+
run the unzipped production zip instead.
220+
- **Docker / systemd / `nohup` (no TTY)** — no stdin; `run()` blocks on the
221+
web server. A clean `docker stop` or `systemctl stop` sends SIGTERM, the
222+
shutdown hook runs, and `contextDestroyed` fires normally. `SIGKILL`
223+
(`docker kill`, `systemctl kill -s SIGKILL`) bypasses hooks.
224+
225+
If you want to drive the lifecycle yourself (e.g. from a test), use
226+
`VaadinBoot.start()` / `stop(reason)` directly instead of `run()`.
227+
204228
## Develop with pleasure
205229

206230
We recommend to develop Vaadin Boot apps using an IDE instead of just a plain text editor.

0 commit comments

Comments
 (0)