diff --git a/flyway/src/main/java/io/micronaut/flyway/DataSourceMigrationRunner.java b/flyway/src/main/java/io/micronaut/flyway/DataSourceMigrationRunner.java index 0af20f89..79dc3350 100644 --- a/flyway/src/main/java/io/micronaut/flyway/DataSourceMigrationRunner.java +++ b/flyway/src/main/java/io/micronaut/flyway/DataSourceMigrationRunner.java @@ -56,15 +56,16 @@ public DataSourceMigrationRunner(ApplicationContext applicationContext, @Override public DataSource onCreated(BeanCreatedEvent event) { DataSource dataSource = event.getBean(); - if (event.getBeanDefinition() instanceof NameResolver) { - ((NameResolver) event.getBeanDefinition()) - .resolveName() - .flatMap(name -> applicationContext.findBean(FlywayConfigurationProperties.class, Qualifiers.byName(name))) - .ifPresent(flywayConfig -> { - DataSource unwrappedDataSource = dataSourceResolver.resolve(dataSource); - run(flywayConfig, unwrappedDataSource); - }); - } + event.getBeanDefinition().getBeanName() + .ifPresent(name -> runMigration(name, dataSource)); return dataSource; } + + private void runMigration(String name, DataSource dataSource) { + applicationContext.findBean(FlywayConfigurationProperties.class, Qualifiers.byName(name)) + .ifPresent(flywayConfig -> { + DataSource unwrappedDataSource = dataSourceResolver.resolve(dataSource); + run(flywayConfig, unwrappedDataSource); + }); + } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a88ca43..679e0814 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ micronaut-test = "4.4.0" micronaut-serde = "2.12.0" micronaut-sql = "6.0.2" micronaut-test-resources="2.6.2" - +micronaut-data = "4.9.6" micronaut-gradle-plugin = "4.4.4" managed-flyway = "10.21.0" @@ -20,7 +20,7 @@ spock = "2.3-groovy-4.0" [libraries] # Core micronaut-core = { module = 'io.micronaut:micronaut-core-bom', version.ref = 'micronaut' } - +micronaut-data = { module = "io.micronaut.data:micronaut-data-bom", version.ref = "micronaut-data" } managed-flyway = { module = "org.flywaydb:flyway-core", version.ref = "managed-flyway" } managed-flyway-mysql = { module = "org.flywaydb:flyway-mysql", version.ref = "managed-flyway" } managed-flyway-sqlserver = { module = "org.flywaydb:flyway-sqlserver", version.ref = "managed-flyway" } diff --git a/settings.gradle b/settings.gradle index bf66c853..eefda86e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,6 +14,7 @@ rootProject.name = 'flyway-parent' include 'flyway' include 'flyway-bom' include 'test-suite-java' +include 'test-suite-manual-datasource' include 'test-suite-serde' enableFeaturePreview('TYPESAFE_PROJECT_ACCESSORS') @@ -22,6 +23,7 @@ micronautBuild { useStandardizedProjectNames = true importMicronautCatalog() + importMicronautCatalog("micronaut-data") importMicronautCatalog("micronaut-serde") importMicronautCatalog("micronaut-sql") importMicronautCatalog("micronaut-test-resources") diff --git a/test-suite-manual-datasource/build.gradle.kts b/test-suite-manual-datasource/build.gradle.kts new file mode 100644 index 00000000..6c860a62 --- /dev/null +++ b/test-suite-manual-datasource/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + id("io.micronaut.build.internal.flyway-base") + `java-library` +} + +description = "Test suite for Flyway + Manual DataSource Configuration" + +dependencies { + annotationProcessor(mn.micronaut.inject.java) + annotationProcessor(mnData.micronaut.data.processor) + implementation(mnData.micronaut.data.jdbc) + implementation(mn.micronaut.http.server.netty) + implementation(projects.micronautFlyway) + implementation(mnSql.hikaricp) + annotationProcessor(mnSerde.micronaut.serde.processor) + implementation(mnSerde.micronaut.serde.jackson) + runtimeOnly(mnLogging.logback.classic) + runtimeOnly(mnSql.h2) + + testAnnotationProcessor(mn.micronaut.inject.java) + testImplementation(mnTest.micronaut.test.junit5) + testImplementation(mn.micronaut.http.client) + testRuntimeOnly(mnTest.junit.jupiter.engine) +} +tasks.withType { + useJUnitPlatform() +} \ No newline at end of file diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/Book.java b/test-suite-manual-datasource/src/main/java/example/micronaut/Book.java new file mode 100644 index 00000000..5fea595d --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/Book.java @@ -0,0 +1,16 @@ +package example.micronaut; + +import io.micronaut.data.annotation.GeneratedValue; +import io.micronaut.data.annotation.Id; +import io.micronaut.data.annotation.MappedEntity; +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +@MappedEntity +public record Book( + @GeneratedValue + @Id Long id, + String title +) { + +} diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/BookController.java b/test-suite-manual-datasource/src/main/java/example/micronaut/BookController.java new file mode 100644 index 00000000..abfc0125 --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/BookController.java @@ -0,0 +1,37 @@ +package example.micronaut; + +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; + +import java.util.ArrayList; +import java.util.List; + +@Controller("/books") +class BookController { + private final MicronautBookRepository micronautBookRepository; + private final GrailsBookRepository grailsBookRepository; + + BookController(MicronautBookRepository micronautBookRepository, + GrailsBookRepository grailsBookRepository) { + this.micronautBookRepository = micronautBookRepository; + this.grailsBookRepository = grailsBookRepository; + } + + @Get + List all() { + List all = new ArrayList<>(); + all.addAll(micronaut()); + all.addAll(grails()); + return all; + } + + @Get("/micronaut") + List micronaut() { + return micronautBookRepository.findAll(); + } + + @Get("/grails") + List grails() { + return grailsBookRepository.findAll(); + } +} diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/BookRepository.java b/test-suite-manual-datasource/src/main/java/example/micronaut/BookRepository.java new file mode 100644 index 00000000..39ca0098 --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/BookRepository.java @@ -0,0 +1,6 @@ +package example.micronaut; + +import io.micronaut.data.repository.CrudRepository; + +public interface BookRepository extends CrudRepository { +} diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/DatasourceFactory.java b/test-suite-manual-datasource/src/main/java/example/micronaut/DatasourceFactory.java new file mode 100644 index 00000000..b2d74500 --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/DatasourceFactory.java @@ -0,0 +1,37 @@ +package example.micronaut; + +import com.zaxxer.hikari.HikariDataSource; +import io.micronaut.context.annotation.Factory; +import io.micronaut.context.annotation.Primary; +import jakarta.inject.Named; +import jakarta.inject.Singleton; + +import javax.sql.DataSource; + + +@Factory +public class DatasourceFactory { + + @Singleton + @Primary + @Named("default") + DataSource dataSource() { + HikariDataSource ds = new HikariDataSource(); + ds.setJdbcUrl("jdbc:h2:mem:micronautDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"); + ds.setUsername("sa"); + ds.setPassword(""); + ds.setDriverClassName("org.h2.Driver"); + return ds; + } + + @Singleton + @Named("grails") + DataSource dataSourceGrails() { + HikariDataSource ds = new HikariDataSource(); + ds.setJdbcUrl("jdbc:h2:mem:grailsDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"); + ds.setUsername("sa"); + ds.setPassword(""); + ds.setDriverClassName("org.h2.Driver"); + return ds; + } +} diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/GrailsBookRepository.java b/test-suite-manual-datasource/src/main/java/example/micronaut/GrailsBookRepository.java new file mode 100644 index 00000000..1e1ad7ae --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/GrailsBookRepository.java @@ -0,0 +1,8 @@ +package example.micronaut; + +import io.micronaut.data.jdbc.annotation.JdbcRepository; +import io.micronaut.data.model.query.builder.sql.Dialect; + +@JdbcRepository(dialect = Dialect.H2, dataSource = "grails") +public interface GrailsBookRepository extends BookRepository { +} diff --git a/test-suite-manual-datasource/src/main/java/example/micronaut/MicronautBookRepository.java b/test-suite-manual-datasource/src/main/java/example/micronaut/MicronautBookRepository.java new file mode 100644 index 00000000..13542a65 --- /dev/null +++ b/test-suite-manual-datasource/src/main/java/example/micronaut/MicronautBookRepository.java @@ -0,0 +1,8 @@ +package example.micronaut; + +import io.micronaut.data.jdbc.annotation.JdbcRepository; +import io.micronaut.data.model.query.builder.sql.Dialect; + +@JdbcRepository(dialect = Dialect.H2) +public interface MicronautBookRepository extends BookRepository{ +} diff --git a/test-suite-manual-datasource/src/main/resources/application.properties b/test-suite-manual-datasource/src/main/resources/application.properties new file mode 100644 index 00000000..ba1621d7 --- /dev/null +++ b/test-suite-manual-datasource/src/main/resources/application.properties @@ -0,0 +1,9 @@ +# Micronaut Books DataSource +datasources.default.dialect=H2 +datasources.default.schema-generate=NONE +flyway.datasources.default.enabled=true + +# Grails Books DataSource +datasources.grails.dialect=H2 +datasources.grails.schema-generate=NONE +flyway.datasources.grails.enabled=true diff --git a/test-suite-manual-datasource/src/main/resources/db/migration/V1__schema.sql b/test-suite-manual-datasource/src/main/resources/db/migration/V1__schema.sql new file mode 100644 index 00000000..ecf589fe --- /dev/null +++ b/test-suite-manual-datasource/src/main/resources/db/migration/V1__schema.sql @@ -0,0 +1,4 @@ +create table book( + id bigint auto_increment primary key, + title varchar(255) not null +); \ No newline at end of file diff --git a/test-suite-manual-datasource/src/main/resources/logback.xml b/test-suite-manual-datasource/src/main/resources/logback.xml new file mode 100644 index 00000000..a783dec3 --- /dev/null +++ b/test-suite-manual-datasource/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/test-suite-manual-datasource/src/test/java/example/micronaut/BookControllerTest.java b/test-suite-manual-datasource/src/test/java/example/micronaut/BookControllerTest.java new file mode 100644 index 00000000..160fa65d --- /dev/null +++ b/test-suite-manual-datasource/src/test/java/example/micronaut/BookControllerTest.java @@ -0,0 +1,72 @@ +package example.micronaut; + +import io.micronaut.core.type.Argument; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.BlockingHttpClient; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MicronautTest(transactional = false) +class BookControllerTest { + + @Inject + MicronautBookRepository micronautBookRepository; + + @Inject + GrailsBookRepository grailsBookRepository; + + @Inject + @Client("/") + HttpClient httpClient; + + @Test + void books() { + //given: + saveGrailsBooks(); + saveMicronautBooks(); + + BlockingHttpClient client = httpClient.toBlocking(); + Argument> arg = Argument.listOf(Book.class); + + //when: + List books = client.retrieve(HttpRequest.GET("/books"), arg); + //then: + assertEquals(9, books.size()); + + //when: + books = client.retrieve(HttpRequest.GET("/books/micronaut"), arg); + //then: + assertEquals(2, books.size()); + + //when: + books = client.retrieve(HttpRequest.GET("/books/grails"), arg); + + //then: + assertEquals(7, books.size()); + //cleanup: + grailsBookRepository.deleteAll(); + micronautBookRepository.deleteAll(); + } + + void saveGrailsBooks() { + grailsBookRepository.save(new Book(null, "Grails 3 - Step by Step")); + grailsBookRepository.save(new Book(null, "Grails Goodness Notebook")); + grailsBookRepository.save(new Book(null, "Falando de Grails")); + grailsBookRepository.save(new Book(null, "Grails in Action")); + grailsBookRepository.save(new Book(null, "The Definitive Guide to Grails 2")); + grailsBookRepository.save(new Book(null, "Programming Grails")); + grailsBookRepository.save(new Book(null, "Grails 2: Quick Start Guide")); + } + + void saveMicronautBooks() { + micronautBookRepository.save(new Book(null, "Introducing Micronaut: Build, Test and Deploy Java Microservices on Oracle Cloud")); + micronautBookRepository.save(new Book(null, "Building Microservices wiht Micronaut: A quick-start guide to building high-performance reactive microservices for Java developers")); + } +} \ No newline at end of file