0

I have a Spring Boot app, that runs on a ec2 server. I do not expect any critical error, however, I would like to secure the app from a total halt. For example, if OutOfMemory is thrown, JVM stops and I'm not aware of it.

Is there a way to configure the app/server in such a way, that if any critical error occurs it is automatically restarted? Thanks in advance.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
void
  • 731
  • 2
  • 11
  • 26
  • There is the option to exit JVM on OutOfMemory exception: http://stackoverflow.com/a/3878199/1179948. And then you maybe can configure AWS to monitor you JVM process and restart it, if it is killed. – Igor Bljahhin Feb 27 '17 at 08:41

2 Answers2

2

You can add a couple of dependencies to your application:

  • Spring-boot-starter-actuator: This exposes a lot of endpoints to check the App status, logs, get thread dumps etc.
  • spring-cloud-context: This contains RestartEndpoint which you can autowire into your application, and expose an API endpoint to restart the application.

Once done, you can use any HTTP monitoring tool (like Spring Admin) to monitor the apps and restart if/when needed.

Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102
1

You could do something like:

public static void main(String... args) throws Exception {
    while(true){
        try(ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args)) {
            CompletableFuture<Throwable> throwableFuture = new CompletableFuture<>();
            Thread.setDefaultUncaughtExceptionHandler(
                    (thread, throwable) -> throwableFuture.completeExceptionally(throwable));
            throwableFuture.get();
        } catch (Exception | VirtualMachineError t) {
            //log error
        }
    }
}

This will wait for any threads to throw an uncaught exception.
The try-with-resources statement will close the context and cleanup any resources associated with it.
The while loop will then recreate the context.

You will need to make sure that any resources you create(like thread factories) and being properly disposed of when the context closes, otherwise you will still run out of memory.

A better approach would be to have your java service restarted by an external service manager like systemd.

Magnus
  • 7,952
  • 2
  • 26
  • 52
  • How could you limit this approach to the type of the exception, e.g. only exit when say `ClassCastException` occurs? – Hasan Can Saral Jul 03 '19 at 12:19
  • @HasanCanSaral Instead of using CompletableFuture, you could create an ArrayBlockingQueue, have the handler add thowables into the queue, have a loop that calls `take()` on the queue, and check the type of the throwable, only rethrowing/exiting if it's the type you expect. – Magnus Jul 03 '19 at 13:00
  • Actually this doesn't work at all. The defaultExceptionHandler is never getting fired, as for this reason: https://stackoverflow.com/questions/35564177/thread-setdefaultuncaughtexceptionhandler-not-being-called-in-spring-boot-applic Looking for a workaround, as the exception I am trying to handle doesn't occur in controller context. – Hasan Can Saral Jul 03 '19 at 13:15