I'm using the code from here to restart my Spring Boot application:
Thread restartThread = new Thread(() -> restartEndpoint.restart());
restartThread.setDaemon(false);
restartThread.start();
However, the restarted application fails to create beans, ultimately due to a RejectedExecutionException
thrown when trying to schedule @Scheduled
-annotated methods:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean' defined in URL [insert-path-here]: Initializetion of bean failed; nested exception is org.springframework.core.TaskRejectedException: Executor [java.util.concurrent.ScheduledThreadPoolExecutor@284a4a89[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 21508]] did not accept task: my.package.MyBean.scheduledMethod
The logs immediately after the Embarrassingly enough, it turns out that doRestart()
invocation indicate that the ExecutorService taskScheduler
is being shut down, which would explain why this is happening. What I'm not entirely sure of is why the ExecutorService isn't recreated.taskScheduler
was a bean defined by my application and was not annotated @RefreshScope
. Now the error I'm getting is
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'anotherBean' definen in URL[...]: Unsatisfied dependency expressed through constructor parameter 0 ... nested exception is java.lang.IllegalStateException: org.springframework.boot.servlet.context.AnnotationConfigServletWebServerApplicationContext@2a95076c has been closed already
Scrolling up a bit in the logs reveals that there's an ApplicationContextException
thrown with the stacktrace containing doRestart
:
org.springframework.ApplicationContextException: Unable to start web server; nested exception is java.lang.IllegalStateException: Filters cannot be added to context [/myapp] as the context has been initialized
at org.springframework.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:157)
...
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.cloud.context.restart.RestartEndpoint(RestartEndpoint.java:160)
at my.package.MyBean.lambda$doThingAndRestart$2 (MyBean.java: 118)
Googling this error seems to result in a single page that isn't relevant, although I do note that this application is running on tomcat as well.
I suspect that this is related to the application creating a wrong sort of application context, which is a AnnotationConfigServletWebServerApplicationContext
, which doesn't extend AbstractRefreshableAplicationContext.
What do I need to do to get rid of this error?
Please bear with me when I only copy single lines from the stack trace. I'm on a two-computer set-up, so I can't copy-and paste and am no allowed to otherwise move the logs to a computer connected to the Internet.
It turns out that RestartEndpoint
only works with Spring's internal Tomcat, not an external one. So, another solution is required. The ones I discovered are
doThingAndRestart
functionality.reload
request blocks until the app is done reloading, which overflowed the heap space.