From 301c952ef9ea8a1086160de0949b02a6203a2724 Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Mon, 31 Oct 2022 14:56:28 +0300 Subject: [PATCH 1/9] smart migrations module --- .../common/spring/annotations/RequiredBy.kt | 9 +++ .../RequiredByBeanDefinitionPostProcessor.kt | 38 ++++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 1 + .../touchin/smartmigration/BeforeLiquibase.kt | 71 +++++++++++++++++++ .../smartmigration/SmartMigrationConfig.kt | 8 +++ .../annotation/EnableSmartMigration.kt | 7 ++ .../src/main/resources/application.yaml | 2 + 8 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 common-spring/src/main/kotlin/ru/touchin/common/spring/annotations/RequiredBy.kt create mode 100644 common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/SmartMigrationConfig.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/annotation/EnableSmartMigration.kt create mode 100644 smart-migration/src/main/resources/application.yaml diff --git a/common-spring/src/main/kotlin/ru/touchin/common/spring/annotations/RequiredBy.kt b/common-spring/src/main/kotlin/ru/touchin/common/spring/annotations/RequiredBy.kt new file mode 100644 index 0000000..b81e6f9 --- /dev/null +++ b/common-spring/src/main/kotlin/ru/touchin/common/spring/annotations/RequiredBy.kt @@ -0,0 +1,9 @@ +package ru.touchin.common.spring.annotations + +import org.springframework.context.annotation.Import +import ru.touchin.common.spring.processors.RequiredByBeanDefinitionPostProcessor + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS) +@Import(RequiredByBeanDefinitionPostProcessor::class) +annotation class RequiredBy(vararg val value: String) diff --git a/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt new file mode 100644 index 0000000..ca0fa2c --- /dev/null +++ b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt @@ -0,0 +1,38 @@ +package ru.touchin.common.spring.processors + +import org.springframework.beans.BeansException +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory +import org.springframework.beans.factory.support.BeanDefinitionRegistry +import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor +import org.springframework.stereotype.Component +import ru.touchin.common.spring.annotations.RequiredBy + +@Component +class RequiredByBeanDefinitionPostProcessor : BeanDefinitionRegistryPostProcessor { + + @Throws(BeansException::class) + override fun postProcessBeanDefinitionRegistry(registry: BeanDefinitionRegistry) { + for (beanName in registry.beanDefinitionNames) { + val beanDefinition = registry.getBeanDefinition(beanName) + if (beanDefinition.beanClassName == null) { + continue + } + try { + val beanClass = Class.forName(beanDefinition.beanClassName) + if (beanClass.isAnnotationPresent(RequiredBy::class.java)) { + val dependantBeanNames = beanClass.getAnnotation(RequiredBy::class.java).value + for (dependantBeanName in dependantBeanNames) { + val dependantBeanDefinition = registry.getBeanDefinition(dependantBeanName) + dependantBeanDefinition.setDependsOn(beanName) + } + } + } catch (e: ClassNotFoundException) { + throw RuntimeException(e) + } + } + } + + @Throws(BeansException::class) + override fun postProcessBeanFactory(beanFactory: ConfigurableListableBeanFactory) { + } +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be52383..f371643 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 6ddd481..2ed83bf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -58,3 +58,4 @@ include("s3-storage") include("server-info-spring-web") include("geoip-core") include("user-agent") +include("smart-migration") diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt new file mode 100644 index 0000000..0adb5a2 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt @@ -0,0 +1,71 @@ +package ru.touchin.smartmigration + +import org.intellij.lang.annotations.Language +import org.springframework.stereotype.Component +import ru.touchin.common.spring.annotations.RequiredBy +import java.sql.Date +import java.sql.ResultSet +import java.text.SimpleDateFormat +import javax.annotation.PostConstruct +import javax.sql.DataSource + +private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" + +val CURRENT_TIME_SQL: String + get() = Date(System.currentTimeMillis()).let { date -> + SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date) + } + +@Component +@RequiredBy("liquibase") +class BeforeLiquibase( + private val dataSource: DataSource +) { + + @PostConstruct + fun doAction() { + val buildNumber = System.getenv("BUILD_NUMBER") + if (buildNumber != null) { + checkMigrationTable() + if (checkBuildMigrationExecuted(buildNumber)) { + System.setProperty("spring.liquibase.enabled", "false") + } else { + insertMigration(buildNumber) + } + } + } + + private fun checkBuildMigrationExecuted(buildNumber: String): Boolean { + @Language("TSQL") + val checkBuildNumber = "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" + + val result: ResultSet = dataSource.connection.createStatement().executeQuery(checkBuildNumber) + var rowCount = 0 + while (result.next()) { + rowCount += 1; + } + return rowCount != 0 + } + + private fun checkMigrationTable() { + @Language("TSQL") + val createTable = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U')" + + "CREATE TABLE SMART_MIGRATION (\n" + + "\"ID\" BIGINT PRIMARY KEY IDENTITY ,\n" + + "\"BUILD_NUMBER\" VARCHAR(255) NOT NULL,\n" + + "\"DATE\" DATETIME NOT NULL" + + ");" + + dataSource.connection.createStatement() + .execute(createTable) + } + + private fun insertMigration(buildNumber: String) { + @Language("TSQL") + val insertMigration = "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + + "VALUES ('$buildNumber', '$CURRENT_TIME_SQL');" + + dataSource.connection.createStatement() + .execute(insertMigration) + } +} diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/SmartMigrationConfig.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/SmartMigrationConfig.kt new file mode 100644 index 0000000..21021a0 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/SmartMigrationConfig.kt @@ -0,0 +1,8 @@ +package ru.touchin.smartmigration + +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan("ru.touchin.smartmigration") +open class SmartMigrationConfig diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/annotation/EnableSmartMigration.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/annotation/EnableSmartMigration.kt new file mode 100644 index 0000000..fcab586 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/annotation/EnableSmartMigration.kt @@ -0,0 +1,7 @@ +package ru.touchin.smartmigration.annotation + +import org.springframework.context.annotation.Import +import ru.touchin.smartmigration.SmartMigrationConfig + +@Import(SmartMigrationConfig::class) +annotation class EnableSmartMigration diff --git a/smart-migration/src/main/resources/application.yaml b/smart-migration/src/main/resources/application.yaml new file mode 100644 index 0000000..6f3708e --- /dev/null +++ b/smart-migration/src/main/resources/application.yaml @@ -0,0 +1,2 @@ +spring: + liquibase.enabled: true From 6b16393ccb5d76c4bff4e08423558efec068d680 Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Mon, 31 Oct 2022 14:57:18 +0300 Subject: [PATCH 2/9] gradle build --- smart-migration/build.gradle | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 smart-migration/build.gradle diff --git a/smart-migration/build.gradle b/smart-migration/build.gradle new file mode 100644 index 0000000..8e9fb4c --- /dev/null +++ b/smart-migration/build.gradle @@ -0,0 +1,11 @@ +plugins { + id("kotlin") + id("kotlin-spring") + id("maven-publish") +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.springframework.boot:spring-boot") + implementation project(":common-spring") +} From 5770faf7dbb7fba7ebb6f63e227c6d29563b94bf Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Mon, 31 Oct 2022 18:37:40 +0300 Subject: [PATCH 3/9] update module for multiple datasource --- smart-migration/build.gradle | 1 + .../touchin/smartmigration/BeforeLiquibase.kt | 25 ++++++------------ .../smartmigration/logic/DataSourceSQL.kt | 7 +++++ .../logic/PostgresDataSourceImpl.kt | 22 ++++++++++++++++ .../smartmigration/logic/SqlDataSourceImpl.kt | 26 +++++++++++++++++++ .../logic/factory/DataSourceSqlFactory.kt | 7 +++++ .../logic/factory/DataSourceSqlFactoryImpl.kt | 18 +++++++++++++ 7 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt create mode 100644 smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt diff --git a/smart-migration/build.gradle b/smart-migration/build.gradle index 8e9fb4c..74e8552 100644 --- a/smart-migration/build.gradle +++ b/smart-migration/build.gradle @@ -7,5 +7,6 @@ plugins { dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.springframework.boot:spring-boot") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation project(":common-spring") } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt index 0adb5a2..2dee228 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt @@ -1,16 +1,15 @@ package ru.touchin.smartmigration -import org.intellij.lang.annotations.Language import org.springframework.stereotype.Component import ru.touchin.common.spring.annotations.RequiredBy +import ru.touchin.smartmigration.logic.DataSourceSQL +import ru.touchin.smartmigration.logic.factory.DataSourceSqlFactoryImpl import java.sql.Date import java.sql.ResultSet import java.text.SimpleDateFormat import javax.annotation.PostConstruct import javax.sql.DataSource -private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" - val CURRENT_TIME_SQL: String get() = Date(System.currentTimeMillis()).let { date -> SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date) @@ -21,9 +20,12 @@ val CURRENT_TIME_SQL: String class BeforeLiquibase( private val dataSource: DataSource ) { + val dataSourceSql: DataSourceSQL = DataSourceSqlFactoryImpl() + .getDataSourceSql(dataSource.connection.metaData.databaseProductName) @PostConstruct fun doAction() { + val buildNumber = System.getenv("BUILD_NUMBER") if (buildNumber != null) { checkMigrationTable() @@ -36,9 +38,8 @@ class BeforeLiquibase( } private fun checkBuildMigrationExecuted(buildNumber: String): Boolean { - @Language("TSQL") - val checkBuildNumber = "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" + val checkBuildNumber = dataSourceSql.getMigrationCheckSQL(buildNumber) val result: ResultSet = dataSource.connection.createStatement().executeQuery(checkBuildNumber) var rowCount = 0 while (result.next()) { @@ -48,23 +49,13 @@ class BeforeLiquibase( } private fun checkMigrationTable() { - @Language("TSQL") - val createTable = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U')" + - "CREATE TABLE SMART_MIGRATION (\n" + - "\"ID\" BIGINT PRIMARY KEY IDENTITY ,\n" + - "\"BUILD_NUMBER\" VARCHAR(255) NOT NULL,\n" + - "\"DATE\" DATETIME NOT NULL" + - ");" - + val createTable = dataSourceSql.getTableCheckSQL() dataSource.connection.createStatement() .execute(createTable) } private fun insertMigration(buildNumber: String) { - @Language("TSQL") - val insertMigration = "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + - "VALUES ('$buildNumber', '$CURRENT_TIME_SQL');" - + val insertMigration =dataSourceSql.getInsertMigrationSQL(buildNumber, CURRENT_TIME_SQL) dataSource.connection.createStatement() .execute(insertMigration) } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt new file mode 100644 index 0000000..0b37da7 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt @@ -0,0 +1,7 @@ +package ru.touchin.smartmigration.logic + +interface DataSourceSQL { + fun getTableCheckSQL(): String + fun getMigrationCheckSQL(buildNumber: String): String + fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String +} diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt new file mode 100644 index 0000000..1f7218b --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt @@ -0,0 +1,22 @@ +package ru.touchin.smartmigration.logic + +private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" + +class PostgresDataSourceImpl: DataSourceSQL { + override fun getTableCheckSQL(): String { + return "CREATE TABLE IF NOT EXISTS smart_migration (\n" + + "ID BIGSERIAL PRIMARY KEY ,\n" + + "BUILD_NUMBER VARCHAR(255) NOT NULL,\n" + + "DATE timestamp NOT NULL" + + ");" + } + + override fun getMigrationCheckSQL(buildNumber: String): String { + return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" + } + + override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { + return "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + + "VALUES ('$buildNumber', '$formattedTime');" + } +} diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt new file mode 100644 index 0000000..164b105 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt @@ -0,0 +1,26 @@ +package ru.touchin.smartmigration.logic + +private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" + +class SqlDatasourceImpl:DataSourceSQL { + override fun getTableCheckSQL(): String { + return "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U')" + + "CREATE TABLE SMART_MIGRATION (\n" + + "\"ID\" BIGINT PRIMARY KEY IDENTITY ,\n" + + "\"BUILD_NUMBER\" VARCHAR(255) NOT NULL,\n" + + "\"DATE\" DATETIME NOT NULL" + + ");" + } + + override fun getMigrationCheckSQL(buildNumber: String): String { + return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" + } + + override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { + return "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + + "VALUES ('$buildNumber', '$formattedTime');" + } + +} + + diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt new file mode 100644 index 0000000..391a2c5 --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt @@ -0,0 +1,7 @@ +package ru.touchin.smartmigration.logic.factory + +import ru.touchin.smartmigration.logic.DataSourceSQL + +interface DataSourceSqlFactory { + fun getDataSourceSql(driverName: String): DataSourceSQL +} diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt new file mode 100644 index 0000000..971d5ac --- /dev/null +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt @@ -0,0 +1,18 @@ +package ru.touchin.smartmigration.logic.factory + +import ru.touchin.smartmigration.logic.DataSourceSQL +import ru.touchin.smartmigration.logic.PostgresDataSourceImpl +import ru.touchin.smartmigration.logic.SqlDatasourceImpl + +class DataSourceSqlFactoryImpl: DataSourceSqlFactory { + + override fun getDataSourceSql(driverName: String): DataSourceSQL { + return when(driverName){ + "sql" -> SqlDatasourceImpl() + "PostgresSQL" -> PostgresDataSourceImpl() + else -> { + PostgresDataSourceImpl() + } + } + } +} From 0e381ff70c08b0f46a06e0e8ee44519fe1c6f673 Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Mon, 31 Oct 2022 18:45:02 +0300 Subject: [PATCH 4/9] Naming fix --- .../smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt index 971d5ac..d80311c 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt @@ -8,7 +8,7 @@ class DataSourceSqlFactoryImpl: DataSourceSqlFactory { override fun getDataSourceSql(driverName: String): DataSourceSQL { return when(driverName){ - "sql" -> SqlDatasourceImpl() + "Microsoft SQL Server" -> SqlDatasourceImpl() "PostgresSQL" -> PostgresDataSourceImpl() else -> { PostgresDataSourceImpl() From 6865e3fdb88c026911a315e9b976e000868835e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=20=D0=A0=D0=B0=D0=B2=D0=B8=D0=BD?= Date: Tue, 1 Nov 2022 15:00:37 +0300 Subject: [PATCH 5/9] styleguide --- .../touchin/smartmigration/BeforeLiquibase.kt | 34 +++++++++---------- .../smartmigration/logic/DataSourceSQL.kt | 4 +++ .../logic/PostgresDataSourceImpl.kt | 16 +++++---- .../smartmigration/logic/SqlDataSourceImpl.kt | 19 ++++++----- .../logic/factory/DataSourceSqlFactory.kt | 2 ++ .../logic/factory/DataSourceSqlFactoryImpl.kt | 1 + .../src/main/resources/application.yaml | 2 -- 7 files changed, 44 insertions(+), 34 deletions(-) delete mode 100644 smart-migration/src/main/resources/application.yaml diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt index 2dee228..3cd5791 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt @@ -10,42 +10,41 @@ import java.text.SimpleDateFormat import javax.annotation.PostConstruct import javax.sql.DataSource -val CURRENT_TIME_SQL: String - get() = Date(System.currentTimeMillis()).let { date -> - SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date) - } +private val SQL_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") + +private val CURRENT_TIME_SQL: String + get() = SQL_DATE_FORMAT.format(Date(System.currentTimeMillis())) @Component @RequiredBy("liquibase") class BeforeLiquibase( private val dataSource: DataSource ) { + val dataSourceSql: DataSourceSQL = DataSourceSqlFactoryImpl() .getDataSourceSql(dataSource.connection.metaData.databaseProductName) @PostConstruct fun doAction() { - val buildNumber = System.getenv("BUILD_NUMBER") - if (buildNumber != null) { - checkMigrationTable() - if (checkBuildMigrationExecuted(buildNumber)) { - System.setProperty("spring.liquibase.enabled", "false") - } else { - insertMigration(buildNumber) - } + ?: return + + checkMigrationTable() + + if (checkBuildMigrationExecuted(buildNumber)) { + System.setProperty("spring.liquibase.enabled", "false") + } else { + insertMigration(buildNumber) } } private fun checkBuildMigrationExecuted(buildNumber: String): Boolean { val checkBuildNumber = dataSourceSql.getMigrationCheckSQL(buildNumber) + val result: ResultSet = dataSource.connection.createStatement().executeQuery(checkBuildNumber) - var rowCount = 0 - while (result.next()) { - rowCount += 1; - } - return rowCount != 0 + + return result.next() != null } private fun checkMigrationTable() { @@ -59,4 +58,5 @@ class BeforeLiquibase( dataSource.connection.createStatement() .execute(insertMigration) } + } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt index 0b37da7..7bfba9b 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/DataSourceSQL.kt @@ -1,7 +1,11 @@ package ru.touchin.smartmigration.logic interface DataSourceSQL { + fun getTableCheckSQL(): String + fun getMigrationCheckSQL(buildNumber: String): String + fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String + } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt index 1f7218b..3df5847 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt @@ -3,12 +3,13 @@ package ru.touchin.smartmigration.logic private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" class PostgresDataSourceImpl: DataSourceSQL { + override fun getTableCheckSQL(): String { - return "CREATE TABLE IF NOT EXISTS smart_migration (\n" + - "ID BIGSERIAL PRIMARY KEY ,\n" + - "BUILD_NUMBER VARCHAR(255) NOT NULL,\n" + - "DATE timestamp NOT NULL" + - ");" + return """CREATE TABLE IF NOT EXISTS smart_migration ( + ID BIGSERIAL PRIMARY KEY , + BUILD_NUMBER VARCHAR(255) NOT NULL, + DATE timestamp NOT NULL + );""" } override fun getMigrationCheckSQL(buildNumber: String): String { @@ -16,7 +17,8 @@ class PostgresDataSourceImpl: DataSourceSQL { } override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { - return "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + - "VALUES ('$buildNumber', '$formattedTime');" + return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) + VALUES ('$buildNumber', '$formattedTime');""" } + } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt index 164b105..7c3d8d3 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt @@ -3,13 +3,16 @@ package ru.touchin.smartmigration.logic private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" class SqlDatasourceImpl:DataSourceSQL { + override fun getTableCheckSQL(): String { - return "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U')" + - "CREATE TABLE SMART_MIGRATION (\n" + - "\"ID\" BIGINT PRIMARY KEY IDENTITY ,\n" + - "\"BUILD_NUMBER\" VARCHAR(255) NOT NULL,\n" + - "\"DATE\" DATETIME NOT NULL" + - ");" + return """IF NOT EXISTS ( + SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U' + ) + CREATE TABLE SMART_MIGRATION ( + \"ID\" BIGINT PRIMARY KEY IDENTITY , + \"BUILD_NUMBER\" VARCHAR(255) NOT NULL, + \"DATE\" DATETIME NOT NULL + );""" } override fun getMigrationCheckSQL(buildNumber: String): String { @@ -17,8 +20,8 @@ class SqlDatasourceImpl:DataSourceSQL { } override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { - return "INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE)\n" + - "VALUES ('$buildNumber', '$formattedTime');" + return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) + VALUES ('$buildNumber', '$formattedTime');""" } } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt index 391a2c5..601e876 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactory.kt @@ -3,5 +3,7 @@ package ru.touchin.smartmigration.logic.factory import ru.touchin.smartmigration.logic.DataSourceSQL interface DataSourceSqlFactory { + fun getDataSourceSql(driverName: String): DataSourceSQL + } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt index d80311c..eb6c29a 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/factory/DataSourceSqlFactoryImpl.kt @@ -15,4 +15,5 @@ class DataSourceSqlFactoryImpl: DataSourceSqlFactory { } } } + } diff --git a/smart-migration/src/main/resources/application.yaml b/smart-migration/src/main/resources/application.yaml deleted file mode 100644 index 6f3708e..0000000 --- a/smart-migration/src/main/resources/application.yaml +++ /dev/null @@ -1,2 +0,0 @@ -spring: - liquibase.enabled: true From 4a32a1c09db85243dff710b5fb12888977d16a81 Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Wed, 2 Nov 2022 15:38:43 +0300 Subject: [PATCH 6/9] styleguide and refactor processor --- .../RequiredByBeanDefinitionPostProcessor.kt | 31 ++++++++++--------- .../touchin/smartmigration/BeforeLiquibase.kt | 7 +++-- .../logic/PostgresDataSourceImpl.kt | 5 +++ .../smartmigration/logic/SqlDataSourceImpl.kt | 11 +++++-- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt index ca0fa2c..e7ef49f 100644 --- a/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt +++ b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt @@ -13,21 +13,11 @@ class RequiredByBeanDefinitionPostProcessor : BeanDefinitionRegistryPostProcesso @Throws(BeansException::class) override fun postProcessBeanDefinitionRegistry(registry: BeanDefinitionRegistry) { for (beanName in registry.beanDefinitionNames) { - val beanDefinition = registry.getBeanDefinition(beanName) - if (beanDefinition.beanClassName == null) { - continue - } - try { - val beanClass = Class.forName(beanDefinition.beanClassName) - if (beanClass.isAnnotationPresent(RequiredBy::class.java)) { - val dependantBeanNames = beanClass.getAnnotation(RequiredBy::class.java).value - for (dependantBeanName in dependantBeanNames) { - val dependantBeanDefinition = registry.getBeanDefinition(dependantBeanName) - dependantBeanDefinition.setDependsOn(beanName) - } - } - } catch (e: ClassNotFoundException) { - throw RuntimeException(e) + val beanClassName = registry.getBeanDefinition(beanName).beanClassName?:continue + + getDependantBeanNames(beanClassName).forEach { dependantBeanName -> + val dependantBeanDefinition = registry.getBeanDefinition(dependantBeanName) + dependantBeanDefinition.setDependsOn(beanName) } } } @@ -35,4 +25,15 @@ class RequiredByBeanDefinitionPostProcessor : BeanDefinitionRegistryPostProcesso @Throws(BeansException::class) override fun postProcessBeanFactory(beanFactory: ConfigurableListableBeanFactory) { } + + private fun getDependantBeanNames(beanClassName: String): List { + val beanClass = Class.forName(beanClassName) + var dependantBeans = emptyList() + + if (beanClass.isAnnotationPresent(RequiredBy::class.java)) { + dependantBeans = beanClass.getAnnotation(RequiredBy::class.java).value.toList() + } + + return dependantBeans + } } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt index 3cd5791..40bc331 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt @@ -43,8 +43,11 @@ class BeforeLiquibase( val checkBuildNumber = dataSourceSql.getMigrationCheckSQL(buildNumber) val result: ResultSet = dataSource.connection.createStatement().executeQuery(checkBuildNumber) - - return result.next() != null + var rowCount = 0 + while (result.next()) { + rowCount += 1; + } + return rowCount != 0 } private fun checkMigrationTable() { diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt index 3df5847..cccc757 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt @@ -1,9 +1,12 @@ package ru.touchin.smartmigration.logic +import org.intellij.lang.annotations.Language + private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" class PostgresDataSourceImpl: DataSourceSQL { + @Language("SQL") override fun getTableCheckSQL(): String { return """CREATE TABLE IF NOT EXISTS smart_migration ( ID BIGSERIAL PRIMARY KEY , @@ -12,10 +15,12 @@ class PostgresDataSourceImpl: DataSourceSQL { );""" } + @Language("SQL") override fun getMigrationCheckSQL(buildNumber: String): String { return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" } + @Language("SQL") override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) VALUES ('$buildNumber', '$formattedTime');""" diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt index 7c3d8d3..4d27df8 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt @@ -1,24 +1,29 @@ package ru.touchin.smartmigration.logic +import org.intellij.lang.annotations.Language + private const val MIGRATION_TABLE_NAME = "SMART_MIGRATION" class SqlDatasourceImpl:DataSourceSQL { + @Language("TSQL") override fun getTableCheckSQL(): String { return """IF NOT EXISTS ( SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U' ) CREATE TABLE SMART_MIGRATION ( - \"ID\" BIGINT PRIMARY KEY IDENTITY , - \"BUILD_NUMBER\" VARCHAR(255) NOT NULL, - \"DATE\" DATETIME NOT NULL + ID BIGINT PRIMARY KEY IDENTITY , + BUILD_NUMBER VARCHAR(255) NOT NULL, + DATE DATETIME NOT NULL );""" } + @Language("TSQL") override fun getMigrationCheckSQL(buildNumber: String): String { return "SELECT * FROM $MIGRATION_TABLE_NAME WHERE BUILD_NUMBER = '$buildNumber'" } + @Language("TSQL") override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) VALUES ('$buildNumber', '$formattedTime');""" From 18248a27737d347f36bfd41bb3be61f83a18e1de Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Thu, 3 Nov 2022 13:47:18 +0300 Subject: [PATCH 7/9] fix functional style --- .../touchin/smartmigration/BeforeLiquibase.kt | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt index 40bc331..1866dff 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/BeforeLiquibase.kt @@ -1,3 +1,4 @@ +@file:Suppress("unused") package ru.touchin.smartmigration import org.springframework.stereotype.Component @@ -5,7 +6,6 @@ import ru.touchin.common.spring.annotations.RequiredBy import ru.touchin.smartmigration.logic.DataSourceSQL import ru.touchin.smartmigration.logic.factory.DataSourceSqlFactoryImpl import java.sql.Date -import java.sql.ResultSet import java.text.SimpleDateFormat import javax.annotation.PostConstruct import javax.sql.DataSource @@ -39,27 +39,21 @@ class BeforeLiquibase( } private fun checkBuildMigrationExecuted(buildNumber: String): Boolean { - - val checkBuildNumber = dataSourceSql.getMigrationCheckSQL(buildNumber) - - val result: ResultSet = dataSource.connection.createStatement().executeQuery(checkBuildNumber) - var rowCount = 0 - while (result.next()) { - rowCount += 1; + return dataSourceSql.getMigrationCheckSQL(buildNumber).let { + dataSource.connection.createStatement().executeQuery(it).next() } - return rowCount != 0 } private fun checkMigrationTable() { - val createTable = dataSourceSql.getTableCheckSQL() - dataSource.connection.createStatement() - .execute(createTable) + dataSourceSql.getTableCheckSQL().let { + dataSource.connection.createStatement().execute(it) + } } private fun insertMigration(buildNumber: String) { - val insertMigration =dataSourceSql.getInsertMigrationSQL(buildNumber, CURRENT_TIME_SQL) - dataSource.connection.createStatement() - .execute(insertMigration) + dataSourceSql.getInsertMigrationSQL(buildNumber, CURRENT_TIME_SQL).let { + dataSource.connection.createStatement().execute(it) + } } } From d0c7ca03fb6e342a6ec3305b1b2090f26d4b781d Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Thu, 3 Nov 2022 14:06:09 +0300 Subject: [PATCH 8/9] fix fs 2 --- .../spring/processors/RequiredByBeanDefinitionPostProcessor.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt index e7ef49f..e98d520 100644 --- a/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt +++ b/common-spring/src/main/kotlin/ru/touchin/common/spring/processors/RequiredByBeanDefinitionPostProcessor.kt @@ -16,8 +16,7 @@ class RequiredByBeanDefinitionPostProcessor : BeanDefinitionRegistryPostProcesso val beanClassName = registry.getBeanDefinition(beanName).beanClassName?:continue getDependantBeanNames(beanClassName).forEach { dependantBeanName -> - val dependantBeanDefinition = registry.getBeanDefinition(dependantBeanName) - dependantBeanDefinition.setDependsOn(beanName) + registry.getBeanDefinition(dependantBeanName).setDependsOn(beanName) } } } From 8b9643b60adb91478777a80c4b3f7d5b444a3fd9 Mon Sep 17 00:00:00 2001 From: Ilia Ravin Date: Thu, 10 Nov 2022 17:20:05 +0300 Subject: [PATCH 9/9] indent fix --- .../logic/PostgresDataSourceImpl.kt | 18 ++++++++------ .../smartmigration/logic/SqlDataSourceImpl.kt | 24 +++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt index cccc757..782a3d4 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/PostgresDataSourceImpl.kt @@ -8,11 +8,13 @@ class PostgresDataSourceImpl: DataSourceSQL { @Language("SQL") override fun getTableCheckSQL(): String { - return """CREATE TABLE IF NOT EXISTS smart_migration ( - ID BIGSERIAL PRIMARY KEY , - BUILD_NUMBER VARCHAR(255) NOT NULL, - DATE timestamp NOT NULL - );""" + return """ + CREATE TABLE IF NOT EXISTS smart_migration ( + ID BIGSERIAL PRIMARY KEY, + BUILD_NUMBER VARCHAR(255) NOT NULL, + DATE timestamp NOT NULL + ); + """ } @Language("SQL") @@ -22,8 +24,10 @@ class PostgresDataSourceImpl: DataSourceSQL { @Language("SQL") override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { - return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) - VALUES ('$buildNumber', '$formattedTime');""" + return """ + INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) + VALUES ('$buildNumber', '$formattedTime'); + """ } } diff --git a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt index 4d27df8..fac3bff 100644 --- a/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt +++ b/smart-migration/src/main/kotlin/ru/touchin/smartmigration/logic/SqlDataSourceImpl.kt @@ -8,14 +8,16 @@ class SqlDatasourceImpl:DataSourceSQL { @Language("TSQL") override fun getTableCheckSQL(): String { - return """IF NOT EXISTS ( - SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U' - ) - CREATE TABLE SMART_MIGRATION ( - ID BIGINT PRIMARY KEY IDENTITY , - BUILD_NUMBER VARCHAR(255) NOT NULL, - DATE DATETIME NOT NULL - );""" + return """ + IF NOT EXISTS ( + SELECT * FROM sysobjects WHERE name = '$MIGRATION_TABLE_NAME' and xtype='U' + ) + CREATE TABLE SMART_MIGRATION ( + ID BIGINT PRIMARY KEY IDENTITY , + BUILD_NUMBER VARCHAR(255) NOT NULL, + DATE DATETIME NOT NULL + ); + """ } @Language("TSQL") @@ -25,8 +27,10 @@ class SqlDatasourceImpl:DataSourceSQL { @Language("TSQL") override fun getInsertMigrationSQL(buildNumber: String, formattedTime: String): String { - return """INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) - VALUES ('$buildNumber', '$formattedTime');""" + return """ + INSERT INTO $MIGRATION_TABLE_NAME (BUILD_NUMBER, DATE) + VALUES ('$buildNumber', '$formattedTime'); + """ } }