From 960ab159e4b289489ba4649e8a7375a57e31f878 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 31 Mar 2020 13:09:59 +0200 Subject: [PATCH] Document how to initialize a database with R2DBC This commit adds a section to the reference guide on how to initialize a database using R2DBC. 2 smoke tests are also added to validate this behaviour with Flyway and Liquibase. Closes gh-20742 --- .../src/docs/asciidoc/howto.adoc | 20 +++++- .../R2dbcDatabaseInitializationExample.java | 50 ++++++++++++++ .../build.gradle | 22 ++++++ .../main/java/smoketest/data/r2dbc/City.java | 61 +++++++++++++++++ .../smoketest/data/r2dbc/CityRepository.java | 27 ++++++++ .../r2dbc/SampleR2dbcFlywayApplication.java | 29 ++++++++ .../src/main/resources/application.properties | 5 ++ .../main/resources/db/migration/V1__init.sql | 9 +++ .../data/r2dbc/CityRepositoryTests.java | 68 +++++++++++++++++++ .../build.gradle | 22 ++++++ .../main/java/smoketest/data/r2dbc/City.java | 61 +++++++++++++++++ .../smoketest/data/r2dbc/CityRepository.java | 27 ++++++++ .../SampleR2dbcLiquibaseApplication.java | 29 ++++++++ .../src/main/resources/application.properties | 5 ++ .../db/changelog/db.changelog-master.yaml | 52 ++++++++++++++ .../data/r2dbc/CityRepositoryTests.java | 68 +++++++++++++++++++ 16 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/r2dbc/R2dbcDatabaseInitializationExample.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/build.gradle create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/City.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/CityRepository.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/SampleR2dbcFlywayApplication.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/application.properties create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/db/migration/V1__init.sql create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/build.gradle create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/City.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/CityRepository.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/SampleR2dbcLiquibaseApplication.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/application.properties create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc index f5ce385176..c33320e7da 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc @@ -1937,7 +1937,7 @@ It is a Hibernate feature (and has nothing to do with Spring). [[howto-initialize-a-database-using-spring-jdbc]] -=== Initialize a Database +=== Initialize a Database using basic SQL scripts Spring Boot can automatically create the schema (DDL scripts) of your `DataSource` and initialize it (DML scripts). It loads SQL from the standard root classpath locations: `schema.sql` and `data.sql`, respectively. In addition, Spring Boot processes the `schema-$\{platform}.sql` and `data-$\{platform}.sql` files (if present), where `platform` is the value of `spring.datasource.platform`. @@ -1965,6 +1965,24 @@ Make sure to disable `spring.jpa.hibernate.ddl-auto` if you use `schema.sql`. +[[howto-initialize-a-database-using-r2dc]] +=== Initialize a Database Using R2DBC +If you are using R2DBC, the regular `DataSource` auto-configuration backs off so none of the options described above can be used. + +If you are using Spring Data R2DBC, you can initialize the database on startup using simple SQL scripts as shown in the following example: + +[source,java,indent=0] +---- +include::{code-examples}/r2dbc/R2dbcDatabaseInitializationExample.java[tag=configuration] +---- + +Alternatively, you can configure either <> or <> to configure a `DataSource` for you for the duration of the migration. +Both these libraries offer properties to set the `url`, `username` and `password` of the database to migrate. + +NOTE: When choosing this option, `org.springframework:spring-jdbc` is still a required dependency. + + + [[howto-initialize-a-spring-batch-database]] === Initialize a Spring Batch Database If you use Spring Batch, it comes pre-packaged with SQL initialization scripts for most popular database platforms. diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/r2dbc/R2dbcDatabaseInitializationExample.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/r2dbc/R2dbcDatabaseInitializationExample.java new file mode 100644 index 0000000000..2f94827545 --- /dev/null +++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/r2dbc/R2dbcDatabaseInitializationExample.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docs.r2dbc; + +import io.r2dbc.spi.ConnectionFactory; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator; + +/** + * Example configuration for initializing a database using R2DBC. + * + * @author Stephane Nicoll + */ +public class R2dbcDatabaseInitializationExample { + + // tag::configuration[] + @Configuration(proxyBeanMethods = false) + static class DatabaseInitializationConfiguration { + + @Autowired + void initializeDatabase(ConnectionFactory connectionFactory) { + ResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource[] scripts = new Resource[] { resourceLoader.getResource("classpath:schema.sql"), + resourceLoader.getResource("classpath:data.sql") }; + new ResourceDatabasePopulator(scripts).execute(connectionFactory).block(); + } + + } + // end::configuration[] + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/build.gradle new file mode 100644 index 0000000000..de9c5211ad --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/build.gradle @@ -0,0 +1,22 @@ +plugins { + id "java" + id "org.springframework.boot.conventions" +} + +description = "Spring Boot Data R2DBC with Flyway smoke test" + +dependencies { + implementation(platform(project(":spring-boot-project:spring-boot-parent"))) + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-r2dbc")) + + runtimeOnly("io.r2dbc:r2dbc-postgresql") + runtimeOnly("org.flywaydb:flyway-core") + runtimeOnly("org.postgresql:postgresql") + runtimeOnly("org.springframework:spring-jdbc") + + testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + testImplementation("io.projectreactor:reactor-test") + testImplementation("org.testcontainers:junit-jupiter") + testImplementation("org.testcontainers:postgresql") + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/City.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/City.java new file mode 100644 index 0000000000..2e30c9b6dd --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/City.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.springframework.data.annotation.Id; + +public class City { + + @Id + private Long id; + + private String name; + + private String state; + + private String country; + + protected City() { + } + + public City(String name, String country) { + this.name = name; + this.country = country; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public String getState() { + return this.state; + } + + public String getCountry() { + return this.country; + } + + @Override + public String toString() { + return getName() + "," + getState() + "," + getCountry(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/CityRepository.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/CityRepository.java new file mode 100644 index 0000000000..d8908f8367 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/CityRepository.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import reactor.core.publisher.Flux; + +import org.springframework.data.repository.reactive.ReactiveCrudRepository; + +public interface CityRepository extends ReactiveCrudRepository { + + Flux findByState(String state); + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/SampleR2dbcFlywayApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/SampleR2dbcFlywayApplication.java new file mode 100644 index 0000000000..02c105e856 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/java/smoketest/data/r2dbc/SampleR2dbcFlywayApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleR2dbcFlywayApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleR2dbcFlywayApplication.class, args); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/application.properties new file mode 100644 index 0000000000..a8107a6bd5 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.r2dbc.url=r2dbc:postgresql://user:secret@localhost/test_flyway + +spring.flyway.url=jdbc:postgresql://localhost/test_flyway +spring.flyway.user=user +spring.flyway.password=secret \ No newline at end of file diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/db/migration/V1__init.sql b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/db/migration/V1__init.sql new file mode 100644 index 0000000000..3cd0824a27 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,9 @@ +CREATE TABLE CITY ( + id INTEGER PRIMARY KEY, + name VARCHAR(30), + state VARCHAR(30), + country VARCHAR(30) +); + +INSERT INTO CITY (ID, NAME, STATE, COUNTRY) values (2000, 'Washington', 'DC', 'US'); +INSERT INTO CITY (ID, NAME, STATE, COUNTRY) values (2001, 'San Francisco', 'CA', 'US'); diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java new file mode 100644 index 0000000000..e66e5316e4 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-flyway/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.test.StepVerifier; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CityRepository}. + */ +@Testcontainers(disabledWithoutDocker = true) +@DataR2dbcTest +class CityRepositoryTests { + + @Container + static PostgreSQLContainer postgresql = new PostgreSQLContainer<>().withDatabaseName("test_flyway"); + + @DynamicPropertySource + static void postgresqlProperties(DynamicPropertyRegistry registry) { + registry.add("spring.r2dbc.url", CityRepositoryTests::r2dbcUrl); + registry.add("spring.r2dbc.username", postgresql::getUsername); + registry.add("spring.r2dbc.password", postgresql::getPassword); + + // configure flyway to use the same database + registry.add("spring.flyway.url", postgresql::getJdbcUrl); + registry.add("spring.flyway.user", postgresql::getUsername); + registry.add("spring.flyway.password", postgresql::getPassword); + } + + @Autowired + private CityRepository repository; + + @Test + void databaseHasBeenInitialized() { + StepVerifier.create(this.repository.findByState("DC").filter((city) -> city.getName().equals("Washington"))) + .consumeNextWith((city) -> assertThat(city.getId()).isNotNull()).verifyComplete(); + } + + private static String r2dbcUrl() { + return String.format("r2dbc:postgresql://%s:%s/%s", postgresql.getContainerIpAddress(), + postgresql.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT), postgresql.getDatabaseName()); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/build.gradle new file mode 100644 index 0000000000..6a36acae38 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/build.gradle @@ -0,0 +1,22 @@ +plugins { + id "java" + id "org.springframework.boot.conventions" +} + +description = "Spring Boot Data R2DBC with Liquibase smoke test" + +dependencies { + implementation(platform(project(":spring-boot-project:spring-boot-parent"))) + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-r2dbc")) + + runtimeOnly("io.r2dbc:r2dbc-postgresql") + runtimeOnly("org.liquibase:liquibase-core") + runtimeOnly("org.postgresql:postgresql") + runtimeOnly("org.springframework:spring-jdbc") + + testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + testImplementation("io.projectreactor:reactor-test") + testImplementation("org.testcontainers:junit-jupiter") + testImplementation("org.testcontainers:postgresql") + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/City.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/City.java new file mode 100644 index 0000000000..2e30c9b6dd --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/City.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.springframework.data.annotation.Id; + +public class City { + + @Id + private Long id; + + private String name; + + private String state; + + private String country; + + protected City() { + } + + public City(String name, String country) { + this.name = name; + this.country = country; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public String getState() { + return this.state; + } + + public String getCountry() { + return this.country; + } + + @Override + public String toString() { + return getName() + "," + getState() + "," + getCountry(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/CityRepository.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/CityRepository.java new file mode 100644 index 0000000000..d8908f8367 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/CityRepository.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import reactor.core.publisher.Flux; + +import org.springframework.data.repository.reactive.ReactiveCrudRepository; + +public interface CityRepository extends ReactiveCrudRepository { + + Flux findByState(String state); + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/SampleR2dbcLiquibaseApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/SampleR2dbcLiquibaseApplication.java new file mode 100644 index 0000000000..748943da9b --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/java/smoketest/data/r2dbc/SampleR2dbcLiquibaseApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleR2dbcLiquibaseApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleR2dbcLiquibaseApplication.class, args); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/application.properties new file mode 100644 index 0000000000..80f7c56fb0 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.r2dbc.url=r2dbc:postgresql://user:secret@localhost/test_liquibase + +spring.liquibase.url=jdbc:postgresql://localhost/test_liquibase +spring.liquibase.user=user +spring.liquibase.password=secret \ No newline at end of file diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml new file mode 100644 index 0000000000..02b39f646d --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml @@ -0,0 +1,52 @@ +databaseChangeLog: + - changeSet: + id: 1 + author: snicoll + changes: + - createTable: + tableName: city + columns: + - column: + name: id + type: int + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: varchar(30) + - column: + name: state + type: varchar(30) + - column: + name: country + type: varchar(30) + - changeSet: + id: 2 + author: snicoll + changes: + - insert: + tableName: city + columns: + - column: + name: name + value: Washington + - column: + name: state + value: DC + - column: + name: country + value: US + - insert: + tableName: city + columns: + - column: + name: name + value: San Francisco + - column: + name: state + value: CA + - column: + name: country + value: US \ No newline at end of file diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java new file mode 100644 index 0000000000..117b472ed4 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-r2dbc-liquibase/src/test/java/smoketest/data/r2dbc/CityRepositoryTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.data.r2dbc; + +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.test.StepVerifier; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CityRepository}. + */ +@Testcontainers(disabledWithoutDocker = true) +@DataR2dbcTest +class CityRepositoryTests { + + @Container + static PostgreSQLContainer postgresql = new PostgreSQLContainer<>().withDatabaseName("test_liquibase"); + + @DynamicPropertySource + static void postgresqlProperties(DynamicPropertyRegistry registry) { + registry.add("spring.r2dbc.url", CityRepositoryTests::r2dbcUrl); + registry.add("spring.r2dbc.username", postgresql::getUsername); + registry.add("spring.r2dbc.password", postgresql::getPassword); + + // configure liquibase to use the same database + registry.add("spring.liquibase.url", postgresql::getJdbcUrl); + registry.add("spring.liquibase.user", postgresql::getUsername); + registry.add("spring.liquibase.password", postgresql::getPassword); + } + + @Autowired + private CityRepository repository; + + @Test + void databaseHasBeenInitialized() { + StepVerifier.create(this.repository.findByState("DC").filter((city) -> city.getName().equals("Washington"))) + .consumeNextWith((city) -> assertThat(city.getId()).isNotNull()).verifyComplete(); + } + + private static String r2dbcUrl() { + return String.format("r2dbc:postgresql://%s:%s/%s", postgresql.getContainerIpAddress(), + postgresql.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT), postgresql.getDatabaseName()); + } + +}