新しいプロジェクトをSpring Bootバージョン2.1.0にアップグレードしたいのですが、Flyway 4.2.ライブラリでサポートされているOracle 11データベースに制限されています。 Spring Bootバージョン2.0.5リリースではすべてが正常に動作しますが、2.1.リリースに移行するとこのエラーが発生します。
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;
}
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にかなり簡単に変換できるはずです。
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");
}
}
}
Javassistライブラリを使用すると、FlywayDBライブラリをインスツルメントして、致命的な例外をスローする代わりにOracleバージョンがサポートされなくなったことをログに記録できます(try-catch句でensureDatabaseIsCompatibleWithFlywayEditionメソッド呼び出しをラップすることにより)。私の場合、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>