Spring Boot 2.1.0 с Flyway 4.2.0

Я хотел бы обновить свои новые проекты до Spring Boot версии 2.1.0, но я ограничен базой данных Oracle 11, которая поддерживается библиотекой Пролетной путь 4.2.0. В Spring Boot версии 2.0.5 Release все работает нормально, но при переходе на версию 2.1.0 я получаю эту ошибку:

java.lang.NoClassDefFoundError: 
org/flywaydb/core/api/configuration/FluentConfiguration

Конфигурация POM следующая:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.0.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <ojdbc6.version>11.2.0.1</ojdbc6.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.oracle.jdbc</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>${ojdbc6.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
        <version>4.2.0</version>
    </dependency>
</dependencies>

Обновлено

Я могу решить проблему с помощью @Configuration (или, конечно, добавить в основной класс), но дело в том, что это ошибка или функция? До версии 2.1.0 все делалось через автоконфигурацию, и она работала "из коробки".

@Bean(initMethod = "migrate")
Flyway flyway() {
    Flyway flyway = new Flyway();
    flyway.setBaselineOnMigrate(true);
    flyway.setDataSource("jdbc:oracle:thin:@localhost:1521:xe", "USER", "PASSWORD1");
    return flyway;
}

Это вообще не ошибка. Spring Boot зависит от Flyway 5.2.1, API которого отличается от используемой вами старой версии.

JB Nizet 16.11.2018 20:31

Да, заметил, но нельзя ли как-то исключить его в pom.xml в пользу более старого? Я мог найти правильную зависимость, но он искал этот класс FluentConfiguration.

troger19 16.11.2018 20:34

Конечно можно. Но это не изменит код загрузки Spring, который настраивает Flyway и использует новые классы, существующие только в последней версии Flyway. Чтобы провести аналогию, если вы скомпилируете классы, которые используют java.util.stream с Java 8, а затем попытаетесь запустить этот код на Java 7, это не сработает, потому что java.util.stream не существует в Java 7. .

JB Nizet 16.11.2018 20:35

как вам удалось протестировать свое приложение?

Andrew T 03.08.2019 15:32
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
28
4
12 911
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

У меня была такая же проблема с PostgreSQL 9.2, и я использовал следующий класс для решения проблемы.

Однако имейте в виду, что все настраиваемые свойства, которые вы можете установить в свойствах Spring Boot, будут проигнорированы, поскольку это заменяет всю автоконфигурацию Flyway вашей собственной. Так что вам, возможно, придется добавить дополнительный код в соответствии с вашими потребностями.

@Configuration
class FlywayConfig {
    @Bean
    fun flyway(dataSource: DataSource): Flyway {
        val flyway = Flyway()
        flyway.dataSource = dataSource
        return flyway
    }

    @Bean
    fun flywayInitializer(flyway: Flyway): FlywayMigrationInitializer {
        return FlywayMigrationInitializer(flyway, null)
    }

    /**
     * Additional configuration to ensure that [EntityManagerFactory] beans depend on the
     * `flywayInitializer` bean.
     */
    @Configuration
    class FlywayInitializerJpaDependencyConfiguration : EntityManagerFactoryDependsOnPostProcessor("flywayInitializer")
}

PS: это код Kotlin, но вы сможете довольно легко перевести его на Java.

Привет. Да, это именно то, что я пытался сделать, пожалуйста, посмотрите мой комментарий; Произведите конфигурацию программно. Дело в том, что это правильный путь? Почему автоконфигурация была изменена таким образом? И как тогда настроить разные источники данных для разных сред, если я не могу использовать application.properties? Спасибо

troger19 16.11.2018 20:23

Вы можете использовать application.properties. Просто не ожидайте, что свойства flyway будут иметь какой-либо эффект, поскольку Spring Boot больше не будет их читать и применять. Остальные, не связанные с Flyway, по-прежнему будут работать.

JB Nizet 16.11.2018 20:26

Как заставить его работать в тестах Spring Boot? Мне нужно загрузить различные свойства для flyway для тестов, но либо компонент Flyway недоступен, либо когда я создаю bean-компонент Flyway вручную, другие компоненты теряются. Спасибо

troger19 08.12.2018 14:02

@JBNizet Как человек, не знающий Kotlin, все понятно, кроме последней строчки.

Younes El Ouarti 20.07.2020 18:16

@Younes_EO Последняя строка: `@Configuration общедоступный статический класс FlywayInitializerJpaDependencyConfiguration extends EntityManagerFactoryDependsOnPostProcessor {public FlywayInitializerJpaDependencyConfiguration () {super (" flywayInitializer "); }} `

pdem 28.07.2020 18:17

Я сделал конфигурацию для Spring Boot 2.1.1, и мне также пришлось переопределить bean-компонент FlywayDefaultDdlModeProvider.

@Configuration
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
public class LegacyFlywayAutoConfiguration {

    @Bean
    @Primary
    public SchemaManagementProvider flywayDefaultDdlModeProvider(ObjectProvider<Flyway> flyways) {
        return new SchemaManagementProvider() {
            @Override
            public SchemaManagement getSchemaManagement(DataSource dataSource) {
                return SchemaManagement.MANAGED;
            }
        };
    }

    @Bean(initMethod = "migrate")
    public Flyway flyway(DataSource dataSource) {
        Flyway flyway = new Flyway();
        flyway.setBaselineOnMigrate(true);
        flyway.setDataSource(dataSource);
        return flyway;
    }

    @Bean
    public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
        return new FlywayMigrationInitializer(flyway, null);
    }

    /**
     * Additional configuration to ensure that {@link JdbcOperations} beans depend
     * on the {@code flywayInitializer} bean.
     */
    @Configuration
    @ConditionalOnClass(JdbcOperations.class)
    @ConditionalOnBean(JdbcOperations.class)
    protected static class FlywayInitializerJdbcOperationsDependencyConfiguration
            extends JdbcOperationsDependsOnPostProcessor {

        public FlywayInitializerJdbcOperationsDependencyConfiguration() {
            super("flywayInitializer");
        }

    }
}

вы можете использовать его в @SpringBootTest?

troger19 08.12.2018 14:02

Да, сама перезаписанная конфигурация работает с @SpringBootTest. Но обычно ты не понимаешь смысла использовать t want to use Oracle database for integration test, so I don только для теста. Я использую базу данных H2 для @SpringBootTest, и у нее нет проблем с последней версией Flyway. Хотя для совместимости я не создавал собственную конфигурацию Flyway для интеграционного теста.

vargapeti 10.12.2018 08:17

Да, это то, что я хочу сделать, но почему-то не могу придумать правильный путь. Если я включаю application.yml в test / resource, создается экземпляр компонента Flyway Bean, и он создается для версии 5+. Если я где-то помещу @ Configuration или @ TestCOnfiguration, я могу создать его программно, но тогда другие Bean (Daos, Services) будут нулевыми, потому что мне также нужно создать их вручную. Я просто хочу создать Flyway Bean вручную, а все остальное оставлю на Spring.

troger19 10.12.2018 15:09

Пришлось добавить spring.main.allow-bean-definition-overriding=true в application.properties, но он работает!

Ondřej Stašek 18.04.2019 13:56

Используя библиотеку Javassist, вы можете настроить библиотеку FlywayDB для регистрации того, что версия Oracle больше не поддерживается, вместо того, чтобы генерировать фатальное исключение (заключив вызов метода sureDatabaseIsCompatibleWithFlywayEdition в предложение try-catch). В моем случае версия сообщества FlywayDB (5.2.4), похоже, нормально работает с Oracle 11.2, как только я это сделал. У этого решения есть свои недостатки, но в моем случае это был лучший вариант (база данных должна быть обновлена ​​в ближайшее время), так что, возможно, кто-то сочтет это полезным. Приведенный ниже код в идеале должен запускаться в вашем приложении прежде всего. Пожалуйста используйте на свой страх и риск.

public static void suppressIncompatibleDatabaseVersionCheck() {
    try {
        CtClass ctClass = ClassPool.getDefault().get("org.flywaydb.core.internal.database.base.Database");
        ctClass.defrost();
        CtMethod method = ctClass.getDeclaredMethod("ensureDatabaseIsCompatibleWithFlywayEdition");
        CtClass etype = ClassPool.getDefault().get("java.lang.Exception");
        method.addCatch("{ LOG.warn(\"Exception suppressed: \" + $e); return ;}", etype);
        ctClass.toClass();
    } catch (NotFoundException | CannotCompileException e) {
        log.error("Could not instrument FlywayDB code.", e);
    }
}

Используйте следующую зависимость, этим она будет решена.

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
    <version>5.2.3</version>
</dependency>

Как я уже упоминал в вопросе, я не могу использовать более высокую версию flyway, чем 4.2.0, из-за неподдерживаемого Oracle 11

troger19 25.09.2019 12:45

То же самое для меня не могу использовать более высокую версию flyway, если вы не скажете, что flyway-core 5 совместим с ojdbc6 11 и oracle 11 (что не так)

pdem 31.07.2020 15:58

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