Ensure that Session JDBC schema is in place before DB is accessed

Fixes gh-27208
pull/27348/head
Andy Wilkinson 3 years ago
parent 4b1b2d6603
commit 7b94b40a19

@ -20,12 +20,16 @@ import java.time.Duration;
import javax.sql.DataSource;
import liquibase.integration.spring.SpringLiquibase;
import org.flywaydb.core.Flyway;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -81,15 +85,40 @@ class JdbcSessionConfiguration {
}
@Configuration(proxyBeanMethods = false)
static class JdbcIndexedSessionRepositoryDependencyConfiguration {
@Bean
JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor dataSourceInitializerJdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor() {
return new JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor(
JdbcSessionDataSourceInitializer.class);
}
@Bean
@ConditionalOnClass(name = "org.flywaydb.core.Flyway")
JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor flywayJdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor() {
return new JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor(FlywayMigrationInitializer.class,
Flyway.class);
}
@Bean
@ConditionalOnClass(name = "liquibase.integration.spring.SpringLiquibase")
JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor liquibaseJdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor() {
return new JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor(FlywayMigrationInitializer.class,
SpringLiquibase.class);
}
}
/**
* Post processor to ensure that {@link JdbcIndexedSessionRepository} beans depend on
* any {@link JdbcSessionDataSourceInitializer} beans.
* {@link AbstractDependsOnBeanFactoryPostProcessor} for Spring Session JDBC's
* {@link JdbcIndexedSessionRepository}.
*/
static class DataSourceInitializationJdbcIndexedSessionRepositoryDependencyConfiguration
static class JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor
extends AbstractDependsOnBeanFactoryPostProcessor {
DataSourceInitializationJdbcIndexedSessionRepositoryDependencyConfiguration() {
super(JdbcIndexedSessionRepository.class, JdbcSessionDataSourceInitializer.class);
JdbcIndexedSessionRepositoryDependsOnBeanFactoryPostProcessor(Class<?>... dependencyTypes) {
super(JdbcIndexedSessionRepository.class, dependencyTypes);
}
}

@ -21,10 +21,13 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.session.JdbcSessionConfiguration.SpringBootJdbcHttpSessionConfiguration;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
@ -57,9 +60,9 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfigurationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
SessionAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(DataSourceTransactionManagerAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class, SessionAutoConfiguration.class))
.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
@ -190,6 +193,51 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration
});
}
@Test
void sessionRepositoryBeansDependOnJdbcSessionDataSourceInitializer() {
this.contextRunner.withPropertyValues("spring.session.store-type=jdbc").run((context) -> {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
String[] sessionRepositoryNames = beanFactory.getBeanNamesForType(JdbcIndexedSessionRepository.class);
assertThat(sessionRepositoryNames).isNotEmpty();
for (String sessionRepositoryName : sessionRepositoryNames) {
assertThat(beanFactory.getBeanDefinition(sessionRepositoryName).getDependsOn())
.contains("jdbcSessionDataSourceInitializer");
}
});
}
@Test
void sessionRepositoryBeansDependOnFlyway() {
this.contextRunner.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.initialize-schema=never")
.run((context) -> {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
String[] sessionRepositoryNames = beanFactory
.getBeanNamesForType(JdbcIndexedSessionRepository.class);
assertThat(sessionRepositoryNames).isNotEmpty();
for (String sessionRepositoryName : sessionRepositoryNames) {
assertThat(beanFactory.getBeanDefinition(sessionRepositoryName).getDependsOn())
.contains("flyway", "flywayInitializer");
}
});
}
@Test
void sessionRepositoryBeansDependOnLiquibase() {
this.contextRunner.withConfiguration(AutoConfigurations.of(LiquibaseAutoConfiguration.class))
.withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.initialize-schema=never")
.run((context) -> {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
String[] sessionRepositoryNames = beanFactory
.getBeanNamesForType(JdbcIndexedSessionRepository.class);
assertThat(sessionRepositoryNames).isNotEmpty();
for (String sessionRepositoryName : sessionRepositoryNames) {
assertThat(beanFactory.getBeanDefinition(sessionRepositoryName).getDependsOn())
.contains("liquibase");
}
});
}
@Configuration
static class SessionDataSourceConfiguration {

Loading…
Cancel
Save