Skip to content

Commit

Permalink
Order detector for AbstractDataSourceInitializers
Browse files Browse the repository at this point in the history
Previously, the detector for AbstractDataSourceInitializers used the
default detector order. This resulted in the initializers detected
initializers running before Flyway. Constrastingly, the detector for
DataSourceScriptDatabaseInitializers uses a custom order so its
detected initializers would run after Flyway.

This commit aligns the order of the detector for
AbstractDataSourceInitializers with the order of the detector for
DataSourceScriptDatabaseInitializers. This ensures that script-based
initialization runs in the same order with respect to Flyway,
irrespective of which initializer implementation is driving it.

Fixes gh-28079
  • Loading branch information
wilkinsona committed Sep 22, 2021
1 parent 90a5e34 commit 2ba5933
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.netty.client.TcpClientTransport;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;

import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration.IntegrationComponentScanConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
Expand All @@ -44,10 +44,8 @@
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.config.IntegrationManagementConfigurer;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.endpoint.MessageProcessorMessageSource;
import org.springframework.integration.gateway.RequestReplyExchanger;
import org.springframework.integration.handler.MessageProcessor;
import org.springframework.integration.rsocket.ClientRSocketConnector;
import org.springframework.integration.rsocket.IntegrationRSocketEndpoint;
import org.springframework.integration.rsocket.ServerRSocketConnector;
Expand Down Expand Up @@ -166,6 +164,27 @@ void integrationJdbcDataSourceInitializerEnabled() {
});
}

@Test
void whenIntegrationJdbcDataSourceInitializerIsEnabledThenFlywayCanBeUsed() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceTransactionManagerAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class, IntegrationAutoConfiguration.class,
FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true",
"spring.integration.jdbc.initialize-schema=always")
.run((context) -> {
IntegrationProperties properties = context.getBean(IntegrationProperties.class);
assertThat(properties.getJdbc().getInitializeSchema())
.isEqualTo(DataSourceInitializationMode.ALWAYS);
JdbcOperations jdbc = context.getBean(JdbcOperations.class);
assertThat(jdbc.queryForList("select * from INT_MESSAGE")).isEmpty();
assertThat(jdbc.queryForList("select * from INT_GROUP_TO_MESSAGE")).isEmpty();
assertThat(jdbc.queryForList("select * from INT_MESSAGE_GROUP")).isEmpty();
assertThat(jdbc.queryForList("select * from INT_LOCK")).isEmpty();
assertThat(jdbc.queryForList("select * from INT_CHANNEL_MESSAGE")).isEmpty();
});
}

@Test
void integrationJdbcDataSourceInitializerDisabled() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
Expand Down Expand Up @@ -362,8 +381,9 @@ interface TestGateway extends RequestReplyExchanger {
static class MessageSourceConfiguration {

@Bean
MessageSource<?> myMessageSource() {
return new MessageProcessorMessageSource(mock(MessageProcessor.class));
org.springframework.integration.core.MessageSource<?> myMessageSource() {
return new MessageProcessorMessageSource(
mock(org.springframework.integration.handler.MessageProcessor.class));
}

}
Expand All @@ -376,7 +396,7 @@ IntegrationRSocketEndpoint mockIntegrationRSocketEndpoint() {
return new IntegrationRSocketEndpoint() {

@Override
public Mono<Void> handleMessage(Message<?> message) {
public reactor.core.publisher.Mono<Void> handleMessage(Message<?> message) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.springframework.boot.sql.init.dependency.AbstractBeansOfTypeDatabaseInitializerDetector;
import org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector;
import org.springframework.core.Ordered;

/**
* A {@link DatabaseInitializerDetector} for {@link AbstractDataSourceInitializer}.
Expand All @@ -29,9 +30,16 @@
*/
class AbstractDataSourceInitializerDatabaseInitializerDetector extends AbstractBeansOfTypeDatabaseInitializerDetector {

private static final int PRECEDENCE = Ordered.LOWEST_PRECEDENCE - 100;

@Override
protected Set<Class<?>> getDatabaseInitializerBeanTypes() {
return Collections.singleton(AbstractDataSourceInitializer.class);
}

@Override
public int getOrder() {
return PRECEDENCE;
}

}

0 comments on commit 2ba5933

Please sign in to comment.