diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java index 2a45b65aa54..e82a99b479d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration.java @@ -18,9 +18,11 @@ package org.springframework.boot.autoconfigure.liquibase; import javax.sql.DataSource; +import liquibase.Liquibase; import liquibase.UpdateSummaryEnum; import liquibase.UpdateSummaryOutputEnum; import liquibase.change.DatabaseChange; +import liquibase.integration.spring.Customizer; import liquibase.integration.spring.SpringLiquibase; import liquibase.ui.UIServiceEnum; @@ -66,6 +68,7 @@ import org.springframework.util.StringUtils; * @author Ferenc Gratzer * @author Evgeniy Cheban * @author Moritz Halbritter + * @author Ahmed Ashour * @since 1.1.0 */ @AutoConfiguration(after = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) @@ -95,9 +98,9 @@ public class LiquibaseAutoConfiguration { } @Bean - public SpringLiquibase liquibase(ObjectProvider dataSource, + SpringLiquibase liquibase(ObjectProvider dataSource, @LiquibaseDataSource ObjectProvider liquibaseDataSource, LiquibaseProperties properties, - LiquibaseConnectionDetails connectionDetails) { + ObjectProvider customizers, LiquibaseConnectionDetails connectionDetails) { SpringLiquibase liquibase = createSpringLiquibase(liquibaseDataSource.getIfAvailable(), dataSource.getIfUnique(), connectionDetails); liquibase.setChangeLog(properties.getChangeLog()); @@ -125,6 +128,7 @@ public class LiquibaseAutoConfiguration { if (properties.getUiService() != null) { liquibase.setUiService(UIServiceEnum.valueOf(properties.getUiService().name())); } + customizers.orderedStream().forEach((customizer) -> customizer.customize(liquibase)); return liquibase; } @@ -173,6 +177,17 @@ public class LiquibaseAutoConfiguration { } + @ConditionalOnClass(Customizer.class) + static class CustomizerConfiguration { + + @Bean + @ConditionalOnBean(Customizer.class) + SpringLiquibaseCustomizer customizerSpringLiquibaseCustomizer(Customizer customizer) { + return (springLiquibase) -> springLiquibase.setCustomizer(customizer); + } + + } + static final class LiquibaseDataSourceCondition extends AnyNestedCondition { LiquibaseDataSourceCondition() { @@ -239,4 +254,15 @@ public class LiquibaseAutoConfiguration { } + @FunctionalInterface + private interface SpringLiquibaseCustomizer { + + /** + * Customize the given {@link SpringLiquibase} instance. + * @param springLiquibase the instance to configure + */ + void customize(SpringLiquibase springLiquibase); + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java index 83d2f7d94aa..cc546cc1e9a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java @@ -29,9 +29,11 @@ import java.util.function.Consumer; import javax.sql.DataSource; import com.zaxxer.hikari.HikariDataSource; +import liquibase.Liquibase; import liquibase.UpdateSummaryEnum; import liquibase.UpdateSummaryOutputEnum; import liquibase.command.core.helpers.ShowSummaryArgument; +import liquibase.integration.spring.Customizer; import liquibase.integration.spring.SpringLiquibase; import liquibase.ui.UIServiceEnum; import org.junit.jupiter.api.Test; @@ -83,6 +85,7 @@ import static org.assertj.core.api.Assertions.contentOf; * @author Evgeniy Cheban * @author Moritz Halbritter * @author Phillip Webb + * @author Ahmed Ashour */ @ExtendWith(OutputCaptureExtension.class) class LiquibaseAutoConfigurationTests { @@ -532,6 +535,12 @@ class LiquibaseAutoConfigurationTests { assertThat(RuntimeHintsPredicates.resource().forResource("db/changelog/tables/init.sql")).accepts(hints); } + @Test + void whenCustomizerBeanIsDefinedThenItIsConfiguredOnSpringLiquibase() { + this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, CustomizerConfiguration.class) + .run(assertLiquibase((liquibase) -> assertThat(liquibase.getCustomizer()).isNotNull())); + } + private ContextConsumer assertLiquibase(Consumer consumer) { return (context) -> { assertThat(context).hasSingleBean(SpringLiquibase.class); @@ -668,6 +677,16 @@ class LiquibaseAutoConfigurationTests { } + @Configuration(proxyBeanMethods = false) + static class CustomizerConfiguration { + + @Bean + Customizer customizer() { + return (liquibase) -> liquibase.setChangeLogParameter("some key", "some value"); + } + + } + static class CustomH2Driver extends org.h2.Driver { } diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-initialization.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-initialization.adoc index 69d3e997808..e9f80a0ab60 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-initialization.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-initialization.adoc @@ -187,6 +187,8 @@ If any of the three properties has not been set, the value of its equivalent `sp See xref:api:java/org/springframework/boot/autoconfigure/liquibase/LiquibaseProperties.html[`LiquibaseProperties`] for details about available settings such as contexts, the default schema, and others. +You can also use a `Customizer` bean if you want to customize the `Liquibase` instance before it is being used. + [[howto.data-initialization.migration-tool.flyway-tests]]