From 147126a70f27e7cc93f08115fabcba2a47acd5a0 Mon Sep 17 00:00:00 2001 From: Dave Ankin Date: Sat, 21 Jan 2023 19:43:57 -0500 Subject: [PATCH 1/2] initial implementation --- ...onDataSourceScriptDatabaseInitializer.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java index a5279ecb45bd..af7e7e5d496d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java @@ -17,10 +17,12 @@ package org.springframework.boot.autoconfigure.session; import java.util.List; +import java.util.Objects; import javax.sql.DataSource; import org.springframework.boot.jdbc.DatabaseDriver; +import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver; import org.springframework.boot.sql.init.DatabaseInitializationSettings; @@ -38,6 +40,8 @@ */ public class JdbcSessionDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer { + private JdbcSessionProperties properties; + /** * Create a new {@link JdbcSessionDataSourceScriptDatabaseInitializer} instance. * @param dataSource the Spring Session JDBC data source @@ -46,6 +50,7 @@ public class JdbcSessionDataSourceScriptDatabaseInitializer extends DataSourceSc */ public JdbcSessionDataSourceScriptDatabaseInitializer(DataSource dataSource, JdbcSessionProperties properties) { this(dataSource, getSettings(dataSource, properties)); + this.properties = properties; } /** @@ -77,6 +82,34 @@ static DatabaseInitializationSettings getSettings(DataSource dataSource, JdbcSes return settings; } + @Override + protected void runScripts(Scripts scripts) { + validateConfiguration(); + super.runScripts(scripts); + } + + private void validateConfiguration() { + if (properties == null) return; // cannot validate without this + JdbcSessionProperties defaults = new JdbcSessionProperties(); + boolean willHappen = switch (properties.getInitializeSchema()) { + case ALWAYS -> true; + case NEVER -> false; + case EMBEDDED -> isEmbeddedDatabase(); + }; + boolean tableNameChanged = !Objects.equals(defaults.getTableName(), properties.getTableName()); + boolean schemaUnchanged = Objects.equals(defaults.getSchema(), properties.getSchema()); + + if (willHappen && tableNameChanged && schemaUnchanged) { + String name = "spring.session.jdbc.schema"; + String value = properties.getSchema(); + String reason = "When JDBC Session database initialization will take place " + + "(spring.session.jdbc.initialize-schema = " + properties.getInitializeSchema() + "), " + + "and the table name is not the default value (" + properties.getTableName() + "), " + + "the schema must be a custom schema to match the specified table name."; + throw new InvalidConfigurationPropertyValueException(name, value, reason); + } + } + private static List resolveSchemaLocations(DataSource dataSource, JdbcSessionProperties properties) { PlatformPlaceholderDatabaseDriverResolver platformResolver = new PlatformPlaceholderDatabaseDriverResolver(); platformResolver = platformResolver.withDriverPlatform(DatabaseDriver.MARIADB, "mysql"); From ba645905881c131bf77bb3b26a70aa888bdf72c5 Mon Sep 17 00:00:00 2001 From: Dave Ankin Date: Sat, 21 Jan 2023 20:23:52 -0500 Subject: [PATCH 2/2] add unit test --- ...onDataSourceScriptDatabaseInitializer.java | 2 +- ...aSourceScriptDatabaseInitializerTests.java | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java index af7e7e5d496d..75838458b41a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializer.java @@ -88,7 +88,7 @@ protected void runScripts(Scripts scripts) { super.runScripts(scripts); } - private void validateConfiguration() { + void validateConfiguration() { if (properties == null) return; // cannot validate without this JdbcSessionProperties defaults = new JdbcSessionProperties(); boolean willHappen = switch (properties.getInitializeSchema()) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializerTests.java index 3b78e05e732a..b7beb10d250c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/JdbcSessionDataSourceScriptDatabaseInitializerTests.java @@ -20,9 +20,12 @@ import org.junit.jupiter.api.Test; +import org.springframework.boot.sql.init.DatabaseInitializationMode; import org.springframework.boot.sql.init.DatabaseInitializationSettings; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; @@ -45,4 +48,29 @@ void getSettingsWithPlatformDoesNotTouchDataSource() { then(dataSource).shouldHaveNoInteractions(); } + @Test + void test_validateConfigurationThrowsForInvalidConfiguration() { + DataSource dataSource = mock(DataSource.class); + JdbcSessionProperties properties = new JdbcSessionProperties(); + properties.setPlatform("mysql"); + JdbcSessionDataSourceScriptDatabaseInitializer initializer = + new JdbcSessionDataSourceScriptDatabaseInitializer(dataSource, properties) { + @Override + protected boolean isEmbeddedDatabase() { + return false; + } + }; + + assertThatCode(initializer::validateConfiguration).doesNotThrowAnyException(); + + properties.setInitializeSchema(DatabaseInitializationMode.ALWAYS); + assertThatCode(initializer::validateConfiguration).doesNotThrowAnyException(); + + properties.setTableName(properties.getTableName() + "_CUSTOM"); + assertThatThrownBy(initializer::validateConfiguration).message().isNotBlank(); + + properties.setSchema(properties.getSchema() + ".different.sql"); + assertThatCode(initializer::validateConfiguration).doesNotThrowAnyException(); + } + }