Как правильно перезапустить загрузочное приложение Spring? - PullRequest
0 голосов
/ 24 января 2019

Я использую код здесь , чтобы перезапустить приложение Spring Boot:

Thread restartThread = new Thread(() -> restartEndpoint.restart());
restartThread.setDaemon(false);
restartThread.start();

Однако перезапущенному приложению не удается создать bean-компоненты, в конечном итоге из-за RejectedExecutionException, генерируемого при попытке запланировать @Scheduled -аннотированные методы:

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

Журналы сразу после вызова doRestart() указывают, что ExecutorService taskScheduler закрывается, что объясняет, почему это происходит. В чем я не совсем уверен, так это в том, что ExecutorService не воссоздан. Довольно неловко, оказывается, что taskScheduler был компонентом, определенным моим приложением и не был аннотирован @RefreshScope. Теперь я получаю ошибку

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

Немного прокручивая в журналах, вы обнаружите, что выдается ApplicationContextException с трассировкой стека, содержащей 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)

Похоже, что поиск этой ошибки приводит к одной странице , которая не имеет отношения к делу, хотя я отмечаю, что это приложение также работает на tomcat.

Я подозреваю, что это связано с тем, что приложение создает неправильный вид контекста приложения, то есть AnnotationConfigServletWebServerApplicationContext, который не расширяет AbstractRefreshableAplicationContext .

Что мне нужно сделать, чтобы избавиться от этой ошибки?

Пожалуйста, потерпите меня, когда я копирую только одну строку из трассировки стека. Я нахожусь на установке с двумя компьютерами, поэтому я не могу копировать и вставлять, и мне запрещено перемещать журналы на компьютер, подключенный к Интернету.

1 Ответ

0 голосов
/ 22 февраля 2019

Оказывается, что RestartEndpoint работает только с внутренним Tomcat Spring, а не с внешним. Итак, другое решение не требуется. Те, что я обнаружил,

  • Использование Tomcat WatchedResource для повторного развертывания сервера при перезаписи файла конфигурации. Это имеет обратную сторону необходимости поддерживать конфигурацию Tomcat при поддержке функциональности doThingAndRestart.
  • Использование Tomcat Manager App . Я заметил, что запрос reload блокируется до тех пор, пока приложение не перезагрузится, что привело к переполнению пространства кучи.
  • Использование Spring RefreshEndpoint . По какой-то причине это не обновило источники данных.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...