Работа со Spring Shell и Mongock из Spring Boot | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
C++ Developer. Professional JavaScript Developer. Professional Android Developer. Professional Microservice Architecture React.js Developer JavaScript Developer. Basic PostgreSQL Программист С C++ Developer. Basic Team Lead PHP Developer. Professional Подготовка к сертификации Oracle Java Programmer (OCAJP) Алгоритмы и структуры данных Разработчик IoT C# Developer. Basic Unreal Engine Technical Game Design C# ASP.NET Core разработчик Python Developer. Basic Архитектура и шаблоны проектирования Node.js Developer iOS Developer. Professional Cloud Solution Architecture Kotlin Backend Developer Agile Project Manager Scala-разработчик Symfony Framework iOS Developer. Basic Супер-интенсив Azure Специализация Python Developer
Инфраструктура
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Microservice Architecture Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Специализация Administrator Linux
-24%
Разработчик IoT Мониторинг и логирование: Zabbix, Prometheus, ELK MongoDB
-37%
DevOps практики и инструменты MS SQL Server Developer SRE практики и инструменты Administrator Linux. Advanced Infrastructure as a code Супер-интенсив "Tarantool" Специализация Network engineer
Корпоративные курсы
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Spark Developer Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» Game QA Engineer DevOps практики и инструменты Enterprise Architect Node.js Developer Cloud Solution Architecture Agile Project Manager Супер-практикум по работе с протоколом BGP Infrastructure as a code Промышленный ML на больших данных Супер-интенсив Azure Руководитель поддержки пользователей в IT
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Работа со Spring Shell и Mongock из Spring Boot

Иногда, пытаясь использовать в проекте Spring Boot, одновременно интерфейс командной строки Spring Shell и библиотеку миграции Mongock, разработчики сталкиваются с тем, что запуск миграций не происходит, хотя остальные функции приложения работают в штатном режиме. В частности, это может случиться в процессе выполнения одного из домашних заданий курса по Spring. Почему так происходит, мы и попробуем выяснить в текущей заметке.

Spring Shell

Для начала стоит разобраться, как запускается интерактивный режим Spring Shell. Известно как минимум три способа запуска своей логики в Spring(Boot). А именно: - InitializingBean — у бинов, реализующих данный интерфейс, будет вызван метод afterPropertiesSet после того, как все свойства были установлены. В т. ч. зависимости; - CommandLineRunner— это интерфейс Spring Boot с методом run, который автоматически вызывается фреймворком у всех компонентов, реализующих этот интерфейс, после загрузки контекста приложения. В сам метод run передаются аргументы командной строки в виде массива строк; - ApplicationRunner — то же самое, что CommandLineRunner, но аргументы командной строки представлены в виде объекта ApplicationArguments.

Последние два пункта работают в Spring Boot и выглядят, как основные кандидаты на отправную точку изысканий.

Давайте попробуем начать с того, что проверим, не запускается ли шелл с помощью ApplicationRunner. Если в IDEA дважды нажать на Shift, выставить флаг "Include non-project items" и ввести в строку поиска ApplicationRunner, то можно увидеть, кто еще использует в названии это сочетание слов. Среди найденных классов есть InteractiveShellApplicationRunner, который, по сути, отвечает за запуск интерактивного режима шелл (что следует уже из его названия). Следует обратить внимание, что над данным классом висит @Order(0), а значит он будет запущен раньше, чем ApplicationRunner-ы с более низким приоритетом. Например, те из них, что не имеют над своим классом аннотации @Order, или имеют, но у нее указано значение больше 0 (значение по умолчанию Integer.MAX_VALUE).

Mongock v3

С шеллом вроде разобрались. Настала очередь Mongock-а. У него в третьей версии есть два класса-раннера. А именно: SpringMongock и SpringBootMongock. Первый для запуска миграций использует InitializingBean, второй — ApplicationRunner (этот момент описан в readme.md на странице проекта в гитхабе). Над классом SpringBootMongock не висит аннотации @Order, а значит при использовании в приложении Spring Shell до его запуска просто не дойдет дело. Стало быть, использование SpringMongock должно решить нашу проблему с запуском миграций. Просто объявляем бин нужного типа и все работает.

Mongock v4

В четвертой версии вся конфигурация скрыта от нас в недрах библиотеки. Мы можем настраивать работу с помощью свойств в application.yml и включать/отключать использование миграций аннотацией @EnableMongock. Если перейти в код данной аннотации, то можно увидеть, что она импортирует две конфигурации:

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({MongockConfiguration.class, MongockContext.class})
public @interface EnableMongock {
}

Первая отвечает за загрузку свойств из application.yml, а вот MongockContext для нас будет гораздо интереснее. Вот его код:

@Configuration
@Import(MongockCoreContextSelector.class)
public class MongockContext {

  @Bean
  @ConditionalOnProperty(value = "mongock.runner-type", matchIfMissing = true, havingValue = "ApplicationRunner")
  public MongockSpring5.MongockApplicationRunner mongockApplicationRunner(MongockSpring5.Builder mongockBuilder) {
    return mongockBuilder.buildApplicationRunner();
  }

  @Bean
  @ConditionalOnProperty(value = "mongock.runner-type", havingValue = "InitializingBean")
  public MongockSpring5.MongockInitializingBeanRunner mongockInitializingBeanRunner(MongockSpring5.Builder mongockBuilder) {
    return mongockBuilder.buildInitializingBeanRunner();
  }
}

Т. е. все то же самое, что и в третьей версии. Два раннера, реализующие ApplicationRunner и InitializingBean. Какой из вариантов будет использоваться, зависит от значения свойства "mongock.runner-type". Если оно не указано, то будет создан раннер на основе ApplicationRunner. А значит, проблема интеграции Mongock и Spring Shell может быть решена указанием строки mongock.runner-type="InitializingBean" в настройках приложения.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться