How to shut down a Spring Boot command-line application
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
A Spring Boot command-line application does not need a special shutdown API in every case. If it is a non-web application and your startup runner finishes with no non-daemon threads left alive, the JVM will exit naturally. Explicit shutdown becomes necessary when you keep the application context around, start background work, or want to return a controlled exit code.
Let a Simple CLI App End Naturally
For a one-shot command-line tool, the cleanest design is usually to run the work inside a CommandLineRunner or ApplicationRunner and then let the process end.
If the run method finishes and you have not started extra threads, the application usually terminates on its own. That is the simplest and most Spring-friendly outcome.
Use SpringApplication.exit for an Explicit Shutdown
If you need to stop the context programmatically, hold onto the ConfigurableApplicationContext and pass it to SpringApplication.exit.
SpringApplication.exit closes the Spring context and triggers bean destruction callbacks. System.exit then ends the JVM with the chosen status code.
Use this pattern when your CLI tool needs a reliable process exit code for shell scripts, CI jobs, or operating-system schedulers.
Shut Down From Inside a Runner or Service
Sometimes the application decides during execution that it should stop, for example after completing a batch job or detecting an unrecoverable condition.
This is a reasonable choice for short-lived job-style applications. The important detail is to close the Spring context first so lifecycle callbacks run cleanly.
Clean Up Resources During Shutdown
A proper shutdown is not only about ending the JVM. It is also about closing resources such as thread pools, database connections, and messaging clients.
Spring gives you several hooks:
- '
@PreDestroy' - '
DisposableBean' - custom
destroyMethod
Example:
If you skip orderly cleanup and call Runtime.getRuntime().halt(...) or force termination too early, you can leave files half-written or lose data in transit.
Watch for Threads That Keep the JVM Alive
Many “Spring Boot will not shut down” cases are not really Spring problems. The application context closes, but some non-daemon thread keeps the JVM running. Common causes include:
- custom
ExecutorServiceinstances - scheduler threads
- messaging consumers
- infinite loops in background workers
If your command-line app should be short-lived, audit every thread you start and make sure it is shut down or awaited properly.
Pick the Right Exit-Code Strategy
If the application participates in automation, exit codes matter. A zero exit code usually means success, while non-zero values signal failure to the caller.
Spring supports custom exit-code generators so you can translate business outcomes into process status codes cleanly instead of scattering System.exit(1) calls across the codebase.
Common Pitfalls
A common mistake is calling System.exit without first closing the Spring context. That skips orderly bean shutdown and can leak work.
Another issue is assuming the app will terminate automatically while custom executors or scheduled tasks are still running. In that case, the context may finish but the JVM stays alive.
Developers also sometimes build a command-line application without disabling web mode. If Boot starts an embedded server, the process behaves like a long-running application by design.
Finally, do not overcomplicate short-lived CLI tools. If the runner finishes and no extra threads remain, natural JVM termination is usually the best shutdown mechanism.
Summary
- A non-web Spring Boot CLI app often exits naturally when its runner completes.
- Use
WebApplicationType.NONEfor true command-line behavior. - Call
SpringApplication.exit(context)beforeSystem.exit(code)when you need explicit shutdown and exit codes. - Close resources through Spring lifecycle hooks such as
@PreDestroy. - If the process stays alive unexpectedly, look for non-daemon threads rather than assuming Spring itself failed to stop.
Related reading
- How to shutdown a Spring Boot Application in a correct way?
- How to simplify a null-safe compareTo implementation?
- How to skip corrupt (non-serializable) messages in Spring Kafka Consumer?
- How to skip weekends while adding days to LocalDate in Java 8?
- How to Solve 403 Error in Spring Boot Post Request
- How to solve deprecation warning of JobBuilderFactory and StepBuilderFactory
- How to solve InaccessibleObjectException Unable to make member accessible module A does not 'opens package' to B on Java 9?
- How to solve Plugin execution not covered by lifecycle configuration for Spring Data Maven Builds

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.