Нет Spring ServletWebServerFactory при исключении встроенных классов MongoDB

У меня есть типичный сервер REST Spring Boot:

…

@SpringBootApplication
public class MyService {

  public static void main(String[] args) {
    SpringApplication.run(MyService.class, args);
  }
}

Я включаю org.springframework.boot:spring-boot-starter-web вместе с de.flapdoodle.embed:de.flapdoodle.embed.mongo.spring30x, чтобы встроить MongoDB для тестирования и запуска в среде IDE. Это приложение запускается нормально из полученного JAR-файла.

Однако я хочу отключить автоматическую настройку встроенного сервера MongoDB; вместо этого я хочу включить его только для определенных профилей. Мой первый шаг — исключить EmbeddedMongoAutoConfiguration:

…

import de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration;

@SpringBootApplication(exclude = {EmbeddedMongoAutoConfiguration.class})
public class MyService {

  public static void main(String[] args) {
    SpringApplication.run(MyService.class, args);
  }
}

Пока все хорошо — приложение все еще работает. Теперь я хочу убедиться, что встроенные классы MongoDB не будут распространяться вместе с приложением, потому что я планирую включить только EmbeddedMongoAutoConfiguration в IDE (на основе профиля). Поэтому я обновляю свой POM следующим образом:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <excludeGroupIds>de.flapdoodle,de.flapdoodle.embed,de.flapdoodle.graph,
            de.flapdoodle.java8,de.flapdoodle.reverse</excludeGroupIds>
      </configuration>
    </execution>
  </executions>
</plugin>

Внезапно приложение больше не запускается, говоря:

***************************
APPLICATION FAILED TO START
***************************

Description:

Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.

Action:

Check your application's dependencies for a supported servlet web server.
Check the configured web application type.

Почему исключение неиспользуемых файлов классов не позволяет приложению определить ServletWebServerFactory?

Я предполагаю, что когда я укажу @SpringBootApplication(exclude = {EmbeddedMongoAutoConfiguration.class}), Spring запутается, если класс EmbeddedMongoAutoConfiguration отсутствует. Вместо того, чтобы думать: «Эй, класс даже не существует, поэтому мне не нужно ничего делать, чтобы его исключить», Spring вместо этого думает: «Я хочу исключить этот класс, но его даже нет, поэтому я не не знаю, что делать!" И вместо того, чтобы выдать ошибку и сказать «Я не могу создать приложение», он просто не создает необходимые bean-компоненты и оставляет это на потом, чтобы приложение могло сказать: «Ой, у меня нет ServletWebServerFactory и я понятия не имею, почему бы и нет».

Кто-нибудь знает способ, которым я могу динамически исключать EmbeddedMongoAutoConfiguration таким образом, чтобы это не путало Spring, если EmbeddedMongoAutoConfiguration на самом деле даже не присутствует в дистрибутиве?

Используйте String с именем класса вместо жесткого кодирования класса таким образом. Использование строки делает ее динамической, жесткое кодирование делает ее обязательной. Для этого используйте excludeName вместо exclude.

M. Deinum 18.04.2023 20:27

Замечательный! Я сделаю больше тестов, но на данный момент это, похоже, сработало! @M.Deinum M.Deinum, если вы хотите добавить это как ответ, я могу пометить его как правильный. Кстати, excludeName поддерживает подстановочные знаки? Просто любопытно.

Garret Wilson 18.04.2023 23:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
2
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы проверите javadoc для @SpringBootApplication, вы увидите exclude и excludeName. Первый принимает массив классов, второй — массив String. Первый из-за классов будет автоматически пытаться загрузить класс, так как он является частью байткода (из-за импорта), второй будет делать это лениво.

В вашем случае вы хотите excludeName вместо exclude. excludeName принимает полное имя класса, который вы хотите исключить.

@SpringBootApplication(excludeName = "de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration"})

Будет делать свое дело.

Кажется, это работает. Большое спасибо! Я обновил свою запись в блоге Embedded MongoDB только в IDE с использованием Spring Boot 3.x этой информацией. Очень признателен.

Garret Wilson 19.04.2023 16:18

Другие вопросы по теме