Programmatically shut down Spring Boot application
Closing a SpringApplication
basically means closing the underlying ApplicationContext
. The SpringApplication#run(String...)
method gives you that ApplicationContext
as a ConfigurableApplicationContext
. You can then close()
it yourself.
For example,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to shut down...
ctx.close();
}
}
Alternatively, you can use the static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
helper method to do it for you. For example,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to stop...
int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
// no errors
return 0;
}
});
// or shortened to
// int exitCode = SpringApplication.exit(ctx, () -> 0);
System.exit(exitCode);
}
}
How to shut down a Spring Boot command-line application
The answer depends on what it is that is still doing work. You can probably find out with a thread dump (eg using jstack). But if it is anything that was started by Spring you should be able to use ConfigurableApplicationContext.close()
to stop the app in your main() method (or in the CommandLineRunner
).
How to gracefully shutdown the spring boot application
Ultimately the spring boot application spins off a java process which needs to be killed. At present you are killing it manually.
You have a few options:
- You can use
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
method. - If your application is not a long running application then do you have some exit point where your application should stop. At that point you can
System.exit(0)
- You can use external manager tools, for example on unix you can use supervisor, here is a blog you can read about this.
SpringApplication.run
gives youApplicationContext
which you can close.
how to close the application during startup in spring boot
We have a lot of options to shutdown spring-boot application:
Shutdown rest endpoint - add below properites to your application.properties and fire following request curl -X POST localhost:port/actuator/shutdown
management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
endpoints.shutdown.enabled=true
Also you can call suitable method to shutdown application:
- By calling method
close()
onConfigurableApplicationContext
object (it will close application context) - By passing exit code to method
SpringApplication.exit(ctx, () -> 0);
Please check this article for more details.
Is it possible to get a list of service that dynamically get down on my application that is on spring boot
Spring Boot actuator provides a lot of useful endpoints, one of which is the health endpoint. The health endpoint returns the health status of your application based on its dependencies (databases, third party APIs, ...).
There are already builtin health indicators for RabbitMQ, Hazelcast and Elastic. There is no builtin health indicator for DynamoDB as far as I know, but you can also write your own health indicator, as seen in this question.
Now, to send you an email there are a two options:
- You can use an external program (eg. monitoring software) to regularly check the health actuator
- You can write it as part of your Spring boot application
Using an external program
If you use an external program, you can make it consume the /actuator/health
endpoint. To enable this endpoint, configure the following property:
management.endpoints.web.exposure.include=health
By default this endpoint only exposes a single aggregated status of all health indicators combined. If you want to individually see which service is down, you can show more details by setting the following property to always
or when_authorized
:
management.endpoint.health.show-details=always | when_authorized
The response will look something like this:
{
"status": "DOWN",
"rabbit": {
"status": "DOWN",
"error": "org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused (Connection refused)"
}
}
Writing your own
You can write a scheduled task by using the @Scheduled
annotation to regularly check the health status. To obtain the health status, you can autowire HealthEndpoint
as seen in this question.
Then you can send an email with Spring.
@Component
public class HealthEmailSender {
private final HealthEndpoint healthEndpoint;
private final JavaMailSender mailSender;
// TODO: Implement constructor to autowire healthEndpoint + mailSender
@Scheduled(fixedRate = 10 * 60 * 1000) // Check once every 10 minutes
public void sendEmailWhenBadHealth() {
if (isHealthDown()) {
sendMail();
}
}
private boolean isHealthDown() {
return Status.DOWN.equals(healthEndpoint.health().getStatus());
}
private void sendMail() {
MimeMessage message = mailsender.createMimeMessage();
// TODO: Set from / to / title / content
mailSender.send(message);
}
}
This code snippet above would send an e-mail as soon as any health indicator goes down (not only from the services you mentioned).
To obtain the health status of one of the services you're interested in, you can use healthEndpoint.healthForPath("rabbit").getStatus()
.
Related Topics
Jpa: What Is the Proper Pattern for Iterating Over Large Result Sets
What Does Class<> Mean in Java
Default Fetch Type for One-To-One, Many-To-One and One-To-Many in Hibernate
Difference Between One-To-Many, Many-To-One and Many-To-Many
How to Convert/Parse from String to Char in Java
Inter Thread Communication in Java
Java.Sql.Sqlexception: Incorrect String Value: '\Xf0\X9F\X91\Xbd\Xf0\X9F...'
Arrays.Aslist(Int[]) Not Working
Random "Element Is No Longer Attached to the Dom" Staleelementreferenceexception
Java.Lang.Noclassdeffounderror: Could Not Initialize Class Xxx
Why Are the Level.Fine Logging Messages Not Showing
Ejb 3.1 @Localbean VS No Annotation
Meaning of Delta or Epsilon Argument of Assertequals for Double Values
Using Spring 3 Autowire in a Standalone Java Application
Is It Not Possible to Have a Code in the Background Who Will Be Called Every 24H