diff --git a/common/src/main/java/org/apache/seata/common/Constants.java b/common/src/main/java/org/apache/seata/common/Constants.java index 43da1827e05..c157b0c6f07 100644 --- a/common/src/main/java/org/apache/seata/common/Constants.java +++ b/common/src/main/java/org/apache/seata/common/Constants.java @@ -127,6 +127,10 @@ public interface Constants { * The constant BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER */ String BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER = "springApplicationContextProvider"; + /** + * The constant BEAN_NAME_SEATA_FILE_CONFIGURATION_PROVIDER + */ + String BEAN_NAME_SEATA_FILE_CONFIGURATION_PROVIDER = "seataFileConfigurationProvider"; /** * The constant BEAN_NAME_SPRING_FENCE_CONFIG */ diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/pom.xml b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/pom.xml index a3767ecb0ab..1fb5096741a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/pom.xml +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/pom.xml @@ -38,5 +38,10 @@ ${project.version} test + + org.springframework.boot + spring-boot-starter-test + test + \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfiguration.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfiguration.java index ce8a1e33a35..c5082805f30 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfiguration.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfiguration.java @@ -16,6 +16,7 @@ */ package org.apache.seata.spring.boot.autoconfigure; +import org.apache.seata.spring.boot.autoconfigure.provider.SeataFileConfigurationProvider; import org.apache.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -23,6 +24,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import static org.apache.seata.common.Constants.BEAN_NAME_SEATA_FILE_CONFIGURATION_PROVIDER; import static org.apache.seata.common.Constants.BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER; import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; @@ -37,4 +39,10 @@ public class SeataCoreAutoConfiguration { public SpringApplicationContextProvider springApplicationContextProvider() { return new SpringApplicationContextProvider(); } + + @Bean(BEAN_NAME_SEATA_FILE_CONFIGURATION_PROVIDER) + @ConditionalOnMissingBean(name = {BEAN_NAME_SEATA_FILE_CONFIGURATION_PROVIDER}) + public SeataFileConfigurationProvider seataFileConfigurationProvider() { + return new SeataFileConfigurationProvider(); + } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SeataFileConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SeataFileConfigurationProvider.java new file mode 100644 index 00000000000..2e9987e07c6 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SeataFileConfigurationProvider.java @@ -0,0 +1,74 @@ +package org.apache.seata.spring.boot.autoconfigure.provider; + +import org.apache.commons.lang.StringUtils; +import org.apache.seata.common.util.CollectionUtils; +import org.apache.seata.config.FileConfiguration; +import org.apache.seata.config.ConfigurationFactory; +import org.apache.seata.config.file.FileConfig; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertiesPropertySource; + +import java.util.*; + +import static org.apache.seata.common.ConfigurationKeys.FILE_ROOT_PREFIX_CONFIG; +import static org.apache.seata.common.ConfigurationKeys.*; + +public class SeataFileConfigurationProvider implements ApplicationContextAware, ApplicationListener { + + private ApplicationContext applicationContext; + + // Prefix list for filtering configuration keys + List prefixList = Arrays.asList(FILE_ROOT_PREFIX_CONFIG, FILE_ROOT_PREFIX_REGISTRY, SERVER_PREFIX, + STORE_PREFIX, METRICS_PREFIX, TRANSPORT_PREFIX); + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + // Only process if the event is for the current application context + if (event.getApplicationContext().equals(this.applicationContext)) { + ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment(); + loadAndAddConfigurations(environment); + } + } + + /** + * Loads configurations from file.conf and registry.conf and adds them to the Spring environment. + * + * @param environment the Spring environment + */ + private void loadAndAddConfigurations(ConfigurableEnvironment environment) { + // Get configurations from file.conf and registry.conf + FileConfiguration configuration = ConfigurationFactory.getOriginFileInstanceRegistry(); + FileConfig fileConfig = configuration.getFileConfig(); + Map configs = fileConfig.getAllConfig(); + + if (CollectionUtils.isNotEmpty(configs)) { + // Optionally merge other configurations + Optional originFileInstance = ConfigurationFactory.getOriginFileInstance(); + originFileInstance.ifPresent(fileConfiguration -> + configs.putAll(fileConfiguration.getFileConfig().getAllConfig()) + ); + + // Convert and filter configurations based on prefix + Properties properties = new Properties(); + configs.forEach((k, v) -> { + if (v instanceof String && StringUtils.isNotEmpty((String) v)) { + if (prefixList.stream().anyMatch(k::startsWith)) { + properties.put(SEATA_FILE_PREFIX_ROOT_CONFIG + k, v); + } + } + }); + + // Add the properties to the environment with the lowest priority + environment.getPropertySources().addLast(new PropertiesPropertySource("seataFileConfig", properties)); + } + } +} \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index c390de9ebe8..45989b0ae01 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -68,6 +68,10 @@ public Configuration provide(Configuration originalConfiguration) { // 1. Get config value from the system property result = originalConfiguration.getConfigFromSys(rawDataId); + if (result == null) { + result = originalConfiguration.getConfig(rawDataId); + } + if (result == null) { String dataId = convertDataId(rawDataId); diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfigurationTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfigurationTest.java new file mode 100644 index 00000000000..61020ad86f3 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfigurationTest.java @@ -0,0 +1,40 @@ +package org.apache.seata.spring.boot.autoconfigure; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = SeataCoreAutoConfiguration.class) +@TestPropertySource(locations = "classpath:application-test.properties") +public class SeataCoreAutoConfigurationTest { + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private Environment environment; + + @Test + public void testSeataPropertiesLoaded() { + // default file.conf + String txServiceGroup = environment.getProperty("seata.store.db.url"); + assertEquals("jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true&configType=file", txServiceGroup, "The transaction service group should be correctly loaded from configuration"); + + + // overridden by application-test.properties + String registryType = environment.getProperty("seata.config.type"); + assertEquals("file", registryType, "The config type should be file"); + + // overridden by application-test.properties + String seataNamespaces = environment.getProperty("seata.config.nacos.namespace"); + assertEquals("seata-test-application.yml", seataNamespaces, "The config type should be file"); + } +} \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties index 8467d6cc7b9..dc1f0851cfc 100755 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/application-test.properties @@ -33,7 +33,7 @@ seata.config.apollo.apollo-config-service=fff seata.config.etcd3.server-addr=aaa seata.config.etcd3.key=bbb -seata.config.nacos.namespace=ddd +seata.config.nacos.namespace=seata-test-application.yml seata.config.nacos.server-addr=aaa seata.config.nacos.group=ccc seata.config.nacos.username=eee diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/file.conf b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/file.conf new file mode 100644 index 00000000000..422c6dd5836 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/file.conf @@ -0,0 +1,67 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#reduce delay for test +## transaction log store, only used in seata-server +store { + ## store mode: file态db + mode = "file" + + ## file store property + file { + ## store location dir + dir = "sessionStore" + } + + ## database store property + db { + ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. + datasource = "dbcp" + ## mysql/oracle/h2/oceanbase etc. + dbType = "mysql" + driverClassName = "com.mysql.jdbc.Driver" + ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param + url = "jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true" + user = "mysql" + password = "mysql" + } +} +server { + recovery { + #schedule committing retry period in milliseconds + committingRetryPeriod = 100 + #schedule asyn committing retry period in milliseconds + asynCommittingRetryPeriod = 100 + #schedule rollbacking retry period in milliseconds + rollbackingRetryPeriod = 100 + #schedule timeout retry period in milliseconds + timeoutRetryPeriod = 100 + } + undo { + logSaveDays = 2 + #schedule delete expired undo_log in milliseconds + logDeletePeriod = 86400000 + } +} +## metrics settings +metrics { + enabled = true + registryType = "compact" + # multi exporters use comma divided + exporterList = "prometheus" + exporterPrometheusPort = 9898 +} \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/registry.conf b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/registry.conf new file mode 100644 index 00000000000..ceb312b5e7e --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/resources/registry.conf @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +config { + type = "file" + + file { + name = "file.conf" + } + nacos { + application = "seata-server" + serverAddr = "127.0.0.1:8848" + namespace = "seata-test" + cluster = "default" + } +} \ No newline at end of file