diff --git a/common/src/main/java/io/seata/common/DefaultValues.java b/common/src/main/java/io/seata/common/DefaultValues.java index bf12a6c3668..5c1dc2b5da2 100644 --- a/common/src/main/java/io/seata/common/DefaultValues.java +++ b/common/src/main/java/io/seata/common/DefaultValues.java @@ -15,8 +15,6 @@ */ package io.seata.common; -import java.time.Duration; - /** * @author xingfudeshi@gmail.com */ @@ -168,17 +166,17 @@ public interface DefaultValues { /** * the constant DEFAULT_RPC_RM_REQUEST_TIMEOUT */ - long DEFAULT_RPC_RM_REQUEST_TIMEOUT = Duration.ofSeconds(15).toMillis(); + long DEFAULT_RPC_RM_REQUEST_TIMEOUT = 15 * 1000L; /** * the constant DEFAULT_RPC_TM_REQUEST_TIMEOUT */ - long DEFAULT_RPC_TM_REQUEST_TIMEOUT = Duration.ofSeconds(30).toMillis(); + long DEFAULT_RPC_TM_REQUEST_TIMEOUT = 30 * 1000L; /** * the constant DEFAULT_RPC_TC_REQUEST_TIMEOUT */ - long DEFAULT_RPC_TC_REQUEST_TIMEOUT = Duration.ofSeconds(15).toMillis(); + long DEFAULT_RPC_TC_REQUEST_TIMEOUT = 15 * 1000L; /** * the constant DEFAULT_XAER_NOTA_RETRY_TIMEOUT diff --git a/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java b/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java index 938268552c6..9ecb7ed0d87 100644 --- a/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java +++ b/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java @@ -21,6 +21,17 @@ * @author slievrly */ public enum FrameworkErrorCode { + + /** + * The Config not found error. + */ + ConfigNotFoundError("0001", "Config not found", "Please check your configuration"), + + /** + * The Config invalid error. + */ + ConfigInvalidError("0002", "Config is invalid", "Please check your configuration"), + /** * 0001 ~ 0099 Configuration related errors */ diff --git a/common/src/main/java/io/seata/common/executor/AbstractInitialize.java b/common/src/main/java/io/seata/common/executor/AbstractInitialize.java new file mode 100644 index 00000000000..907c3fb0510 --- /dev/null +++ b/common/src/main/java/io/seata/common/executor/AbstractInitialize.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.common.executor; + +/** + * The type Abstract initialize. + * + * @author wang.liang + */ +public abstract class AbstractInitialize implements Initialize { + + /** + * Whether initialized + */ + private volatile boolean initialized = false; + + + //region # Override Initialize + + @Override + public boolean isInitialized() { + return initialized; + } + + protected void setInitialized(boolean initialized) { + this.initialized = initialized; + } + + //endregion # Override Initialize +} diff --git a/common/src/main/java/io/seata/common/executor/Cacheable.java b/common/src/main/java/io/seata/common/executor/Cacheable.java new file mode 100644 index 00000000000..e6089398979 --- /dev/null +++ b/common/src/main/java/io/seata/common/executor/Cacheable.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.common.executor; + +/** + * The interface Cacheable. + * + * @author wang.liang + */ +public interface Cacheable { + + /** + * Remove cache by key. + * + * @param key the cache key + * @return the removed cache. + */ + Object removeCache(String key); + + /** + * Clean the caches. + */ + void cleanCaches(); +} + diff --git a/common/src/main/java/io/seata/common/executor/Cleanable.java b/common/src/main/java/io/seata/common/executor/Cleanable.java new file mode 100644 index 00000000000..a9ace05039f --- /dev/null +++ b/common/src/main/java/io/seata/common/executor/Cleanable.java @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.common.executor; + +/** + * The interface Cleanable + * + * @author wang.liang + */ +public interface Cleanable { + + void clean(); + +} diff --git a/common/src/main/java/io/seata/common/executor/Initialize.java b/common/src/main/java/io/seata/common/executor/Initialize.java index 49c41cda288..97e29942846 100644 --- a/common/src/main/java/io/seata/common/executor/Initialize.java +++ b/common/src/main/java/io/seata/common/executor/Initialize.java @@ -27,4 +27,11 @@ public interface Initialize { */ void init(); + /** + * whether initialized + * + * @return the boolean + */ + boolean isInitialized(); + } diff --git a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java index dc56d50f76c..a8c56b99b10 100644 --- a/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java +++ b/common/src/main/java/io/seata/common/loader/EnhancedServiceLoader.java @@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; +import javax.annotation.Nonnull; import io.seata.common.Constants; import io.seata.common.executor.Initialize; @@ -59,6 +60,7 @@ public class EnhancedServiceLoader { * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service, ClassLoader loader) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(loader); } @@ -71,6 +73,7 @@ public static S load(Class service, ClassLoader loader) throws EnhancedSe * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(findClassLoader()); } @@ -84,6 +87,7 @@ public static S load(Class service) throws EnhancedServiceNotFoundExcepti * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service, String activateName) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, findClassLoader()); } @@ -98,6 +102,7 @@ public static S load(Class service, String activateName) throws EnhancedS * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service, String activateName, ClassLoader loader) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, loader); @@ -113,6 +118,7 @@ public static S load(Class service, String activateName, ClassLoader load * @return the s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service, String activateName, Object[] args) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, args, findClassLoader()); @@ -129,6 +135,7 @@ public static S load(Class service, String activateName, Object[] args) * @return the s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull public static S load(Class service, String activateName, Class[] argsType, Object[] args) throws EnhancedServiceNotFoundException { return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, argsType, args, findClassLoader()); @@ -141,6 +148,7 @@ public static S load(Class service, String activateName, Class[] argsT * @param service the service * @return list list */ + @Nonnull public static List loadAll(Class service) { return InnerEnhancedServiceLoader.getServiceLoader(service).loadAll(findClassLoader()); } @@ -154,6 +162,7 @@ public static List loadAll(Class service) { * @param args the args * @return list list */ + @Nonnull public static List loadAll(Class service, Class[] argsType, Object[] args) { return InnerEnhancedServiceLoader.getServiceLoader(service).loadAll(argsType, args, findClassLoader()); } @@ -233,10 +242,11 @@ static List> getAllExtensionClass(Class service) { static List> getAllExtensionClass(Class service, ClassLoader loader) { return InnerEnhancedServiceLoader.getServiceLoader(service).getAllExtensionClass(loader); } + /** * Cannot use TCCL, in the pandora container will cause the class in the plugin not to be loaded * - * @return + * @return the class loader */ private static ClassLoader findClassLoader() { return EnhancedServiceLoader.class.getClassLoader(); @@ -294,6 +304,7 @@ private static void removeAllServiceLoader() { * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull private S load(ClassLoader loader) throws EnhancedServiceNotFoundException { return loadExtension(loader, null, null); } @@ -306,6 +317,7 @@ private S load(ClassLoader loader) throws EnhancedServiceNotFoundException { * @return s s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull private S load(String activateName, ClassLoader loader) throws EnhancedServiceNotFoundException { return loadExtension(activateName, loader, null, null); @@ -320,6 +332,7 @@ private S load(String activateName, ClassLoader loader) * @return the s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull private S load(String activateName, Object[] args, ClassLoader loader) throws EnhancedServiceNotFoundException { Class[] argsType = null; @@ -338,10 +351,11 @@ private S load(String activateName, Object[] args, ClassLoader loader) * @param activateName the activate name * @param argsType the args type * @param args the args - * @param loader the class loader + * @param loader the class loader * @return the s * @throws EnhancedServiceNotFoundException the enhanced service not found exception */ + @Nonnull private S load(String activateName, Class[] argsType, Object[] args, ClassLoader loader) throws EnhancedServiceNotFoundException { return loadExtension(activateName, loader, argsType, args); @@ -349,10 +363,11 @@ private S load(String activateName, Class[] argsType, Object[] args, ClassLoa /** * get all implements - * @param loader the class loader * + * @param loader the class loader * @return list list */ + @Nonnull private List loadAll(ClassLoader loader) { return loadAll(null, null, loader); } @@ -364,20 +379,24 @@ private List loadAll(ClassLoader loader) { * @param args the args * @return list list */ + @Nonnull private List loadAll(Class[] argsType, Object[] args, ClassLoader loader) { List allInstances = new ArrayList<>(); - List> allClazzs = getAllExtensionClass(loader); - if (CollectionUtils.isEmpty(allClazzs)) { + + List> allClasses = getAllExtensionClass(loader); + if (CollectionUtils.isEmpty(allClasses)) { return allInstances; } + try { - for (Class clazz : allClazzs) { + for (Class clazz : allClasses) { ExtensionDefinition definition = classToDefinitionMap.get(clazz); allInstances.add(getExtensionInstance(definition, loader, argsType, args)); } } catch (Throwable t) { throw new EnhancedServiceNotFoundException(t); } + return allInstances; } @@ -391,6 +410,7 @@ private List> getAllExtensionClass(ClassLoader loader) { return loadAllExtensionClass(loader); } + @Nonnull private S loadExtension(ClassLoader loader, Class[] argTypes, Object[] args) { try { loadAllExtensionClass(loader); @@ -406,6 +426,7 @@ private S loadExtension(ClassLoader loader, Class[] argTypes, Object[] args) } @SuppressWarnings("rawtypes") + @Nonnull private S loadExtension(String activateName, ClassLoader loader, Class[] argTypes, Object[] args) { if (StringUtils.isEmpty(activateName)) { @@ -415,17 +436,16 @@ private S loadExtension(String activateName, ClassLoader loader, Class[] argType loadAllExtensionClass(loader); ExtensionDefinition cachedExtensionDefinition = getCachedExtensionDefinition(activateName); return getExtensionInstance(cachedExtensionDefinition, loader, argTypes, args); + } catch (EnhancedServiceNotFoundException e) { + throw e; } catch (Throwable e) { - if (e instanceof EnhancedServiceNotFoundException) { - throw (EnhancedServiceNotFoundException)e; - } else { - throw new EnhancedServiceNotFoundException( - "not found service provider for : " + type.getName() + " caused by " + ExceptionUtils - .getFullStackTrace(e)); - } + throw new EnhancedServiceNotFoundException( + "not found service provider for : " + type.getName() + + " caused by " + ExceptionUtils.getFullStackTrace(e)); } } + @Nonnull private S getExtensionInstance(ExtensionDefinition definition, ClassLoader loader, Class[] argTypes, Object[] args) { if (definition == null) { @@ -450,6 +470,7 @@ private S getExtensionInstance(ExtensionDefinition definition, ClassLoader lo } } + @Nonnull private S createNewExtension(ExtensionDefinition definition, ClassLoader loader, Class[] argTypes, Object[] args) { Class clazz = definition.getServiceClass(); try { @@ -632,9 +653,10 @@ private ExtensionDefinition getCachedExtensionDefinition(String activateName) * @throws NoSuchMethodException the no such method exception * @throws InvocationTargetException the invocation target exception */ + @Nonnull private S initInstance(Class implClazz, Class[] argTypes, Object[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { - S s = null; + S s; if (argTypes != null && args != null) { // Constructor with arguments Constructor constructor = implClazz.getDeclaredConstructor(argTypes); @@ -651,7 +673,8 @@ private S initInstance(Class implClazz, Class[] argTypes, Object[] args) /** * Helper Class for hold a value. - * @param + * + * @param the type */ private static class Holder { private volatile T value; @@ -666,5 +689,4 @@ private T get() { } } - -} \ No newline at end of file +} diff --git a/common/src/main/java/io/seata/common/util/ConvertUtils.java b/common/src/main/java/io/seata/common/util/ConvertUtils.java new file mode 100644 index 00000000000..696d5038916 --- /dev/null +++ b/common/src/main/java/io/seata/common/util/ConvertUtils.java @@ -0,0 +1,85 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.common.util; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.seata.common.exception.NotSupportYetException; + +/** + * The type Convert utils. + * + * @author wang.liang + */ +public class ConvertUtils { + + private ConvertUtils() { + } + + + @SuppressWarnings("unchecked") + public static T convert(Object value, Class targetType) { + if (value == null) { + return null; + } + + if (targetType.isAssignableFrom(value.getClass())) { + return (T)value; + } + + if (String.class.equals(targetType)) { + return (T)String.valueOf(value); + } + + if (ObjectUtils.isBlank(value)) { + // Keep the blank value for List. + if (List.class.equals(targetType)) { + return (T)new ArrayList<>(); + } + + return null; + } + + if (Long.class.equals(targetType)) { + return (T)Long.valueOf(String.valueOf(value)); + } + if (Integer.class.equals(targetType)) { + return (T)Integer.valueOf(String.valueOf(value)); + } + if (Short.class.equals(targetType)) { + return (T)Short.valueOf(String.valueOf(value)); + } + if (Boolean.class.equals(targetType)) { + return (T)Boolean.valueOf(String.valueOf(value)); + } + if (Duration.class.equals(targetType)) { + return (T)DurationUtil.parse(String.valueOf(value)); + } + if (List.class.equals(targetType)) { + String str = String.valueOf(value); + String regex = ","; + if (str.contains(";")) { + regex = ";"; + } + return (T)Arrays.asList(str.split(regex)); + } + + throw new NotSupportYetException("Not support convert type from '" + value.getClass().getName() + "' to '" + targetType.getName() + "'."); + } +} diff --git a/common/src/main/java/io/seata/common/util/ObjectUtils.java b/common/src/main/java/io/seata/common/util/ObjectUtils.java new file mode 100644 index 00000000000..e5aea99f7ff --- /dev/null +++ b/common/src/main/java/io/seata/common/util/ObjectUtils.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.common.util; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + +/** + * The type Object utils. + * + * @author wang.liang + */ +public class ObjectUtils { + + private ObjectUtils() { + } + + + public static boolean isBlank(Object obj) { + if (obj == null) { + return true; + } + + Class clazz = obj.getClass(); + + if (CharSequence.class.isAssignableFrom(clazz)) { + return StringUtils.isBlank(String.valueOf(obj)); + } + if (Character.class.isAssignableFrom(clazz)) { + return Character.isWhitespace((Character)obj); + } + if (Map.class.isAssignableFrom(clazz)) { + return ((Map)obj).isEmpty(); + } + if (Collection.class.isAssignableFrom(clazz)) { + return ((Collection)obj).isEmpty(); + } + if (clazz.isArray()) { + return Array.getLength(obj) == 0; + } + + return StringUtils.isBlank(String.valueOf(obj)); + } + + public static boolean isNotBlank(Object obj) { + return !isBlank(obj); + } +} diff --git a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSource.java similarity index 75% rename from config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java rename to config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSource.java index 55c5d4cb3e5..c1444581869 100644 --- a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java +++ b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSource.java @@ -23,34 +23,36 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.ConfigService; import com.ctrip.framework.apollo.enums.PropertyChangeType; import com.ctrip.framework.apollo.model.ConfigChange; -import io.seata.common.exception.NotSupportYetException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; import io.seata.config.ConfigFuture; import io.seata.config.Configuration; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; -import io.seata.config.ConfigurationChangeType; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; +import io.seata.config.changelistener.ConfigurationChangeType; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_CONFIG; /** - * The type Apollo configuration. + * The type Apollo config source. * * @author kl @kailing.pub */ -public class ApolloConfiguration extends AbstractConfiguration { +public class ApolloConfigSource implements RemoteConfigSource, ConfigurationChangeListenerManager { - private static final String REGISTRY_TYPE = "apollo"; + private static final String CONFIG_TYPE = "apollo"; private static final String APP_ID = "appId"; private static final String APOLLO_META = "apolloMeta"; private static final String APOLLO_SECRET = "apolloAccessKeySecret"; @@ -63,22 +65,22 @@ public class ApolloConfiguration extends AbstractConfiguration { private static final String PROP_APOLLO_CLUSTER = "apollo.cluster"; private static final String NAMESPACE = "namespace"; private static final String DEFAULT_NAMESPACE = "application"; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); private static volatile Config config; private ExecutorService configOperateExecutor; private static final int CORE_CONFIG_OPERATE_THREAD = 1; private static final ConcurrentMap> LISTENER_SERVICE_MAP = new ConcurrentHashMap<>(); private static final int MAX_CONFIG_OPERATE_THREAD = 2; - private static volatile ApolloConfiguration instance; + private static volatile ApolloConfigSource instance; @SuppressWarnings("lgtm[java/unsafe-double-checked-locking-init-order]") - private ApolloConfiguration() { + private ApolloConfigSource() { readyApolloConfig(); if (config == null) { - synchronized (ApolloConfiguration.class) { + synchronized (ApolloConfigSource.class) { if (config == null) { - config = ConfigService.getConfig(FILE_CONFIG.getConfig(getApolloNamespaceKey(), DEFAULT_NAMESPACE)); + config = ConfigService.getConfig(CONFIG.getString(getApolloNamespaceKey(), DEFAULT_NAMESPACE)); configOperateExecutor = new ThreadPoolExecutor(CORE_CONFIG_OPERATE_THREAD, MAX_CONFIG_OPERATE_THREAD, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), @@ -90,7 +92,7 @@ private ApolloConfiguration() { } ConfigChange change = changeEvent.getChange(key); ConfigurationChangeEvent event = new ConfigurationChangeEvent(key, change.getNamespace(), - change.getOldValue(), change.getNewValue(), getChangeType(change.getChangeType())); + change.getOldValue(), change.getNewValue(), getChangeType(change.getChangeType()), this); LISTENER_SERVICE_MAP.get(key).forEach(listener -> listener.onProcessEvent(event)); } }); @@ -104,11 +106,11 @@ private ApolloConfiguration() { * * @return the instance */ - public static ApolloConfiguration getInstance() { + public static ApolloConfigSource getInstance() { if (instance == null) { - synchronized (ApolloConfiguration.class) { + synchronized (ApolloConfigSource.class) { if (instance == null) { - instance = new ApolloConfiguration(); + instance = new ApolloConfigSource(); } } } @@ -116,31 +118,16 @@ public static ApolloConfiguration getInstance() { } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { - ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, + public String getLatestConfig(String dataId, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.GET, timeoutMills); configOperateExecutor.submit(() -> { - String result = config.getProperty(dataId, defaultValue); + String result = config.getProperty(dataId, null); configFuture.setResult(result); }); return (String) configFuture.get(); } - @Override - public boolean putConfig(String dataId, String content, long timeoutMills) { - throw new NotSupportYetException("not support putConfig"); - } - - @Override - public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { - throw new NotSupportYetException("not support atomic operation putConfigIfAbsent"); - } - - @Override - public boolean removeConfig(String dataId, long timeoutMills) { - throw new NotSupportYetException("not support removeConfig"); - } - @Override public void addConfigListener(String dataId, ConfigurationChangeListener listener) { if (StringUtils.isBlank(dataId) || listener == null) { @@ -161,6 +148,11 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list } } + @Override + public Set getListenedConfigDataIds() { + return LISTENER_SERVICE_MAP.keySet(); + } + @Override public Set getConfigListeners(String dataId) { return LISTENER_SERVICE_MAP.get(dataId); @@ -169,31 +161,31 @@ public Set getConfigListeners(String dataId) { private void readyApolloConfig() { Properties properties = System.getProperties(); if (!properties.containsKey(PROP_APP_ID)) { - String appId = FILE_CONFIG.getConfig(getApolloAppIdFileKey()); + String appId = CONFIG.getString(getApolloAppIdFileKey()); if (StringUtils.isNotBlank(appId)) { System.setProperty(PROP_APP_ID, appId); } } if (!properties.containsKey(PROP_APOLLO_META)) { - String apolloMeta = FILE_CONFIG.getConfig(getApolloMetaFileKey()); + String apolloMeta = CONFIG.getString(getApolloMetaFileKey()); if (StringUtils.isNotBlank(apolloMeta)) { System.setProperty(PROP_APOLLO_META, apolloMeta); } } if (!properties.containsKey(PROP_APOLLO_SECRET)) { - String apolloAccesskeySecret = FILE_CONFIG.getConfig(getApolloSecretFileKey()); + String apolloAccesskeySecret = CONFIG.getString(getApolloSecretFileKey()); if (StringUtils.isNotBlank(apolloAccesskeySecret)) { System.setProperty(PROP_APOLLO_SECRET, apolloAccesskeySecret); } } if (!properties.containsKey(APOLLO_CLUSTER)) { - String apolloCluster = FILE_CONFIG.getConfig(getApolloCluster()); + String apolloCluster = CONFIG.getString(getApolloCluster()); if (StringUtils.isNotBlank(apolloCluster)) { System.setProperty(PROP_APOLLO_CLUSTER, apolloCluster); } } if (!properties.containsKey(APOLLO_CONFIG_SERVICE)) { - String apolloConfigService = FILE_CONFIG.getConfig(getApolloConfigService()); + String apolloConfigService = CONFIG.getString(getApolloConfigService()); if (StringUtils.isNotBlank(apolloConfigService)) { System.setProperty(PROP_APOLLO_CONFIG_SERVICE, apolloConfigService); } else { @@ -204,33 +196,39 @@ private void readyApolloConfig() { } } + @Nonnull + @Override + public String getName() { + return CONFIG_TYPE; + } + @Override - public String getTypeName() { - return REGISTRY_TYPE; + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; } public static String getApolloMetaFileKey() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, APOLLO_META); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, APOLLO_META); } public static String getApolloSecretFileKey() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, APOLLO_SECRET); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, APOLLO_SECRET); } public static String getApolloAppIdFileKey() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, APP_ID); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, APP_ID); } public static String getApolloNamespaceKey() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, NAMESPACE); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, NAMESPACE); } public static String getApolloCluster() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, APOLLO_CLUSTER); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, APOLLO_CLUSTER); } public static String getApolloConfigService() { - return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, REGISTRY_TYPE, APOLLO_CONFIG_SERVICE); + return String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_CONFIG, CONFIG_TYPE, APOLLO_CONFIG_SERVICE); } diff --git a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigurationProvider.java b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSourceProvider.java similarity index 76% rename from config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigurationProvider.java rename to config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSourceProvider.java index 70205b1764e..44730760019 100644 --- a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigurationProvider.java +++ b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfigSourceProvider.java @@ -17,15 +17,15 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; /** * @author xingfudeshi@gmail.com */ @LoadLevel(name = "Apollo", order = 1) -public class ApolloConfigurationProvider implements ConfigurationProvider { +public class ApolloConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - return ApolloConfiguration.getInstance(); + public void provide(Configuration configuration) { + configuration.addSource(ApolloConfigSource.getInstance()); } } diff --git a/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index 5f4a891a239..00000000000 --- a/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.apollo.ApolloConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..3d448a07445 --- /dev/null +++ b/config/seata-config-apollo/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.apollo.ApolloConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSource.java similarity index 89% rename from config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java rename to config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSource.java index 33092b86f33..379498ae414 100644 --- a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java +++ b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSource.java @@ -19,15 +19,16 @@ import java.net.InetSocketAddress; import java.util.Enumeration; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; import com.ecwid.consul.v1.ConsulClient; import com.ecwid.consul.v1.QueryParams; @@ -38,30 +39,34 @@ import io.seata.common.util.CollectionUtils; import io.seata.common.util.NetUtil; import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; import io.seata.config.ConfigFuture; import io.seata.config.Configuration; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; import io.seata.config.processor.ConfigProcessor; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; +import io.seata.config.source.UpdatableConfigSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_CONFIG; /** - * The type Consul configuration. + * The type Consul config source. * * @author xingfudeshi @gmail.com */ -public class ConsulConfiguration extends AbstractConfiguration { - private volatile static ConsulConfiguration instance; +public class ConsulConfigSource implements RemoteConfigSource + , UpdatableConfigSource, ConfigurationChangeListenerManager { + private volatile static ConsulConfigSource instance; private volatile static ConsulClient client; - private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfiguration.class); - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigSource.class); + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); private static final String SERVER_ADDR_KEY = "serverAddr"; private static final String CONSUL_CONFIG_KEY = "key"; private static final String CONFIG_TYPE = "consul"; @@ -82,7 +87,7 @@ public class ConsulConfiguration extends AbstractConfiguration { private static final int DEFAULT_WATCH_TIMEOUT = 60; private static final long CAS = 0L; - private ConsulConfiguration() { + private ConsulConfigSource() { consulNotifierExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("consul-config-executor", THREAD_POOL_NUM)); @@ -94,11 +99,11 @@ private ConsulConfiguration() { * * @return instance */ - public static ConsulConfiguration getInstance() { + public static ConsulConfigSource getInstance() { if (instance == null) { - synchronized (ConsulConfiguration.class) { + synchronized (ConsulConfigSource.class) { if (instance == null) { - instance = new ConsulConfiguration(); + instance = new ConsulConfigSource(); } } } @@ -106,11 +111,11 @@ public static ConsulConfiguration getInstance() { } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, long timeoutMills) { String value = seataConfig.getProperty(dataId); if (value == null) { - ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, + ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.GET, timeoutMills); consulNotifierExecutor.execute(() -> complete(getConsulClient().getKVValue(dataId, getAclToken()), configFuture)); value = (String) configFuture.get(); @@ -178,7 +183,7 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene .add(consulListener); // Start config change listener for the dataId. - consulListener.onProcessEvent(new ConfigurationChangeEvent()); + consulListener.onProcessEvent(new ConfigurationChangeEvent(this)); } @Override @@ -200,16 +205,27 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list } } + @Override + public Set getListenedConfigDataIds() { + return CONFIG_LISTENERS_MAP.keySet(); + } + @Override public Set getConfigListeners(String dataId) { return CONFIG_LISTENERS_MAP.get(dataId); } + @Nonnull @Override - public String getTypeName() { + public String getName() { return CONFIG_TYPE; } + @Override + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + } + /** * get consul client * @@ -217,9 +233,9 @@ public String getTypeName() { */ private static ConsulClient getConsulClient() { if (client == null) { - synchronized (ConsulConfiguration.class) { + synchronized (ConsulConfigSource.class) { if (client == null) { - String serverAddr = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); + String serverAddr = CONFIG.getString(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); InetSocketAddress inetSocketAddress = NetUtil.toInetSocketAddress(serverAddr); client = new ConsulClient(inetSocketAddress.getHostName(), inetSocketAddress.getPort()); } @@ -235,7 +251,7 @@ private static ConsulClient getConsulClient() { */ private static String getAclToken() { String aclToken = StringUtils.isNotBlank(System.getProperty(ACL_TOKEN)) ? System.getProperty(ACL_TOKEN) - : FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + ACL_TOKEN); + : CONFIG.getString(FILE_CONFIG_KEY_PREFIX + ACL_TOKEN); return StringUtils.isNotBlank(aclToken) ? aclToken : null; } @@ -271,7 +287,7 @@ private void initSeataConfig() { } // Start config change listener for the ConsulConfigKey,default value is "seata.properties". ConsulListener consulListener = new ConsulListener(getConsulConfigKey(), null); - consulListener.onProcessEvent(new ConfigurationChangeEvent()); + consulListener.onProcessEvent(new ConfigurationChangeEvent(this)); } private static String getConsulDataType() { @@ -279,7 +295,7 @@ private static String getConsulDataType() { } private static String getConsulConfigKey() { - return FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + CONSUL_CONFIG_KEY, DEFAULT_CONSUL_CONFIG_KEY_VALUE); + return CONFIG.getString(FILE_CONFIG_KEY_PREFIX + CONSUL_CONFIG_KEY, DEFAULT_CONSUL_CONFIG_KEY_VALUE); } private static String getSeataConfigStr() { diff --git a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSourceProvider.java similarity index 76% rename from config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java rename to config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSourceProvider.java index 7113b8953a8..1f6f9bb61b2 100644 --- a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java +++ b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigSourceProvider.java @@ -17,15 +17,15 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; /** * @author xingfudeshi@gmail.com */ @LoadLevel(name = "Consul", order = 1) -public class ConsulConfigurationProvider implements ConfigurationProvider { +public class ConsulConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - return ConsulConfiguration.getInstance(); + public void provide(Configuration configuration) { + configuration.addSource(ConsulConfigSource.getInstance()); } } diff --git a/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index d4de8482081..00000000000 --- a/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.consul.ConsulConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..e706687fbc1 --- /dev/null +++ b/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.consul.ConsulConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-core/pom.xml b/config/seata-config-core/pom.xml index 72098b12471..f167cca61e2 100644 --- a/config/seata-config-core/pom.xml +++ b/config/seata-config-core/pom.xml @@ -40,10 +40,6 @@ org.yaml snakeyaml - - net.bytebuddy - byte-buddy - diff --git a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java index af1ecaf1fb2..30562ea117b 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/AbstractConfiguration.java @@ -15,156 +15,148 @@ */ package io.seata.config; -import java.time.Duration; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -import io.seata.common.util.DurationUtil; +import io.seata.common.executor.AbstractInitialize; +import io.seata.common.util.ConvertUtils; import io.seata.common.util.StringUtils; +import io.seata.config.source.ConfigSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type Abstract configuration. * * @author slievrly + * @author wang.liang */ -public abstract class AbstractConfiguration implements Configuration { +public abstract class AbstractConfiguration extends AbstractInitialize implements Configuration { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfiguration.class); - /** - * The constant DEFAULT_CONFIG_TIMEOUT. - */ - protected static final long DEFAULT_CONFIG_TIMEOUT = 5 * 1000; /** - * The constant DEFAULT_XXX. + * The name */ - public static final short DEFAULT_SHORT = (short)0; - public static final int DEFAULT_INT = 0; - public static final long DEFAULT_LONG = 0L; - public static final Duration DEFAULT_DURATION = Duration.ZERO; - public static final boolean DEFAULT_BOOLEAN = false; + @Nonnull + private final String name; - @Override - public short getShort(String dataId, short defaultValue, long timeoutMills) { - String result = getConfig(dataId, timeoutMills); - return StringUtils.isBlank(result) ? defaultValue : Short.parseShort(result); + protected AbstractConfiguration(@Nonnull String name) { + Objects.requireNonNull(name, "The 'name' must not be null."); + this.name = name; } - @Override - public short getShort(String dataId, short defaultValue) { - return getShort(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); - } - @Override - public short getShort(String dataId) { - return getShort(dataId, DEFAULT_SHORT); - } + //region # Get config from sources - @Override - public int getInt(String dataId, int defaultValue, long timeoutMills) { - String result = getConfig(dataId, timeoutMills); - return StringUtils.isBlank(result) ? defaultValue : Integer.parseInt(result); - } + @Nullable + protected ConfigInfo getConfigFromSources(String dataId, long timeoutMills) { + if (StringUtils.isBlank(dataId)) { + return null; + } - @Override - public int getInt(String dataId, int defaultValue) { - return getInt(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); - } + // get sources + List sources = this.getSources(); + + String blankValue = null; + ConfigSource blankValueFromSource = null; + + String value; + for (ConfigSource source : sources) { + value = source.getLatestConfig(dataId, timeoutMills); + + if (value == null) { + continue; + } + + if (StringUtils.isBlank(value)) { + if (blankValue == null) { + blankValue = value; + blankValueFromSource = source; + } + LOGGER.debug("Skip config '{}' blank value '{}' of type [{}] from source '{}' by configuration '{}'.", + dataId, value, value.getClass().getName(), source.getName(), this.getName()); + continue; + } + + if (this.printGetSuccessLog) { + LOGGER.debug("Get config ['{}' = '{}'] of type [{}] from source '{}' by configuration '{}'.", + dataId, value, value.getClass().getName(), source.getName(), this.getName()); + } + + // 1. Not blank value. + return new ConfigInfo(dataId, value, source); + } - @Override - public int getInt(String dataId) { - return getInt(dataId, DEFAULT_INT); - } + if (blankValue != null) { + // 2. Is blank value. + return new ConfigInfo(dataId, blankValue, blankValueFromSource); + } - @Override - public long getLong(String dataId, long defaultValue, long timeoutMills) { - String result = getConfig(dataId, timeoutMills); - return StringUtils.isBlank(result) ? defaultValue : Long.parseLong(result); + // 3. null + return null; } - @Override - public long getLong(String dataId, long defaultValue) { - return getLong(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + @Nullable + protected ConfigInfo getConfigFromSources(String dataId) { + return this.getConfigFromSources(dataId, DEFAULT_CONFIG_TIMEOUT); } - @Override - public long getLong(String dataId) { - return getLong(dataId, DEFAULT_LONG); - } + //endregion # Get config from sources - @Override - public Duration getDuration(String dataId) { - return getDuration(dataId, DEFAULT_DURATION); - } - @Override - public Duration getDuration(String dataId, Duration defaultValue) { - return getDuration(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); - } + //region # Override Configuration @Override - public Duration getDuration(String dataId, Duration defaultValue, long timeoutMills) { - String result = getConfig(dataId, timeoutMills); - return StringUtils.isBlank(result) ? defaultValue : DurationUtil.parse(result); - } + public T getConfig(String dataId, T defaultValue, long timeoutMills, Class dataType) { + if (StringUtils.isBlank(dataId)) { + return null; + } - @Override - public boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills) { - String result = getConfig(dataId, timeoutMills); - return StringUtils.isBlank(result) ? defaultValue : Boolean.parseBoolean(result); - } + ConfigInfo configInfo = this.getConfigFromSources(dataId, timeoutMills); - @Override - public boolean getBoolean(String dataId, boolean defaultValue) { - return getBoolean(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); - } + if (configInfo != null + && (StringUtils.isNotBlank(configInfo.getValue()) || defaultValue == null)) { + // May be null or blank. + return ConvertUtils.convert(configInfo.getValue(), dataType); + } - @Override - public boolean getBoolean(String dataId) { - return getBoolean(dataId, DEFAULT_BOOLEAN); + return defaultValue; } + @Nonnull @Override - public String getConfig(String dataId, String defaultValue) { - return getConfig(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + public String getName() { + return name; } - @Override - public String getConfig(String dataId, long timeoutMills) { - return getConfig(dataId, null, timeoutMills); - } + //endregion # Override Configuration - @Override - public String getConfig(String dataId, String content, long timeoutMills) { - String value = getConfigFromSys(dataId); - if (value != null) { - return value; - } - return getLatestConfig(dataId, content, timeoutMills); - } - @Override - public String getConfig(String dataId) { - return getConfig(dataId, DEFAULT_CONFIG_TIMEOUT); - } + //region # printGetSuccessLog - @Override - public boolean putConfig(String dataId, String content) { - return putConfig(dataId, content, DEFAULT_CONFIG_TIMEOUT); + /** + * Whether to print the get success log. Used to avoid printing the log repeatedly. + */ + private volatile boolean printGetSuccessLog = true; + + public void enablePrintGetSuccessLog() { + this.printGetSuccessLog = true; } - @Override - public boolean putConfigIfAbsent(String dataId, String content) { - return putConfigIfAbsent(dataId, content, DEFAULT_CONFIG_TIMEOUT); + public void disablePrintGetSuccessLog() { + this.printGetSuccessLog = false; } + //endregion # printGetSuccessLog + + @Override - public boolean removeConfig(String dataId) { - return removeConfig(dataId, DEFAULT_CONFIG_TIMEOUT); + public String toString() { + return "[name='" + getName() + "']"; } - - /** - * Gets type name. - * - * @return the type name - */ - public abstract String getTypeName(); } diff --git a/config/seata-config-core/src/main/java/io/seata/config/CacheableConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/CacheableConfiguration.java new file mode 100644 index 00000000000..34de09971e0 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/CacheableConfiguration.java @@ -0,0 +1,201 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import io.seata.common.executor.Cacheable; +import io.seata.common.executor.Cleanable; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.ConvertUtils; +import io.seata.common.util.ObjectUtils; +import io.seata.common.util.StringUtils; +import io.seata.config.changelistener.ConfigChangeListenerUtils; +import io.seata.config.changelistener.ConfigurationChangeType; +import io.seata.config.source.ConfigSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The type Cacheable configuration. + * + * @author wang.liang + */ +public class CacheableConfiguration extends SimpleConfiguration + implements Cacheable, Cleanable { + + private static final Logger LOGGER = LoggerFactory.getLogger(CacheableConfiguration.class); + + private static final String NAME_PREFIX = "cache:"; + + + /** + * The cache map. + */ + @Nonnull + private final ConcurrentMap configCacheMap; + + + public CacheableConfiguration(String name, @Nonnull ConcurrentMap configCacheMap) { + super(NAME_PREFIX + name); + + Objects.requireNonNull(configCacheMap, "The 'configCacheMap' must not be null."); + this.configCacheMap = configCacheMap; + } + + public CacheableConfiguration(String name) { + super(NAME_PREFIX + name); + this.configCacheMap = new ConcurrentHashMap<>(); + } + + + //region # Override AbstractConfiguration + + /** + * Override to use cache + */ + @Override + public T getConfig(String dataId, T defaultValue, long timeoutMills, Class dataType) { + if (StringUtils.isBlank(dataId)) { + return null; + } + + // Get config from cache + ConfigCache cache = CollectionUtils.computeIfAbsent(configCacheMap, dataId, key -> { + // Get config from sources + ConfigInfo config = this.getConfigFromSources(dataId, timeoutMills); + // Wrap config, also when config is null or blank + return ConfigCache.fromConfigInfo(dataId, config, dataType); + }); + + T value = cache.getConfig(); + if (value != null) { + // If the same config is obtained from cache with different types multiple times, + // The dataType will be inconsistent with the class of the value. + if (!dataType.isAssignableFrom(value.getClass())) { + LOGGER.warn("The dataType '{}' used to get config '{}' is different from type '{}' in the cache." + + " Recommended to use the same type multiple times.", + dataType.getName(), dataId, value.getClass().getName()); + + // Convert to the targetType + value = ConvertUtils.convert(value, dataType); + } + + if (ObjectUtils.isNotBlank(value)) { + return value; + } + } + + // Return default value + if (defaultValue != null) { + LOGGER.debug("Config '{}' not found, returned defaultValue '{}' of type [{}] from parameter by configuration '{}'.", + dataId, defaultValue, defaultValue.getClass().getName(), this.getName()); + + return defaultValue; + } + + // May be null or blank. + return value; + } + + //endregion # Override AbstractConfiguration + + + //region # Override ConfigSourceManager + + @Override + public void onAddedSource(ConfigSource newSource, List higherSources, List lowerSources) { + super.onAddedSource(newSource, higherSources, lowerSources); + + // Compare the priority of the config in the cache with the value in the newSource + this.configCacheMap.forEach((dataId, oldCache) -> { + String oldValue = oldCache.getStringValue(); + + if (oldValue != null && oldCache.getSource().getOrder() > newSource.getOrder()) { + // the source in the cache is higher than newSource + return; + } + + String newValue = newSource.getLatestConfig(oldCache.getDataId()); + if (newValue != null && !Objects.equals(oldValue, newValue)) { + ConfigurationChangeType type = ConfigChangeListenerUtils.getChangeType(oldValue, newValue); + this.changeCache(oldCache, newSource, newValue, type, "addSource_and_cacheChanged"); + } + }); + } + + protected void changeCache(ConfigCache oldCache, ConfigSource newSource, String newValue, ConfigurationChangeType type, String namespace) { + String dataId = oldCache.getDataId(); + + ConfigCache newCache = ConfigCache.create(dataId, newValue, oldCache.getType(), newSource); + this.configCacheMap.put(dataId, newCache); + this.onCacheChanged(new ConfigCacheChangeEvent(dataId, oldCache, newCache, type, namespace)); + } + + /** + * After the cache changed, trigger this method + * + * @param event the event + */ + protected void onCacheChanged(ConfigCacheChangeEvent event) { + // default do nothing + } + + //endregion # Override ConfigSourceManager + + + //region # Override Cacheable, Cleanable + + + @Override + public ConfigCache removeCache(String key) { + return this.configCacheMap.remove(key); + } + + @Override + public void cleanCaches() { + this.configCacheMap.clear(); + } + + @Override + public void clean() { + this.cleanCaches(); + } + + @Nonnull + protected Map getCacheMap() { + return this.configCacheMap; + } + + @Nullable + protected ConfigCache getCache(String dataId) { + return this.configCacheMap.get(dataId); + } + + @Nullable + protected Object getCacheValue(String dataId) { + ConfigCache configCache = this.getCache(dataId); + return configCache != null ? configCache.getValue() : null; + } + + //endregion # Override Cacheable, Cleanable +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigCache.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigCache.java new file mode 100644 index 00000000000..1654e83ecf1 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigCache.java @@ -0,0 +1,171 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import io.seata.common.util.ConvertUtils; +import io.seata.config.source.ConfigSource; + +/** + * The type ConfigCache. + * + * @author wang.liang + */ +public class ConfigCache implements Serializable { + private static final long serialVersionUID = 1L; + + private static final NonConfigSource NON_CONFIG_SOURCE = new NonConfigSource(); + + + //region Class + + private final String dataId; + + private final Object value; + private final String stringValue; + private final Class type; + + private final ConfigSource source; + + // cache time + private final Date time = new Date(); + private String timeStr; + + + private ConfigCache(@Nonnull String dataId, @Nullable Object value, String stringValue, @Nonnull Class type, @Nonnull ConfigSource source) { + Objects.requireNonNull(dataId, "The 'dataId' must not be null."); + Objects.requireNonNull(source, "The 'source' must not be null."); + Objects.requireNonNull(type, "The 'type' must be not null"); + + this.dataId = dataId; + this.value = value; + this.stringValue = stringValue; + this.type = type; + this.source = source; + } + + @Nonnull + public String getDataId() { + return dataId; + } + + @Nullable + public Object getValue() { + return value; + } + + @Nullable + public T getConfig() { + return (T)value; + } + + public String getStringValue() { + return stringValue; + } + + @Nonnull + public Class getType() { + return type; + } + + @Nonnull + public ConfigSource getSource() { + return source; + } + + @Nonnull + public String getSourceName() { + return source.getName(); + } + + @Nonnull + public Date getTime() { + return time; + } + + + @Nonnull + public String getTimeStr() { + if (timeStr == null) { + timeStr = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS").format(new Date()); + } + + return timeStr; + } + + //endregion Class + + + //region static + + @Nonnull + public static ConfigCache create(String dataId, String stringValue, Class type, ConfigSource source) { + Object value = ConvertUtils.convert(stringValue, type); + return new ConfigCache(dataId, value, stringValue, type, source); + } + + //endregion static + + + @Override + public String toString() { + return '[' + + "c=" + (stringValue != null ? ('\'' + stringValue + '\'') : null) + + ", t=" + type.getSimpleName() + + ", s='" + getSourceName() + '\'' + + ']'; + } + + + public static ConfigCache fromConfigInfo(String dataId, ConfigInfo config, Class dataType) { + String stringValue = null; + ConfigSource source; + if (config != null) { + stringValue = config.getValue(); + source = config.getSource(); + } else { + source = NON_CONFIG_SOURCE; + } + + // Wrap config, also when config is null or blank + return create(dataId, stringValue, dataType, source); + } + + + private static class NonConfigSource implements ConfigSource { + @Override + public String getLatestConfig(String dataId, long timeoutMills) { + return null; + } + + @Nonnull + @Override + public String getName() { + return "non"; + } + + @Override + public int getOrder() { + return Integer.MAX_VALUE; + } + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigCacheChangeEvent.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigCacheChangeEvent.java new file mode 100644 index 00000000000..d6af8d5336c --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigCacheChangeEvent.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import io.seata.config.changelistener.ConfigurationChangeType; + +/** + * The type ConfigCacheChangeEvent. + * + * @author wang.liang + */ +public class ConfigCacheChangeEvent { + + private final String dataId; + + private final ConfigCache oldCache; + private final ConfigCache newCache; + private final ConfigurationChangeType type; + private final String namespace; + + + public ConfigCacheChangeEvent(String dataId, ConfigCache oldCache, ConfigCache newCache, ConfigurationChangeType type, String namespace) { + this.dataId = dataId; + this.oldCache = oldCache; + this.newCache = newCache; + this.type = type; + this.namespace = namespace; + } + + public String getDataId() { + return dataId; + } + + public ConfigCache getOldCache() { + return oldCache; + } + + public ConfigCache getNewCache() { + return newCache; + } + + public ConfigurationChangeType getType() { + return type; + } + + public String getNamespace() { + return namespace; + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigInfo.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigInfo.java new file mode 100644 index 00000000000..fbe4e4e1269 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigInfo.java @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.util.Objects; +import javax.annotation.Nonnull; + +import io.seata.config.source.ConfigSource; + +/** + * The type ConfigInfo. + * + * @author wang.liang + */ +public class ConfigInfo { + + private final String dataId; + private final String value; + private final ConfigSource source; + + + public ConfigInfo(String dataId, String value, ConfigSource source) { + Objects.requireNonNull(value, "The 'config' value must not be null."); + Objects.requireNonNull(source, "The 'source' must not be null."); + + this.dataId = dataId; + this.value = value; + this.source = source; + } + + public String getDataId() { + return dataId; + } + + @Nonnull + public String getValue() { + return value; + } + + @Nonnull + public ConfigSource getSource() { + return source; + } + + public String getSourceName() { + return source.getName(); + } + + + @Override + public String toString() { + return '{' + + "v=" + value + + ", s=" + getSourceName() + + '}'; + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java index ecab723feda..4697eb5dcad 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/Configuration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/Configuration.java @@ -16,299 +16,240 @@ package io.seata.config; import java.time.Duration; -import java.util.Map; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; -import io.seata.common.util.StringUtils; +import io.seata.common.util.ConvertUtils; +import io.seata.config.source.ConfigSourceManager; /** * The interface Configuration. * * @author slievrly + * @author wang.liang */ -public interface Configuration { +public interface Configuration extends ConfigSourceManager { - Map ENV_MAP = System.getenv(); /** - * Gets short. - * - * @param dataId the data id - * @param defaultValue the default value - * @param timeoutMills the timeout mills - * @return the short + * The constant DEFAULT_CONFIG_TIMEOUT. */ - short getShort(String dataId, short defaultValue, long timeoutMills); + long DEFAULT_CONFIG_TIMEOUT = 5 * 1000; /** - * Gets short. - * - * @param dataId the data id - * @param defaultValue the default value - * @return the int + * The constant DEFAULT_XXX. */ - short getShort(String dataId, short defaultValue); + short DEFAULT_SHORT = (short)0; + int DEFAULT_INT = 0; + long DEFAULT_LONG = 0L; + Duration DEFAULT_DURATION = Duration.ZERO; + boolean DEFAULT_BOOLEAN = false; + /** - * Gets short. + * Get name * - * @param dataId the data id - * @return the int + * @return the name */ - short getShort(String dataId); + @Nonnull + String getName(); /** - * Gets int. + * Get config. * * @param dataId the data id * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the int + * @param dataType the data type + * @param the data type + * @return the Latest config */ - int getInt(String dataId, int defaultValue, long timeoutMills); + T getConfig(String dataId, T defaultValue, long timeoutMills, Class dataType); - /** - * Gets int. - * - * @param dataId the data id - * @param defaultValue the default value - * @return the int - */ - int getInt(String dataId, int defaultValue); + default T getConfig(String dataId, T defaultValue, Class dataType) { + return getConfig(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT, dataType); + } - /** - * Gets int. - * - * @param dataId the data id - * @return the int - */ - int getInt(String dataId); + default T getConfig(String dataId, long timeoutMills, Class dataType) { + return getConfig(dataId, null, timeoutMills, dataType); + } + + default T getConfig(String dataId, Class dataType) { + return getConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT, dataType); + } - /** - * Gets long. - * - * @param dataId the data id - * @param defaultValue the default value - * @param timeoutMills the timeout mills - * @return the long - */ - long getLong(String dataId, long defaultValue, long timeoutMills); /** - * Gets long. + * Gets string config. * * @param dataId the data id * @param defaultValue the default value - * @return the long + * @param timeoutMills the timeout mills + * @return the config */ - long getLong(String dataId, long defaultValue); + default String getString(String dataId, String defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, String.class); + } - /** - * Gets long. - * - * @param dataId the data id - * @return the long - */ - long getLong(String dataId); + default String getString(String dataId, String defaultValue) { + return getString(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } - /** - * Gets duration. - * - * @param dataId the data id - * @return the duration - */ - Duration getDuration(String dataId); + default String getString(String dataId) { + return getString(dataId, null, DEFAULT_CONFIG_TIMEOUT); + } - /** - * Gets duration. - * - * @param dataId the data id - * @param defaultValue the default value - * @return the duration - */ - Duration getDuration(String dataId, Duration defaultValue); /** - * Gets duration. + * Gets short config. * * @param dataId the data id * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the duration + * @return the short config */ - Duration getDuration(String dataId, Duration defaultValue, long timeoutMills); + default short getShort(String dataId, short defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, Short.class); + } + + default short getShort(String dataId, short defaultValue) { + return getShort(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } + + default short getShort(String dataId) { + Short config = getConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT, Short.class); + return config == null ? DEFAULT_SHORT : config; + } + /** - * Gets boolean. + * Gets int config. * * @param dataId the data id * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the boolean + * @return the int config */ - boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills); + default int getInt(String dataId, int defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, Integer.class); + } - /** - * Gets boolean. - * - * @param dataId the data id - * @param defaultValue the default value - * @return the boolean - */ - boolean getBoolean(String dataId, boolean defaultValue); + default int getInt(String dataId, int defaultValue) { + return getInt(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } + + default int getInt(String dataId) { + Integer config = getConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT, Integer.class); + return config == null ? DEFAULT_INT : config; + } - /** - * Gets boolean. - * - * @param dataId the data id - * @return the boolean - */ - boolean getBoolean(String dataId); /** - * Gets config. + * Gets long config. * * @param dataId the data id * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the config + * @return the long config */ - String getConfig(String dataId, String defaultValue, long timeoutMills); + default long getLong(String dataId, long defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, Long.class); + } - /** - * Gets config. - * - * @param dataId the data id - * @param defaultValue the default value - * @return the config - */ - String getConfig(String dataId, String defaultValue); + default long getLong(String dataId, long defaultValue) { + return getLong(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } - /** - * Gets config. - * - * @param dataId the data id - * @param timeoutMills the timeout mills - * @return the config - */ - String getConfig(String dataId, long timeoutMills); + default long getLong(String dataId) { + Long config = getConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT, Long.class); + return config == null ? DEFAULT_LONG : config; + } - /** - * Gets config. - * - * @param dataId the data id - * @return the config - */ - String getConfig(String dataId); /** - * Put config boolean. + * Gets duration config. * * @param dataId the data id - * @param content the content + * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the boolean + * @return the duration config */ - boolean putConfig(String dataId, String content, long timeoutMills); + default Duration getDuration(String dataId, Duration defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, Duration.class); + } + + default Duration getDuration(String dataId, Duration defaultValue) { + return getDuration(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } + + default Duration getDuration(String dataId) { + return getDuration(dataId, DEFAULT_DURATION, DEFAULT_CONFIG_TIMEOUT); + } + /** - * Get latest config. + * Gets boolean config. * * @param dataId the data id * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the Latest config + * @return the boolean config */ - String getLatestConfig(String dataId, String defaultValue, long timeoutMills); + default boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills) { + return getConfig(dataId, defaultValue, timeoutMills, Boolean.class); + } - /** - * Put config boolean. - * - * @param dataId the data id - * @param content the content - * @return the boolean - */ - boolean putConfig(String dataId, String content); + default boolean getBoolean(String dataId, boolean defaultValue) { + return getBoolean(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT); + } - /** - * Put config if absent boolean. - * - * @param dataId the data id - * @param content the content - * @param timeoutMills the timeout mills - * @return the boolean - */ - boolean putConfigIfAbsent(String dataId, String content, long timeoutMills); + default boolean getBoolean(String dataId) { + Boolean config = getConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT, Boolean.class); + return config == null ? DEFAULT_BOOLEAN : config; + } - /** - * Put config if absent boolean. - * - * @param dataId the data id - * @param content the content - * @return the boolean - */ - boolean putConfigIfAbsent(String dataId, String content); /** - * Remove config boolean. + * Gets list config. * * @param dataId the data id + * @param defaultValue the default value * @param timeoutMills the timeout mills - * @return the boolean + * @return the duration config */ - boolean removeConfig(String dataId, long timeoutMills); + default List getList(String dataId, List defaultValue, long timeoutMills, Class dataType) { + List configList = getConfig(dataId, defaultValue, timeoutMills, List.class); - /** - * Remove config boolean. - * - * @param dataId the data id - * @return the boolean - */ - boolean removeConfig(String dataId); + List resultList = new ArrayList<>(); - /** - * Add config listener. - * - * @param dataId the data id - * @param listener the listener - */ - void addConfigListener(String dataId, ConfigurationChangeListener listener); + if (configList != null) { + for (Object config : configList) { + // add the converted value + resultList.add(ConvertUtils.convert(config, dataType)); + } + } - /** - * Remove config listener. - * - * @param dataId the data id - * @param listener the listener - */ - void removeConfigListener(String dataId, ConfigurationChangeListener listener); + return resultList; + } - /** - * Gets config listeners. - * - * @param dataId the data id - * @return the config listeners - */ - Set getConfigListeners(String dataId); + default List getList(String dataId, List defaultValue, Class dataType) { + return getList(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT, dataType); + } - /** - * Gets config from sys pro. - * - * @param dataId the data id - * @return the config from sys pro - */ - default String getConfigFromSys(String dataId) { - if (StringUtils.isBlank(dataId)) { - return null; - } - String content = ENV_MAP.get(dataId); - if (null != content) { - return content; - } - String envDataId = dataId.toUpperCase().replace(".", "_"); - content = ENV_MAP.get(envDataId); - if (null != content) { - return content; - } - return System.getProperty(dataId); + default List getList(String dataId, Class dataType) { + return getList(dataId, null, DEFAULT_CONFIG_TIMEOUT, dataType); + } + + default List getList(String dataId, List defaultValue, long timeoutMills) { + return getList(dataId, defaultValue, timeoutMills, String.class); + } + + default List getList(String dataId, List defaultValue) { + return getList(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT, String.class); + } + + default List getList(String dataId) { + return getList(dataId, null, DEFAULT_CONFIG_TIMEOUT, String.class); } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationProvider.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationBuilder.java similarity index 77% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigurationProvider.java rename to config/seata-config-core/src/main/java/io/seata/config/ConfigurationBuilder.java index c868323e404..63aaea631c1 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationProvider.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationBuilder.java @@ -16,13 +16,17 @@ package io.seata.config; /** - * the interface configuration provider - * @author xingfudeshi@gmail.com + * The interface configuration builder + * + * @author wang.liang */ -public interface ConfigurationProvider { +public interface ConfigurationBuilder { + /** - * provide a AbstractConfiguration implementation instance + * build a Configuration implementation instance + * * @return Configuration */ - Configuration provide(); + Configuration build(); + } diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java deleted file mode 100644 index e837ce78fae..00000000000 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationCache.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.DurationUtil; -import io.seata.common.util.StringUtils; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.implementation.InvocationHandlerAdapter; -import net.bytebuddy.matcher.ElementMatchers; - -/** - * @author funkye - */ -public class ConfigurationCache implements ConfigurationChangeListener { - - private static final String METHOD_PREFIX = "get"; - - private static final String METHOD_LATEST_CONFIG = METHOD_PREFIX + "LatestConfig"; - - private static final Map CONFIG_CACHE = new ConcurrentHashMap<>(); - - private Map> configListenersMap = new HashMap<>(); - - public static void addConfigListener(String dataId, ConfigurationChangeListener... listeners) { - if (StringUtils.isBlank(dataId)) { - return; - } - synchronized (ConfigurationCache.class) { - HashSet listenerHashSet = - getInstance().configListenersMap.computeIfAbsent(dataId, key -> new HashSet<>()); - if (!listenerHashSet.contains(getInstance())) { - ConfigurationFactory.getInstance().addConfigListener(dataId, getInstance()); - listenerHashSet.add(getInstance()); - } - if (null != listeners && listeners.length > 0) { - for (ConfigurationChangeListener listener : listeners) { - if (!listenerHashSet.contains(listener)) { - listenerHashSet.add(listener); - ConfigurationFactory.getInstance().addConfigListener(dataId, listener); - } - } - } - } - } - - public static void removeConfigListener(String dataId, ConfigurationChangeListener... listeners) { - if (StringUtils.isBlank(dataId)) { - return; - } - synchronized (ConfigurationCache.class) { - final HashSet listenerSet = getInstance().configListenersMap.get(dataId); - if (CollectionUtils.isNotEmpty(listenerSet)) { - for (ConfigurationChangeListener listener : listeners) { - if (listenerSet.remove(listener)) { - ConfigurationFactory.getInstance().removeConfigListener(dataId, listener); - } - } - } - } - } - - public static ConfigurationCache getInstance() { - return ConfigurationCacheInstance.INSTANCE; - } - - @Override - public void onChangeEvent(ConfigurationChangeEvent event) { - ObjectWrapper oldWrapper = CONFIG_CACHE.get(event.getDataId()); - // The wrapper.data only exists in the cache when it is not null. - if (StringUtils.isNotBlank(event.getNewValue())) { - if (oldWrapper == null) { - CONFIG_CACHE.put(event.getDataId(), new ObjectWrapper(event.getNewValue(), null)); - } else { - Object newValue = new ObjectWrapper(event.getNewValue(), null).convertData(oldWrapper.getType()); - if (!Objects.equals(oldWrapper.getData(), newValue)) { - CONFIG_CACHE.put(event.getDataId(), new ObjectWrapper(newValue, oldWrapper.getType(),oldWrapper.getLastDefaultValue())); - } - } - } else { - CONFIG_CACHE.remove(event.getDataId()); - } - } - - public Configuration proxy(Configuration originalConfiguration) throws Exception { - return new ByteBuddy().subclass(Configuration.class).method(ElementMatchers.any()) - .intercept(InvocationHandlerAdapter.of((proxy, method, args) -> { - String methodName = method.getName(); - if (methodName.startsWith(METHOD_PREFIX) && !methodName.equalsIgnoreCase(METHOD_LATEST_CONFIG)) { - String rawDataId = (String)args[0]; - ObjectWrapper wrapper = CONFIG_CACHE.get(rawDataId); - ObjectWrapper.ConfigType type = - ObjectWrapper.getTypeByName(methodName.substring(METHOD_PREFIX.length())); - Object defaultValue = null; - if (args.length > 1 - && method.getParameterTypes()[1].getSimpleName().equalsIgnoreCase(type.name())) { - defaultValue = args[1]; - } - if (null == wrapper - || (null != defaultValue && !Objects.equals(defaultValue, wrapper.lastDefaultValue))) { - Object result = method.invoke(originalConfiguration, args); - // The wrapper.data only exists in the cache when it is not null. - if (result != null) { - wrapper = new ObjectWrapper(result, type, defaultValue); - CONFIG_CACHE.put(rawDataId, wrapper); - } - } - return wrapper == null ? null : wrapper.convertData(type); - } - return method.invoke(originalConfiguration, args); - })).make().load(originalConfiguration.getClass().getClassLoader()).getLoaded().getDeclaredConstructor() - .newInstance(); - } - - private static class ConfigurationCacheInstance { - private static final ConfigurationCache INSTANCE = new ConfigurationCache(); - } - - public static void clear() { - CONFIG_CACHE.clear(); - } - - private static class ObjectWrapper { - private final Object data; - private final ConfigType type; - private final Object lastDefaultValue; - - ObjectWrapper(Object data, ConfigType type) { - this(data, type, null); - } - - ObjectWrapper(Object data, ConfigType type, Object lastDefaultValue) { - this.data = data; - this.type = type; - this.lastDefaultValue = lastDefaultValue; - } - - public Object getData() { - return data; - } - - public ConfigType getType() { - return type; - } - - public Object getLastDefaultValue() { - return lastDefaultValue; - } - - public Object convertData(ConfigType aType) { - if (data != null && Objects.equals(type, aType)) { - return data; - } - if (data != null) { - if (ConfigType.INT.equals(aType)) { - return Integer.parseInt(data.toString()); - } else if (ConfigType.BOOLEAN.equals(aType)) { - return Boolean.parseBoolean(data.toString()); - } else if (ConfigType.DURATION.equals(aType)) { - return DurationUtil.parse(data.toString()); - } else if (ConfigType.LONG.equals(aType)) { - return Long.parseLong(data.toString()); - } else if (ConfigType.SHORT.equals(aType)) { - return Short.parseShort(data.toString()); - } - return String.valueOf(data); - } - return null; - } - - public static boolean supportType(String type) { - return getTypeByName(type) != null; - } - - public static ConfigType getTypeByName(String postfix) { - return ConfigType.fromCode(postfix); - } - - /** - * Config Cache Operation type - */ - enum ConfigType { - - /** - * getInt - */ - INT("Int"), - - /** - * getBoolean - */ - BOOLEAN("Boolean"), - - /** - * getDuration - */ - DURATION("Duration"), - - /** - * getLong - */ - LONG("Long"), - - /** - * getShort - */ - SHORT("Short"), - - /** - * getConfig - */ - STRING("Config"); - - private static final Map CODE_TO_VALUE = new HashMap<>(); - - static { - for (ConfigType configType : ConfigType.values()) { - CODE_TO_VALUE.put(configType.code.toUpperCase(), configType); - } - } - - private String code; - - ConfigType(String code) { - this.code = code; - } - - public String getCode() { - return code; - } - - public static ConfigType fromCode(String code) { - ConfigType configType = CODE_TO_VALUE.get(code.toUpperCase()); - return configType == null ? ConfigType.STRING : configType; - } - - public static ConfigType fromName(String name) { - return ConfigType.valueOf(name); - } - } - } -} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java index 38edf0c7ec4..c174f6e7755 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigurationFactory.java @@ -15,12 +15,15 @@ */ package io.seata.config; -import java.util.Objects; +import java.util.Set; import io.seata.common.exception.NotSupportYetException; +import io.seata.common.executor.Cacheable; +import io.seata.common.executor.Cleanable; +import io.seata.common.executor.Initialize; import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.EnhancedServiceNotFoundException; -import io.seata.common.util.StringUtils; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,67 +32,26 @@ * * @author slievrly * @author Geng Zhang + * @author wang.liang */ public final class ConfigurationFactory { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationFactory.class); - private static final String REGISTRY_CONF_DEFAULT = "registry"; - private static final String ENV_SYSTEM_KEY = "SEATA_ENV"; - public static final String ENV_PROPERTY_KEY = "seataEnv"; - private static final String SYSTEM_PROPERTY_SEATA_CONFIG_NAME = "seata.config.name"; - - private static final String ENV_SEATA_CONFIG_NAME = "SEATA_CONFIG_NAME"; - - public static Configuration CURRENT_FILE_INSTANCE; - - static { - load(); - } - - private static void load() { - String seataConfigName = System.getProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME); - if (seataConfigName == null) { - seataConfigName = System.getenv(ENV_SEATA_CONFIG_NAME); - } - if (seataConfigName == null) { - seataConfigName = REGISTRY_CONF_DEFAULT; - } - String envValue = System.getProperty(ENV_PROPERTY_KEY); - if (envValue == null) { - envValue = System.getenv(ENV_SYSTEM_KEY); - } - Configuration configuration = (envValue == null) ? new FileConfiguration(seataConfigName, - false) : new FileConfiguration(seataConfigName + "-" + envValue, false); - Configuration extConfiguration = null; - try { - extConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("load Configuration from :{}", extConfiguration == null ? - configuration.getClass().getSimpleName() : "Spring Configuration"); - } - } catch (EnhancedServiceNotFoundException e) { - if (LOGGER.isDebugEnabled()) { - LOGGER.warn("failed to load extConfiguration: {}", e.getMessage(), e); - } - } catch (Exception e) { - LOGGER.error("failed to load extConfiguration: {}", e.getMessage(), e); - } - CURRENT_FILE_INSTANCE = extConfiguration == null ? configuration : extConfiguration; - } - - private static final String NAME_KEY = "name"; - private static final String FILE_TYPE = "file"; + //region Configuration private static volatile Configuration instance = null; + private static volatile boolean instanceInitializing = false; + /** * Gets instance. * * @return the instance */ public static Configuration getInstance() { + // Build configuration. if (instance == null) { synchronized (Configuration.class) { if (instance == null) { @@ -97,63 +59,143 @@ public static Configuration getInstance() { } } } + + // Init configuration. + initConfiguration(); + return instance; } private static Configuration buildConfiguration() { - String configTypeName = CURRENT_FILE_INSTANCE.getConfig( - ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR - + ConfigurationKeys.FILE_ROOT_TYPE); - LOGGER.info("use configuration center type: {}", configTypeName); - if (StringUtils.isBlank(configTypeName)) { - throw new NotSupportYetException("config type can not be null"); + ConfigurationBuilder configurationBuilder = EnhancedServiceLoader.load(ConfigurationBuilder.class); + return configurationBuilder.build(); + } + + private static void initConfiguration() { + if (!(instance instanceof Initialize)) { + // not an Initialize. + return; } - ConfigType configType = ConfigType.getType(configTypeName); - - Configuration extConfiguration = null; - Configuration configuration; - if (ConfigType.File == configType) { - String pathDataId = String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, - ConfigurationKeys.FILE_ROOT_CONFIG, FILE_TYPE, NAME_KEY); - String name = CURRENT_FILE_INSTANCE.getConfig(pathDataId); - configuration = new FileConfiguration(name); - try { - extConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); - if (LOGGER.isInfoEnabled()) { - LOGGER.info("load Configuration from :{}", extConfiguration == null ? - configuration.getClass().getSimpleName() : "Spring Configuration"); - } - } catch (EnhancedServiceNotFoundException ignore) { - } catch (Exception e) { - LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e); - } - } else { - configuration = EnhancedServiceLoader - .load(ConfigurationProvider.class, Objects.requireNonNull(configType).name()).provide(); + Initialize initialize = (Initialize)instance; + if (initialize.isInitialized()) { + // instance is initialized. + return; } - try { - Configuration configurationCache; - if (null != extConfiguration) { - configurationCache = ConfigurationCache.getInstance().proxy(extConfiguration); - } else { - configurationCache = ConfigurationCache.getInstance().proxy(configuration); - } - if (null != configurationCache) { - extConfiguration = configurationCache; + + if (!instanceInitializing) { + synchronized (Configuration.class) { + if (!instanceInitializing && !initialize.isInitialized()) { + instanceInitializing = true; + initialize.init(); + instanceInitializing = false; + } } - } catch (EnhancedServiceNotFoundException ignore) { + } else if (!initialize.isInitialized()) { + LOGGER.warn("Current configuration '{}' has not been fully initialized. Some config source may not be available.", + instance.getName()); + } + } - } catch (Exception e) { - LOGGER.error("failed to load configurationCacheProvider:{}", e.getMessage(), e); + public static void clean() { + if (instance instanceof Cleanable) { + ((Cleanable)instance).clean(); } - return null == extConfiguration ? configuration : extConfiguration; } - protected static void reload() { - ConfigurationCache.clear(); - load(); + public static void removeCache(String dataId) { + if (instance instanceof Cacheable) { + ((Cacheable)instance).removeCache(dataId); + } + } + + public static void cleanCaches() { + if (instance instanceof Cacheable) { + ((Cacheable)instance).cleanCaches(); + } + } + + /** + * Reload the instance. + */ + static void reload() { + clean(); instance = null; getInstance(); } + + //endregion + + + //region UpdatableConfiguration + + public static UpdatableConfiguration getUpdatableConfiguration() { + Configuration instance = getInstance(); + if (instance instanceof UpdatableConfiguration) { + return (UpdatableConfiguration)instance; + } else { + throw new NotSupportYetException("Current configuration is not a " + UpdatableConfiguration.class.getSimpleName() + "."); + } + } + + + // putConfig + public static boolean putConfig(String dataId, String content, long timeoutMills) { + return getUpdatableConfiguration().putConfig(dataId, content, timeoutMills); + } + + public static boolean putConfig(String dataId, String content) { + return getUpdatableConfiguration().putConfig(dataId, content); + } + + // putConfigIfAbsent + public static boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { + return getUpdatableConfiguration().putConfigIfAbsent(dataId, content, timeoutMills); + } + + public static boolean putConfigIfAbsent(String dataId, String content) { + return getUpdatableConfiguration().putConfigIfAbsent(dataId, content); + } + + // removeConfig + public static boolean removeConfig(String dataId, long timeoutMills) { + return getUpdatableConfiguration().removeConfig(dataId, timeoutMills); + } + + public static boolean removeConfig(String dataId) { + return getUpdatableConfiguration().removeConfig(dataId); + } + + //endregion + + + //region ConfigurationChangeListenerManager + + public static ConfigurationChangeListenerManager getConfigChangeListenerManager() { + Configuration instance = getInstance(); + if (instance instanceof ConfigurationChangeListenerManager) { + return (ConfigurationChangeListenerManager)instance; + } else { + throw new NotSupportYetException("Current configuration is not a " + ConfigurationChangeListenerManager.class.getSimpleName() + "."); + } + } + + + public static void addConfigListener(String dataId, ConfigurationChangeListener listener) { + getConfigChangeListenerManager().addConfigListener(dataId, listener); + } + + public static void removeConfigListener(String dataId, ConfigurationChangeListener listener) { + getConfigChangeListenerManager().removeConfigListener(dataId, listener); + } + + public static Set getListenedConfigDataIds() { + return getConfigChangeListenerManager().getListenedConfigDataIds(); + } + + public static Set getConfigListeners(String dataId) { + return getConfigChangeListenerManager().getConfigListeners(dataId); + } + + //endregion } diff --git a/config/seata-config-core/src/main/java/io/seata/config/SeataConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/SeataConfiguration.java new file mode 100644 index 00000000000..e5047bfd25c --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/SeataConfiguration.java @@ -0,0 +1,293 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import io.seata.common.exception.NotSupportYetException; +import io.seata.common.util.StringUtils; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; +import io.seata.config.source.ConfigSource; +import io.seata.config.source.UpdatableConfigSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The type Seata configuration. + * + * @author wang.liang + */ +public class SeataConfiguration extends CacheableConfiguration + implements ConfigurationChangeListener, ConfigurationChangeListenerManager + , UpdatableConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(SeataConfiguration.class); + + private static final String NAME_PREFIX = "seata:"; + + + /** + * The config change listener map. + */ + protected final Map> listenersMap = new ConcurrentHashMap<>(); + + + //region # Constructor + + public SeataConfiguration(String name, ConcurrentMap configCache) { + super(NAME_PREFIX + name, configCache); + } + + public SeataConfiguration(String name) { + super(NAME_PREFIX + name); + } + + //endregion # Constructor + + + //region # Override CacheableConfiguration + + @Override + protected void onCacheChanged(ConfigCacheChangeEvent event) { + super.onCacheChanged(event); + + String oldCacheValue = event.getOldCache() != null ? event.getOldCache().getStringValue() : null; + + ConfigurationChangeEvent configChangeEvent = new ConfigurationChangeEvent(event.getDataId(), event.getNamespace(), + oldCacheValue, event.getNewCache().getStringValue(), event.getType(), event.getNewCache().getSource()); + + this.doConfigListenersChangeEvent(configChangeEvent); + } + + //endregion # Override CacheableConfiguration + + + //region # Override UpdatableConfiguration + + @Override + public boolean putConfig(String dataId, String content, long timeoutMills) { + if (mainSource instanceof UpdatableConfigSource) { + return ((UpdatableConfigSource) mainSource).putConfig(dataId, content, timeoutMills); + } else { + throw new NotSupportYetException("Configuration '" + this.getClass().getSimpleName() + "(" + this.getName() + ")' " + + "not support putConfig"); + } + } + + @Override + public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { + if (mainSource instanceof UpdatableConfigSource) { + return ((UpdatableConfigSource) mainSource).putConfigIfAbsent(dataId, content, timeoutMills); + } else { + throw new NotSupportYetException("Configuration '" + this.getClass().getSimpleName() + "(" + this.getName() + ")' " + + "not support atomic operation putConfigIfAbsent"); + } + } + + @Override + public boolean removeConfig(String dataId, long timeoutMills) { + if (mainSource instanceof UpdatableConfigSource) { + return ((UpdatableConfigSource) mainSource).removeConfig(dataId, timeoutMills); + } else { + throw new NotSupportYetException("Configuration '" + this.getClass().getSimpleName() + "(" + this.getName() + ")' " + + "not support removeConfig"); + } + } + + //endregion # Override UpdatableConfiguration + + + //region # Override ConfigurationChangeListenerManager + + //region ## add config listener + + @Override + public void addConfigListener(String dataId, ConfigurationChangeListener listener) { + if (StringUtils.isBlank(dataId) || listener == null) { + return; + } + + LOGGER.info("Add config listener: dataId = '{}', listener = '{}'.", dataId, listener); + + listenersMap.computeIfAbsent(dataId, key -> ConcurrentHashMap.newKeySet()) + .add(listener); + + // add self (self is a ConfigurationChangeListener) to sources + this.addSelfConfigListenerToSources(dataId); + } + + protected void addSelfConfigListenerToSource(String dataId, ConfigSource source) { + if (source instanceof ConfigurationChangeListenerManager) { + ConfigurationChangeListenerManager manager = (ConfigurationChangeListenerManager) source; + manager.addConfigListener(dataId, this); + LOGGER.info("Add config listener to source: dataId = '{}', source = '{}'.", dataId, source.getName()); + } + } + + protected void addSelfConfigListenerToSources(String dataId) { + this.getSources().forEach(s -> this.addSelfConfigListenerToSource(dataId, s)); + } + + protected void addSelfConfigListenersToSource(ConfigSource source) { + this.listenersMap.keySet().forEach(dataId -> { + this.addSelfConfigListenerToSource(dataId, source); + }); + } + + //endregion ## add config listener + + + //region ## remove config listener + + @Override + public void removeConfigListener(String dataId, ConfigurationChangeListener listener) { + LOGGER.info("Remove config listener: dataId = '{}', listener = '{}'.", dataId, listener); + + Set listeners = this.listenersMap.get(dataId); + if (listeners != null) { + listeners.remove(listener); + if (listeners.isEmpty()) { + this.removeSelfConfigListenerFromSources(dataId); + this.listenersMap.remove(dataId); + } + } + } + + protected void removeSelfConfigListenerFromSources(String dataId) { + this.getSources().forEach(source -> { + if (source instanceof ConfigurationChangeListenerManager) { + ((ConfigurationChangeListenerManager) source).removeConfigListener(dataId, this); + LOGGER.info("Remove config listener from source: dataId = '{}', source = '{}'.", dataId, source.getName()); + } + }); + } + + protected void removeSelfConfigListenerFromSources() { + this.listenersMap.keySet().forEach(this::removeSelfConfigListenerFromSources); + } + + //endregion ## remove config listener + + + @Override + public Set getListenedConfigDataIds() { + return this.listenersMap.keySet(); + } + + @Override + public Set getConfigListeners(String dataId) { + return this.listenersMap.get(dataId); + } + + + private void cleanListeners() { + // First, remove self (self is a ConfigurationChangeListener) from sources. + this.removeSelfConfigListenerFromSources(); + + // Clear the listener map. + this.listenersMap.clear(); + } + + + //region ## Override ConfigurationChangeListener + + /** + * This method will be called by the {@link ConfigSource}. + * + * @see this#addSelfConfigListenerToSource(String dataId, ConfigSource source) + */ + @Override + public synchronized void onChangeEvent(ConfigurationChangeEvent event) { + String dataId = event.getDataId(); + + // Get config cache + ConfigCache oldCache = this.getCache(dataId); + if (oldCache != null) { + String cacheValue = oldCache.getStringValue(); + + // Compare the order + if (oldCache.getSource().getOrder() > event.getChangeEventSource().getOrder()) { + LOGGER.info("Ignore current change. Although the config '{}' has changed (from '{}' to '{}') by source '{}'," + + " but the order of the changeSource is lower than the cache source '{}'. (Cache time '{}')", + dataId, event.getOldValue(), event.getNewValue(), event.getChangeEventSourceTypeName(), + oldCache.getSourceName(), oldCache.getTimeStr()); + return; + } + + // Compare the value + if (Objects.equals(cacheValue, event.getNewValue())) { + LOGGER.info("Ignore current change. Although the config '{}' has changed (from '{}' to '{}') by source '{}'," + + " but the new value is equals to the cache value '{}' from source '{}'. (Cache time '{}')", + dataId, event.getOldValue(), event.getNewValue(), event.getChangeEventSourceTypeName(), + cacheValue, oldCache.getSourceName(), oldCache.getTimeStr()); + return; + } + + this.changeCache(oldCache, event.getChangeEventSource(), event.getNewValue(), event.getChangeType(), event.getNamespace()); + } else { + // Do nothing: There is no cache, which means that the config of the dataId has not been obtained anywhere. + } + } + + private synchronized void doConfigListenersChangeEvent(ConfigurationChangeEvent event) { + LOGGER.info("The config '{}' has changed by event: {}", event.getDataId(), event); + + Set configListeners = getConfigListeners(event.getDataId()); + if (configListeners != null) { + configListeners.forEach(listener -> listener.onChangeEvent(event)); + } + } + + //endregion ## Override ConfigurationChangeListener + + + //region ## Override ConfigSourceManager + + /** + * Override: Add the config listener to the new source. + * + * @param newSource the new source + */ + @Override + public void onAddedSource(ConfigSource newSource, List higherSources, List lowerSources) { + super.onAddedSource(newSource, higherSources, lowerSources); + + // add self (self is a ConfigurationChangeListener) to source + this.addSelfConfigListenersToSource(newSource); + } + + //endregion ## Override ConfigSourceManager + + + //region ## Override Cleanable + + @Override + public void clean() { + super.clean(); + this.cleanListeners(); + } + + //endregion ## Override Cleanable + + //endregion # Override ConfigurationChangeListenerManager +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/SeataConfigurationBuilder.java b/config/seata-config-core/src/main/java/io/seata/config/SeataConfigurationBuilder.java new file mode 100644 index 00000000000..6f8d1cf4246 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/SeataConfigurationBuilder.java @@ -0,0 +1,29 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +/** + * the type Default configuration builder. + * + * @author wang.liang + */ +public class SeataConfigurationBuilder implements ConfigurationBuilder { + + @Override + public Configuration build() { + return new SeataConfiguration("default-configuration"); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/SimpleConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/SimpleConfiguration.java new file mode 100644 index 00000000000..e37764c3f67 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/SimpleConfiguration.java @@ -0,0 +1,120 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.annotation.Nonnull; + +import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.source.ConfigSource; + +/** + * The type Simple configuration + * + * @author wang.liang + */ +public class SimpleConfiguration extends AbstractConfiguration { + + public static final String DEFAULT_NAME = "simple-configuration"; + + + /** + * The main source. + */ + protected volatile ConfigSource mainSource; + + /** + * All the sources, contains the main source. + */ + private final List sources = new CopyOnWriteArrayList<>(); + + /** + * The source map, contains the main source. + */ + private final Map sourceMap = new ConcurrentHashMap<>(8); + + + public SimpleConfiguration() { + this(DEFAULT_NAME); + } + + public SimpleConfiguration(String name) { + super(name); + } + + + //region # Override Initialize + + @Override + public void init() { + this.loadSources(); + this.initSources(); + super.setInitialized(true); + } + + /** + * Load the processors and process current configuration. + */ + protected void loadSources() { + List processors = EnhancedServiceLoader.loadAll(ConfigurationProcessor.class); + for (ConfigurationProcessor processor : processors) { + processor.process(this); + } + } + + private void initSources() { + sources.forEach(source -> { + // If not initialized, do init the sources. + if (source instanceof Initialize && !((Initialize)source).isInitialized()) { + ((Initialize)source).init(); + } + }); + } + + //endregion + + + //region # Override ConfigSourceManager + + @Override + public ConfigSource getMainSource() { + return this.mainSource; + } + + @Override + public void setMainSource(ConfigSource mainSource) { + this.mainSource = mainSource; + } + + @Nonnull + @Override + public List getSources() { + return this.sources; + } + + @Nonnull + @Override + public Map getSourceMap() { + return this.sourceMap; + } + + //endregion +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/UpdatableConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/UpdatableConfiguration.java new file mode 100644 index 00000000000..4301d444f76 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/UpdatableConfiguration.java @@ -0,0 +1,71 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import static io.seata.config.Configuration.DEFAULT_CONFIG_TIMEOUT; + +/** + * The interface UpdatableConfiguration. + * + * @author slievrly + * @author wang.liang + */ +public interface UpdatableConfiguration { + + /** + * Put config. + * + * @param dataId the data id + * @param content the content + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean putConfig(String dataId, String content, long timeoutMills); + + default boolean putConfig(String dataId, String content) { + return putConfig(dataId, content, DEFAULT_CONFIG_TIMEOUT); + } + + + /** + * Put config if absent. + * + * @param dataId the data id + * @param content the content + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean putConfigIfAbsent(String dataId, String content, long timeoutMills); + + default boolean putConfigIfAbsent(String dataId, String content) { + return putConfigIfAbsent(dataId, content, DEFAULT_CONFIG_TIMEOUT); + } + + + /** + * Remove config. + * + * @param dataId the data id + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean removeConfig(String dataId, long timeoutMills); + + default boolean removeConfig(String dataId) { + return removeConfig(dataId, DEFAULT_CONFIG_TIMEOUT); + } + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/changelistener/AbstractConfigurationChangeListenerManager.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/AbstractConfigurationChangeListenerManager.java new file mode 100644 index 00000000000..2b3cc6c3a09 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/AbstractConfigurationChangeListenerManager.java @@ -0,0 +1,71 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.changelistener; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringUtils; + +/** + * The type AbstractConfigurationChangeListenerManager. + * + * @author wang.liang + */ +public class AbstractConfigurationChangeListenerManager implements ConfigurationChangeListenerManager { + + private final Map> listenersMap = new ConcurrentHashMap<>(8); + + + @Override + public void addConfigListener(String dataId, ConfigurationChangeListener listener) { + if (StringUtils.isBlank(dataId) || listener == null) { + return; + } + + CollectionUtils.computeIfAbsent(this.listenersMap, dataId, key -> ConcurrentHashMap.newKeySet()) + .add(listener); + } + + @Override + public void removeConfigListener(String dataId, ConfigurationChangeListener listener) { + if (StringUtils.isBlank(dataId) || listener == null) { + return; + } + + if (this.listenersMap.containsKey(dataId)) { + Set listeners = this.listenersMap.get(dataId); + if (listeners != null) { + listeners.remove(listener); + if (listeners.isEmpty()) { + this.listenersMap.remove(dataId); + } + } + } + } + + @Override + public Set getListenedConfigDataIds() { + return listenersMap.keySet(); + } + + @Override + public Set getConfigListeners(String dataId) { + return listenersMap.get(dataId); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigChangeListener.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListener.java similarity index 96% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigChangeListener.java rename to config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListener.java index d67f2e4b8f1..de52d80cb78 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigChangeListener.java +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListener.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.changelistener; import java.util.concurrent.ExecutorService; diff --git a/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListenerUtils.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListenerUtils.java new file mode 100644 index 00000000000..987101a39e1 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigChangeListenerUtils.java @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.changelistener; + +/** + * The type Config change listener utils. + * + * @author wang.liang + */ +public class ConfigChangeListenerUtils { + + /** + * Get change type. + * + * @param oldValue the old value + * @param newValue the new value + * @return the change type + */ + public static ConfigurationChangeType getChangeType(String oldValue, String newValue) { + if (oldValue == null) { + return ConfigurationChangeType.ADD; + } else if (newValue == null) { + return ConfigurationChangeType.DELETE; + } else { + return ConfigurationChangeType.MODIFY; + } + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeEvent.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeEvent.java similarity index 66% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeEvent.java rename to config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeEvent.java index 45bc2e4ec09..9a7badddd6a 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeEvent.java +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeEvent.java @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.changelistener; + +import java.util.Objects; +import javax.annotation.Nonnull; + +import io.seata.config.source.ConfigSource; /** * The type Configuration change event. @@ -27,26 +32,29 @@ public class ConfigurationChangeEvent { private String newValue; private String namespace; private ConfigurationChangeType changeType; - private static final String DEFAULT_NAMESPACE = "DEFAULT"; + @Nonnull + private final ConfigSource changeEventSource; - public ConfigurationChangeEvent(){ - } - - public ConfigurationChangeEvent(String dataId, String newValue) { - this(dataId, DEFAULT_NAMESPACE, null, newValue, ConfigurationChangeType.MODIFY); + public ConfigurationChangeEvent(@Nonnull ConfigSource changeEventSource) { + Objects.requireNonNull(changeEventSource, "The 'changeEventSource' must not be null."); + this.changeEventSource = changeEventSource; } public ConfigurationChangeEvent(String dataId, String namespace, String oldValue, String newValue, - ConfigurationChangeType type) { + ConfigurationChangeType type, @Nonnull ConfigSource changeEventSource) { + Objects.requireNonNull(changeEventSource, "The 'changeEventSource' must not be null."); + this.dataId = dataId; this.namespace = namespace; this.oldValue = oldValue; this.newValue = newValue; this.changeType = type; + this.changeEventSource = changeEventSource; } + /** * Gets data id. * @@ -141,4 +149,37 @@ public ConfigurationChangeEvent setNamespace(String namespace) { this.namespace = namespace; return this; } + + /** + * Gets change event source + * + * @return the change event source + */ + @Nonnull + public ConfigSource getChangeEventSource() { + return changeEventSource; + } + + /** + * Gets type name of change event source + * + * @return the type name + */ + @Nonnull + public String getChangeEventSourceTypeName() { + return getChangeEventSource().getName(); + } + + + @Override + public String toString() { + return "[" + + "dataId='" + dataId + '\'' + + ", oldValue=" + (oldValue != null ? ('\'' + oldValue + '\'') : null) + + ", newValue=" + (newValue != null ? ('\'' + newValue + '\'') : null) + + ", namespace=" + (namespace != null ? ('\'' + namespace + '\'') : null) + + ", changeType=" + changeType + + ", changeEventSource=" + changeEventSource.getName() + + ']'; + } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeListener.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListener.java similarity index 90% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeListener.java rename to config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListener.java index fd74d45193d..3025c0ce3a5 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeListener.java +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListener.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.changelistener; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; @@ -58,9 +58,9 @@ public interface ConfigurationChangeListener { */ default void onProcessEvent(ConfigurationChangeEvent event) { getExecutorService().submit(() -> { - beforeEvent(); + beforeEvent(event); onChangeEvent(event); - afterEvent(); + afterEvent(event); }); } @@ -83,14 +83,12 @@ default ExecutorService getExecutorService() { /** * Before event. */ - default void beforeEvent() { - + default void beforeEvent(ConfigurationChangeEvent event) { } /** * After event. */ - default void afterEvent() { - + default void afterEvent(ConfigurationChangeEvent event) { } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListenerManager.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListenerManager.java new file mode 100644 index 00000000000..0327086bafb --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeListenerManager.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.changelistener; + +import java.util.Set; + +/** + * The interface ConfigurationChangeListenerManager. + * + * @author slievrly + * @author wang.liang + */ +public interface ConfigurationChangeListenerManager { + + /** + * Add config listener. + * + * @param dataId the data id + * @param listener the listener + */ + void addConfigListener(String dataId, ConfigurationChangeListener listener); + + /** + * Remove config listener. + * + * @param dataId the data id + * @param listener the listener + */ + void removeConfigListener(String dataId, ConfigurationChangeListener listener); + + /** + * Gets set of listened config dataId + * + * @return the set listened config dataId + */ + Set getListenedConfigDataIds(); + + /** + * Gets config listeners. + * + * @param dataId the data id + * @return the config listeners + */ + Set getConfigListeners(String dataId); + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeType.java b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeType.java similarity index 95% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeType.java rename to config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeType.java index d0ca07f508d..35d132591bc 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigurationChangeType.java +++ b/config/seata-config-core/src/main/java/io/seata/config/changelistener/ConfigurationChangeType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.changelistener; /** * The enum Configuration change type. diff --git a/config/seata-config-core/src/main/java/io/seata/config/FileConfigFactory.java b/config/seata-config-core/src/main/java/io/seata/config/file/FileConfigFactory.java similarity index 92% rename from config/seata-config-core/src/main/java/io/seata/config/FileConfigFactory.java rename to config/seata-config-core/src/main/java/io/seata/config/file/FileConfigFactory.java index 271dda1e94c..3de09df2805 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/FileConfigFactory.java +++ b/config/seata-config-core/src/main/java/io/seata/config/file/FileConfigFactory.java @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.file; -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.config.file.FileConfig; import java.io.File; import java.util.LinkedHashMap; import java.util.Set; +import javax.annotation.Nonnull; + +import io.seata.common.loader.EnhancedServiceLoader; /** * @author wangwei-ying @@ -38,11 +39,12 @@ public class FileConfigFactory { } }; - + @Nonnull public static FileConfig load() { return loadService(DEFAULT_TYPE, null, null); } + @Nonnull public static FileConfig load(File targetFile, String name) { String fileName = targetFile.getName(); String configType = getConfigType(fileName); @@ -59,7 +61,8 @@ private static String getConfigType(String fileName) { return configType; } - private static FileConfig loadService(String name, Class[] argsType, Object[] args) { + @Nonnull + private static FileConfig loadService(String name, Class[] argsType, Object[] args) { FileConfig fileConfig = EnhancedServiceLoader.load(FileConfig.class, name, argsType, args); return fileConfig; } diff --git a/config/seata-config-core/src/main/java/io/seata/config/file/SimpleFileConfig.java b/config/seata-config-core/src/main/java/io/seata/config/file/SimpleFileConfig.java index 5a642ebe3df..e2a68e7fe79 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/file/SimpleFileConfig.java +++ b/config/seata-config-core/src/main/java/io/seata/config/file/SimpleFileConfig.java @@ -15,15 +15,13 @@ */ package io.seata.config.file; +import java.io.File; + import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; - import io.seata.common.loader.LoadLevel; import io.seata.common.loader.Scope; -import io.seata.config.FileConfigFactory; -import io.seata.config.FileConfiguration; - -import java.io.File; +import io.seata.config.source.impl.FileConfigSource; /** * @author wangwei-ying @@ -38,7 +36,7 @@ public SimpleFileConfig() { } public SimpleFileConfig(File file, String name) { - if (name.startsWith(FileConfiguration.SYS_FILE_RESOURCE_PREFIX)) { + if (name.startsWith(FileConfigSource.SYS_FILE_RESOURCE_PREFIX)) { Config appConfig = ConfigFactory.parseFileAnySyntax(file); fileConfig = ConfigFactory.load(appConfig); } else { diff --git a/config/seata-config-core/src/main/java/io/seata/config/file/YamlFileConfig.java b/config/seata-config-core/src/main/java/io/seata/config/file/YamlFileConfig.java index 03b48d3f9e3..5b67dd843a1 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/file/YamlFileConfig.java +++ b/config/seata-config-core/src/main/java/io/seata/config/file/YamlFileConfig.java @@ -15,13 +15,6 @@ */ package io.seata.config.file; -import io.seata.common.loader.LoadLevel; -import io.seata.common.loader.Scope; -import io.seata.config.FileConfigFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.Yaml; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -29,6 +22,12 @@ import java.io.InputStream; import java.util.Map; +import io.seata.common.loader.LoadLevel; +import io.seata.common.loader.Scope; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + /** * @author wangwei-ying */ diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessor.java index 2ae8c328d75..638b48123e4 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessor.java +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessor.java @@ -15,14 +15,13 @@ */ package io.seata.config.processor; +import java.io.IOException; +import java.util.Properties; + +import io.seata.common.ConfigurationKeys; import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationKeys; - -import java.io.IOException; -import java.util.Properties; /** * The Config Processor. @@ -31,7 +30,6 @@ */ public class ConfigProcessor { private static final String SEPARATOR = "."; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; private static final String DEFAULT_DATA_TYPE = "properties"; /** * processing configuration @@ -52,7 +50,7 @@ public static Properties processConfig(String config, String dataType) throws IO * @return data type */ public static String resolverConfigDataType(String dataId) { - return resolverConfigDataType(FILE_CONFIG.getConfig(getDataTypeKey()),dataId,DEFAULT_DATA_TYPE); + return resolverConfigDataType(ConfigurationFactory.getInstance().getString(getDataTypeKey()),dataId,DEFAULT_DATA_TYPE); } /** diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessorOrdered.java b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessorOrdered.java new file mode 100644 index 00000000000..857e48c48a1 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigProcessorOrdered.java @@ -0,0 +1,99 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor; + +import io.seata.config.processor.impl.ConfigFilesConfigurationProcessor; + +/** + * The interface ConfigProcessorOrdered. + *

+ * Process sequence: systems > defaults > others. + * + * @author wang.liang + */ +public interface ConfigProcessorOrdered { + + //region 1. System property and env configuration processors. Start processing first. + + /** + * 1.1. System property processor, the {@link ConfigurationProcessor} with the highest priority. + * + * @see io.seata.config.processor.impl.SystemPropertyConfigurationProcessor + */ + int SYSTEM_PROPERTY_PROCESSOR_ORDER = Integer.MIN_VALUE + 100; + + /** + * 1.2. System env processor. + * + * @see io.seata.config.processor.impl.SystemEnvConfigurationProcessor + */ + int SYSTEM_ENV_PROCESSOR_ORDER = Integer.MIN_VALUE + 200; + + //endregion + + + //------------------------------------------------------------------------- + + + //region 2. Default value configuration processors. Priority process than the following. + + /** + * 2.1. Default value from property object processor. + *

+ * See the processor in the module 'seata-spring-autoconfigure-core'. + */ + int PROPERTY_OBJECT_DEFAULT_VALUE_PROCESSOR_ORDER = -200; + + /** + * 2.2. Default value from files processor. + * + * @see io.seata.config.processor.impl.FilesDefaultValueConfigurationProcessor + */ + int FILES_DEFAULT_VALUE_PROCESSOR_ORDER = -100; + + //endregion + + + //------------------------------------------------------------------------- + + + //region 3. Other configuration processors. Priority lower than above. + + /** + * 3.1. Spring environment processor. + */ + int SPRING_ENVIRONMENT_PROCESSOR_ORDER = 100; + + /** + * 3.2. Config file processor. + * + * @see ConfigFilesConfigurationProcessor + */ + int CONFIG_FILES_PROCESSOR_ORDER = 200; + + /** + * 3.3. Config center processor. + *

+ * It will be processed finally, because it needs other config sources to provide config related to the config-center.
+ * For example: the address of the config-center + * + * @see io.seata.config.processor.impl.ConfigCenterConfigurationProcessor + */ + int CONFIG_CENTER_PROCESSOR_ORDER = 300; + + //endregion + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigurationProcessor.java new file mode 100644 index 00000000000..37d1beefc1a --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/ConfigurationProcessor.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor; + +import io.seata.config.Configuration; + +/** + * The interface ConfigurationProcessor + * + * @author wang.liang + */ +public interface ConfigurationProcessor { + + /** + * process configuration + */ + void process(Configuration configuration); + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigCenterConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigCenterConfigurationProcessor.java new file mode 100644 index 00000000000..5707e77a29e --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigCenterConfigurationProcessor.java @@ -0,0 +1,64 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor.impl; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.EnhancedServiceNotFoundException; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.source.ConfigSourceProvider; +import io.seata.config.util.ConfigurationUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.seata.config.processor.ConfigProcessorOrdered.CONFIG_CENTER_PROCESSOR_ORDER; + +/** + * The type ConfigCenterConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "config-center-processor", order = CONFIG_CENTER_PROCESSOR_ORDER) +public class ConfigCenterConfigurationProcessor implements ConfigurationProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationProcessor.class); + + + @Override + public void process(Configuration configuration) { + // get config type name + String configTypeName = ConfigurationUtils.getConfigTypeName(configuration); + if (StringUtils.isBlank(configTypeName)) { + LOGGER.warn("Config type name is null or blank: {}, do not load the config center.", configTypeName); + return; + } + + // load Config source provider by configTypeName + ConfigSourceProvider sourceProvider; + try { + sourceProvider = EnhancedServiceLoader.load(ConfigSourceProvider.class, configTypeName); + } catch (EnhancedServiceNotFoundException e) { + LOGGER.error("The config source provider for config center '{}' is not found, do not load the config center.", + configTypeName, e); + return; + } + + // provide one or more config source + sourceProvider.provide(configuration); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigFilesConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigFilesConfigurationProcessor.java new file mode 100644 index 00000000000..eac5915e67d --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/ConfigFilesConfigurationProcessor.java @@ -0,0 +1,45 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor.impl; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.util.ConfigurationUtils; + +import static io.seata.config.processor.ConfigProcessorOrdered.CONFIG_FILES_PROCESSOR_ORDER; +import static io.seata.config.source.ConfigSourceOrdered.COMMON_CONFIG_FILES_SOURCE_ORDER; +import static io.seata.config.source.ConfigSourceOrdered.ENV_CONFIG_FILES_SOURCE_ORDER; + +/** + * The type ConfigFilesConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "config-files-processor", order = CONFIG_FILES_PROCESSOR_ORDER) +public class ConfigFilesConfigurationProcessor implements ConfigurationProcessor { + + @Override + public void process(Configuration configuration) { + // get registry configFileName from configuration + String configFileName = ConfigurationUtils.getConfigFileName(configuration); + + // load file sources by configFileName + ConfigurationUtils.loadFileSources(configuration, configFileName, + COMMON_CONFIG_FILES_SOURCE_ORDER, ENV_CONFIG_FILES_SOURCE_ORDER, + true, false); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/impl/FilesDefaultValueConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/FilesDefaultValueConfigurationProcessor.java new file mode 100644 index 00000000000..566203b9828 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/FilesDefaultValueConfigurationProcessor.java @@ -0,0 +1,45 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor.impl; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.source.impl.FileConfigSource; + +import static io.seata.config.processor.ConfigProcessorOrdered.FILES_DEFAULT_VALUE_PROCESSOR_ORDER; +import static io.seata.config.source.ConfigSourceOrdered.FILES_DEFAULT_VALUE_CONFIG_SOURCE_ORDER; + +/** + * The type Files default value ConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "files-default-value-processor", order = FILES_DEFAULT_VALUE_PROCESSOR_ORDER) +public class FilesDefaultValueConfigurationProcessor implements ConfigurationProcessor { + + private static final String DEFAULT_CONFIG_COMMON_FILE_NAME = "seata-default-config-common.conf"; + private static final String DEFAULT_CONFIG_CLIENT_FILE_NAME = "seata-default-config-client.conf"; + + + @Override + public void process(Configuration configuration) { + // common + configuration.addSource(new FileConfigSource(DEFAULT_CONFIG_COMMON_FILE_NAME, FILES_DEFAULT_VALUE_CONFIG_SOURCE_ORDER)); + // client + configuration.addSource(new FileConfigSource(DEFAULT_CONFIG_CLIENT_FILE_NAME, FILES_DEFAULT_VALUE_CONFIG_SOURCE_ORDER)); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemEnvConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemEnvConfigurationProcessor.java new file mode 100644 index 00000000000..ce11e5e9cf9 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemEnvConfigurationProcessor.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor.impl; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.source.impl.SystemEnvConfigSource; + +import static io.seata.config.processor.ConfigProcessorOrdered.SYSTEM_ENV_PROCESSOR_ORDER; + +/** + * The type SystemEnvConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "system-env-processor", order = SYSTEM_ENV_PROCESSOR_ORDER) +public class SystemEnvConfigurationProcessor implements ConfigurationProcessor { + + @Override + public void process(Configuration configuration) { + configuration.addSource(new SystemEnvConfigSource()); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemPropertyConfigurationProcessor.java b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemPropertyConfigurationProcessor.java new file mode 100644 index 00000000000..ad39cc92ee1 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/processor/impl/SystemPropertyConfigurationProcessor.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.processor.impl; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.config.source.impl.SystemPropertyConfigSource; + +import static io.seata.config.processor.ConfigProcessorOrdered.SYSTEM_PROPERTY_PROCESSOR_ORDER; + +/** + * The type SystemPropertyConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "system-property-processor", order = SYSTEM_PROPERTY_PROCESSOR_ORDER) +public class SystemPropertyConfigurationProcessor implements ConfigurationProcessor { + + @Override + public void process(Configuration configuration) { + SystemPropertyConfigSource source = new SystemPropertyConfigSource(true); + + // This source can be initialized first. + source.init(); + + // Add this source to the first location, because it has the highest priority + configuration.addSource(source); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/AbstractScheduledUpdateConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/AbstractScheduledUpdateConfigSource.java new file mode 100644 index 00000000000..8eaa5fb67b7 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/AbstractScheduledUpdateConfigSource.java @@ -0,0 +1,202 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; + +import io.seata.common.executor.Initialize; +import io.seata.common.thread.NamedThreadFactory; +import io.seata.config.changelistener.AbstractConfigurationChangeListenerManager; +import io.seata.config.changelistener.ConfigChangeListenerUtils; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeType; + +/** + * The type AbstractScheduledUpdateConfigSource. + * + * @author wang.liang + */ +public abstract class AbstractScheduledUpdateConfigSource extends AbstractConfigurationChangeListenerManager + implements ScheduledUpdateConfigSource, Initialize { + + private static final String EXECUTOR_SERVICE_PREFIX = "scheduledUpdateSource"; + private static final long DEFAULT_EXECUTOR_SERVICE_PERIOD = 1000L; + + /** + * The name + */ + @Nonnull + private final String name; + + private final ScheduledThreadPoolExecutor executorService; + private final long executorServicePeriod; + + private final Map latestConfigCacheMap = new ConcurrentHashMap<>(); + + + protected AbstractScheduledUpdateConfigSource(@Nonnull String name, boolean allowAutoUpdate, long executorServicePeriod) { + Objects.requireNonNull(name, "The 'name' must not be null."); + this.name = name; + + if (allowAutoUpdate) { + this.executorService = this.buildExecutorService(name); + } else { + this.executorService = null; + } + + this.executorServicePeriod = executorServicePeriod; + } + + protected AbstractScheduledUpdateConfigSource(@Nonnull String name, boolean allowAutoUpdate) { + this(name, allowAutoUpdate, DEFAULT_EXECUTOR_SERVICE_PERIOD); + } + + protected AbstractScheduledUpdateConfigSource(@Nonnull String name, long executorServicePeriod) { + this(name, executorServicePeriod > 0, executorServicePeriod); + } + + protected AbstractScheduledUpdateConfigSource(@Nonnull String name, ScheduledThreadPoolExecutor executorService, long executorServicePeriod) { + Objects.requireNonNull(name, "The 'name' must not be null."); + this.name = name; + this.executorService = executorService; + this.executorServicePeriod = executorServicePeriod; + } + + protected AbstractScheduledUpdateConfigSource(@Nonnull String name, ScheduledThreadPoolExecutor executorService) { + this(name, executorService, DEFAULT_EXECUTOR_SERVICE_PERIOD); + } + + + protected void initLatestConfigCacheMap(Map latestConfigCacheMap) { + // default: do nothing + } + + + /** + * Check whether the configuration is changed. + */ + private void checkWhetherConfigChanged() { + // First, reload config source. + if (this.reloadConfigSource()) { + // Then, do check whether config changed. + getListenedConfigDataIds().forEach(this::doCheckWhetherConfigChanged); + } + } + + /** + * Reload the config from the source. + *

+ * Can be overridden in subclasses. + */ + protected boolean reloadConfigSource() { + // default: do nothing + return true; + } + + protected void doCheckWhetherConfigChanged(String dataId) { + String oldValue = this.latestConfigCacheMap.get(dataId); + String currentValue = this.getLatestConfig(dataId); + if (!Objects.equals(currentValue, oldValue)) { + @SuppressWarnings("all") + String newValue = currentValue; + + // Get change type by oldValue and newValue. + ConfigurationChangeType type = ConfigChangeListenerUtils.getChangeType(oldValue, newValue); + // Build change event. + ConfigurationChangeEvent event = this.buildChangeEvent(dataId, oldValue, newValue, type); + // Trigger the listener's onChangeEvent. + getConfigListeners(dataId).forEach(listener -> listener.onChangeEvent(event)); + // Update the latest config cache. + this.latestConfigCacheMap.put(dataId, newValue); + } + } + + protected ConfigurationChangeEvent buildChangeEvent(String dataId, String oldValue, String newValue, ConfigurationChangeType type) { + return new ConfigurationChangeEvent(dataId, null, oldValue, newValue, type, this); + } + + + //region # Override ScheduledThreadPoolExecutor + + private ScheduledThreadPoolExecutor buildExecutorService(String name) { + return new ScheduledThreadPoolExecutor(1, new NamedThreadFactory(EXECUTOR_SERVICE_PREFIX + "_" + name, 1)); + } + + private void initExecutorService() { + if (this.executorService != null) { + this.executorService.scheduleAtFixedRate(this::checkWhetherConfigChanged, 0, executorServicePeriod, TimeUnit.MILLISECONDS); + } + } + + //endregion # Override ScheduledThreadPoolExecutor + + + //region # Override ScheduledUpdateConfigSource + + @Override + public void start() { + if (this.executorService != null) { + this.initExecutorService(); + } + } + + @Override + public void shutdown() { + if (this.executorService != null) { + this.executorService.shutdown(); + } + } + + @Nonnull + @Override + public String getName() { + return name; + } + + //endregion # Override ScheduledUpdateConfigSource + + + //region # Override Initialize + + /** + * Whether initialized + */ + private volatile boolean initialized = false; + + @Override + public void init() { + this.initLatestConfigCacheMap(this.latestConfigCacheMap); + this.start(); + this.setInitialized(true); + } + + @Override + public boolean isInitialized() { + return initialized; + } + + @SuppressWarnings("all") + protected void setInitialized(boolean initialized) { + this.initialized = initialized; + } + + //endregion # Override Initialize +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSource.java new file mode 100644 index 00000000000..e98629e4d74 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSource.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +import javax.annotation.Nonnull; + +import static io.seata.config.Configuration.DEFAULT_CONFIG_TIMEOUT; + +/** + * The interface ConfigSource. + * + * @author wang.liang + * @author slievrly + */ +public interface ConfigSource { + + /** + * Get latest config. + * + * @param dataId the data id + * @param timeoutMills the timeout mills + * @return the Latest config + */ + String getLatestConfig(String dataId, long timeoutMills); + + default String getLatestConfig(String dataId) { + return getLatestConfig(dataId, DEFAULT_CONFIG_TIMEOUT); + } + + + /** + * Get the name + * + * @return the name + */ + @Nonnull + String getName(); + + /** + * Get the order. + *

+ * The lower order, the higher priority. + * + * @return the order + */ + int getOrder(); +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceManager.java b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceManager.java new file mode 100644 index 00000000000..3314b77f242 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceManager.java @@ -0,0 +1,128 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * The interface ConfigSourceManager. + * + * @author wang.liang + */ +public interface ConfigSourceManager { + + //region main source + + /** + * Get main source + * + * @return the main source + */ + ConfigSource getMainSource(); + + /** + * Sets main source. + * + * @param mainSource the main source + */ + void setMainSource(ConfigSource mainSource); + + //endregion + + + /** + * Get all the sources, contains the main source. + * + * @return the sources + */ + @Nonnull + List getSources(); + + /** + * Get source map. + * + * @return The source map + */ + @Nonnull + Map getSourceMap(); + + /** + * Get source by name. + * + * @param sourceName the source name + * @return the source + */ + @Nullable + default ConfigSource getSource(String sourceName) { + return getSourceMap().get(sourceName); + } + + /** + * add source + * + * @param newSource the new source + */ + default void addSource(@Nonnull ConfigSource newSource) { + Objects.requireNonNull(newSource, "The 'newSource' must not be null."); + + + // add before the target source, if exist + List sources = this.getSources(); + int newSourceIndex = -1; + + ConfigSource current; + for (int i = 0; i < sources.size(); i++) { + current = sources.get(i); + + if (newSource.getOrder() < current.getOrder()) { + sources.add(i, newSource); + newSourceIndex = i; + break; + } + } + + List higherSources; + List lowerSources; + if (newSourceIndex >= 0) { + higherSources = sources.subList(0, newSourceIndex); + lowerSources = sources.subList(newSourceIndex + 1, sources.size() - 1); + } else { + higherSources = new ArrayList<>(sources); + lowerSources = Collections.emptyList(); + sources.add(newSource); + } + + + this.onAddedSource(newSource, higherSources, lowerSources); + } + + /** + * After adding a new source, trigger this method. + * + * @param newSource the new source + * @param higherSources the sources with higher priority than newSource + * @param lowerSources the sources with lower priority than newSource + */ + default void onAddedSource(ConfigSource newSource, List higherSources, List lowerSources) { + + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceOrdered.java b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceOrdered.java new file mode 100644 index 00000000000..4921d0198a2 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceOrdered.java @@ -0,0 +1,106 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +import io.seata.config.processor.impl.ConfigFilesConfigurationProcessor; + +/** + * The interface ConfigSourceOrdered. + *

+ * Priority: systems > others > defaults. + * + * @author wang.liang + * @see ConfigSource + */ +public interface ConfigSourceOrdered { + + //region 1. System property and env sources. Priority higher than the following. + + /** + * 1.1. System property, the {@link ConfigSource} with the highest priority. + * + * @see io.seata.config.source.impl.SystemPropertyConfigSource + * @see io.seata.config.processor.impl.SystemPropertyConfigurationProcessor + */ + int SYSTEM_PROPERTY_SOURCE_ORDER = Integer.MIN_VALUE + 100; + + /** + * 1.2. System env + * + * @see io.seata.config.source.impl.SystemEnvConfigSource + * @see io.seata.config.processor.impl.SystemEnvConfigurationProcessor + */ + int SYSTEM_ENV_SOURCE_ORDER = Integer.MIN_VALUE + 200; + + //endregion + + + //------------------------------------------------------------------------- + + + //region 2. Others. Priority higher than the following. + + /** + * 2.1. Config center, examples: nacos, apollo, consul, etcd3, spring-cloud, zookeeper... + * + * @see io.seata.config.processor.impl.ConfigCenterConfigurationProcessor + */ + int CONFIG_CENTER_SOURCE_ORDER = 100; + + /** + * 2.2. Spring environment + */ + int SPRING_ENVIRONMENT_SOURCE_ORDER = 200; + + /** + * 2.3. Env config files, examples: registry-dev.conf, file-dev.conf + * + * @see io.seata.config.source.impl.FileConfigSource + * @see ConfigFilesConfigurationProcessor + */ + int ENV_CONFIG_FILES_SOURCE_ORDER = 300; + + /** + * 2.4. Common config files, examples: registry.conf, file.conf + * + * @see io.seata.config.source.impl.FileConfigSource + * @see ConfigFilesConfigurationProcessor + */ + int COMMON_CONFIG_FILES_SOURCE_ORDER = 400; + + //endregion + + + //------------------------------------------------------------------------- + + + //region 3. Default value sources. Priority lower than above. + + /** + * 3.1. Default value from property object. + */ + int PROPERTY_OBJECT_DEFAULT_VALUE_CONFIG_SOURCE_ORDER = Integer.MAX_VALUE - 200; + + /** + * 3.2. Default value from default-config-files, examples: seata-default-config-common.conf, seata-default-config-client.conf + * + * @see io.seata.config.source.impl.FileConfigSource + * @see io.seata.config.processor.impl.FilesDefaultValueConfigurationProcessor + */ + int FILES_DEFAULT_VALUE_CONFIG_SOURCE_ORDER = Integer.MAX_VALUE - 100; + + //endregion +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/ExtConfigurationProvider.java b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceProvider.java similarity index 68% rename from config/seata-config-core/src/main/java/io/seata/config/ExtConfigurationProvider.java rename to config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceProvider.java index cc94b67c5a5..5d04ec9b556 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ExtConfigurationProvider.java +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceProvider.java @@ -13,17 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.source; + +import io.seata.config.Configuration; /** - * the interface ext configuration provider + * The interface ConfigSourceProvider + * * @author xingfudeshi@gmail.com + * @author wang.liang */ -public interface ExtConfigurationProvider { +public interface ConfigSourceProvider { + /** - * provide a AbstractConfiguration implementation instance - * @param originalConfiguration - * @return configuration + * provide one or more ConfigSource implementation instance */ - Configuration provide(Configuration originalConfiguration); + void provide(Configuration configuration); } diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceType.java similarity index 80% rename from config/seata-config-core/src/main/java/io/seata/config/ConfigType.java rename to config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceType.java index 326a1d47fca..84d15410d47 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ConfigSourceType.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.source; /** - * The enum Config type. + * The enum Config source type. * * @author slievrly */ -public enum ConfigType { +public enum ConfigSourceType { /** * File config type. */ @@ -60,10 +60,10 @@ public enum ConfigType { * @param name the name * @return the type */ - public static ConfigType getType(String name) { - for (ConfigType configType : values()) { - if (configType.name().equalsIgnoreCase(name)) { - return configType; + public static ConfigSourceType getType(String name) { + for (ConfigSourceType configSourceType : values()) { + if (configSourceType.name().equalsIgnoreCase(name)) { + return configSourceType; } } throw new IllegalArgumentException("not support config type: " + name); diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/LocalConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/LocalConfigSource.java new file mode 100644 index 00000000000..2337bd45ad0 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/LocalConfigSource.java @@ -0,0 +1,24 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +/** + * The interface LocalConfigSource. + * + * @author wang.liang + */ +public interface LocalConfigSource extends ConfigSource { +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/RemoteConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/RemoteConfigSource.java new file mode 100644 index 00000000000..3297000eb9d --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/RemoteConfigSource.java @@ -0,0 +1,24 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +/** + * The interface RemoteConfigSource. + * + * @author wang.liang + */ +public interface RemoteConfigSource extends ConfigSource { +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/ScheduledUpdateConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/ScheduledUpdateConfigSource.java new file mode 100644 index 00000000000..651a67dc736 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/ScheduledUpdateConfigSource.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +/** + * The interface ScheduledUpdateConfigSource. + * + * @author wang.liang + */ +public interface ScheduledUpdateConfigSource extends ConfigSource { + + /** + * Start. + */ + void start(); + + /** + * Shutdown. + */ + void shutdown(); + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/UpdatableConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/UpdatableConfigSource.java new file mode 100644 index 00000000000..8eb42a0751b --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/UpdatableConfigSource.java @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source; + +import static io.seata.config.Configuration.DEFAULT_CONFIG_TIMEOUT; + +/** + * The interface UpdatableConfigSource. + * + * @author wang.liang + */ +public interface UpdatableConfigSource { + + /** + * Put config. + * + * @param dataId the data id + * @param content the content + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean putConfig(String dataId, String content, long timeoutMills); + + default boolean putConfig(String dataId, String content) { + return putConfig(dataId, content, DEFAULT_CONFIG_TIMEOUT); + } + + + /** + * Put config if absent. + * + * @param dataId the data id + * @param content the content + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean putConfigIfAbsent(String dataId, String content, long timeoutMills); + + default boolean putConfigIfAbsent(String dataId, String content) { + return putConfigIfAbsent(dataId, content, DEFAULT_CONFIG_TIMEOUT); + } + + + /** + * Remove config. + * + * @param dataId the data id + * @param timeoutMills the timeout mills + * @return the boolean + */ + boolean removeConfig(String dataId, long timeoutMills); + + default boolean removeConfig(String dataId) { + return removeConfig(dataId, DEFAULT_CONFIG_TIMEOUT); + } + +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSource.java similarity index 82% rename from config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java rename to config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSource.java index 08f633406c8..42eef7b317e 100644 --- a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java +++ b/config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSource.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.seata.config; +package io.seata.config.source.impl; import java.io.File; import java.io.UnsupportedEncodingException; @@ -25,29 +25,41 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import io.seata.common.ConfigurationKeys; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; +import io.seata.config.ConfigFuture; import io.seata.config.ConfigFuture.ConfigOperation; +import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigChangeListenerUtils; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; import io.seata.config.file.FileConfig; +import io.seata.config.file.FileConfigFactory; +import io.seata.config.source.ConfigSource; +import io.seata.config.source.LocalConfigSource; +import io.seata.config.source.UpdatableConfigSource; import org.apache.commons.lang.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The type FileConfiguration. + * The type File config source. * * @author slievrly */ -public class FileConfiguration extends AbstractConfiguration { +public class FileConfigSource implements LocalConfigSource + , UpdatableConfigSource, ConfigurationChangeListenerManager { - private static final Logger LOGGER = LoggerFactory.getLogger(FileConfiguration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FileConfigSource.class); private FileConfig fileConfig; @@ -59,12 +71,11 @@ public class FileConfiguration extends AbstractConfiguration { private static final long LISTENER_CONFIG_INTERVAL = 1 * 1000; - private static final String REGISTRY_TYPE = "file"; + private static final String CONFIG_TYPE = "file"; public static final String SYS_FILE_RESOURCE_PREFIX = "file:"; - private final ConcurrentMap> configListenersMap = new ConcurrentHashMap<>( - 8); + private final Map> configListenersMap = new ConcurrentHashMap<>(8); private final Map listenedConfigMap = new HashMap<>(8); @@ -74,7 +85,9 @@ public class FileConfiguration extends AbstractConfiguration { private final String name; - private final FileListener fileListener = new FileListener(); + private final int order; + + private final FileListener fileListener = new FileListener(this); private final boolean allowDynamicRefresh; @@ -82,8 +95,9 @@ public class FileConfiguration extends AbstractConfiguration { * Note that:this constructor is only used to create proxy with CGLIB * see io.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider#provide */ - public FileConfiguration() { + public FileConfigSource() { this.name = null; + this.order = Integer.MAX_VALUE; this.targetFilePath = null; this.allowDynamicRefresh = false; } @@ -91,20 +105,23 @@ public FileConfiguration() { /** * Instantiates a new File configuration. * - * @param name the name + * @param name the name + * @param order the order */ - public FileConfiguration(String name) { - this(name, true); + public FileConfigSource(String name, int order) { + this(name, order, true); } /** * Instantiates a new File configuration. * For seata-server side the conf file should always exists. * For application(or client) side,conf file may not exists when using seata-spring-boot-starter + * * @param name the name + * @param order the order * @param allowDynamicRefresh the allow dynamic refresh */ - public FileConfiguration(String name, boolean allowDynamicRefresh) { + public FileConfigSource(String name, int order, boolean allowDynamicRefresh) { File file = getConfigFile(name); if (file == null) { targetFilePath = null; @@ -120,6 +137,7 @@ public FileConfiguration(String name, boolean allowDynamicRefresh) { } } this.name = name; + this.order = order; configOperateExecutor = new ThreadPoolExecutor(CORE_CONFIG_OPERATE_THREAD, MAX_CONFIG_OPERATE_THREAD, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("configOperate", MAX_CONFIG_OPERATE_THREAD)); @@ -154,10 +172,9 @@ private File getConfigFile(String name) { } private File getFileFromFileSystem(String decodedPath) { - // run with jar file and not package third lib into jar file, this.getClass().getClassLoader() will be null URL resourceUrl = this.getClass().getClassLoader().getResource(""); - String[] tryPaths = null; + String[] tryPaths; if (resourceUrl != null) { tryPaths = new String[]{ // first: project dir @@ -211,12 +228,8 @@ private File getFileFromClasspath(String name) throws UnsupportedEncodingExcepti } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { - String value = getConfigFromSys(dataId); - if (value != null) { - return value; - } - ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigOperation.GET, timeoutMills); + public String getLatestConfig(String dataId, long timeoutMills) { + ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigOperation.GET, timeoutMills); configOperateExecutor.submit(new ConfigOperateRunnable(configFuture)); Object getValue = configFuture.get(); return getValue == null ? null : String.valueOf(getValue); @@ -250,7 +263,7 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene } configListenersMap.computeIfAbsent(dataId, key -> ConcurrentHashMap.newKeySet()) .add(listener); - listenedConfigMap.put(dataId, ConfigurationFactory.getInstance().getConfig(dataId)); + listenedConfigMap.put(dataId, ConfigurationFactory.getInstance().getString(dataId)); // Start config change listener for the dataId. fileListener.addListener(dataId, listener); @@ -272,14 +285,25 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list listener.onShutDown(); } + @Override + public Set getListenedConfigDataIds() { + return configListenersMap.keySet(); + } + @Override public Set getConfigListeners(String dataId) { return configListenersMap.get(dataId); } + @Nonnull @Override - public String getTypeName() { - return REGISTRY_TYPE; + public String getName() { + return CONFIG_TYPE + ":" + name; + } + + @Override + public int getOrder() { + return order; } /** @@ -309,11 +333,8 @@ public void run() { if (allowDynamicRefresh) { long tempLastModified = new File(targetFilePath).lastModified(); if (tempLastModified > targetFileLastModified) { - FileConfig tempConfig = FileConfigFactory.load(new File(targetFilePath), name); - if (tempConfig != null) { - fileConfig = tempConfig; - targetFileLastModified = tempLastModified; - } + fileConfig = FileConfigFactory.load(new File(targetFilePath), name); + targetFileLastModified = tempLastModified; } } if (configFuture.getOperation() == ConfigOperation.GET) { @@ -332,7 +353,7 @@ public void run() { } catch (Exception e) { setFailResult(configFuture); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Could not found property {}, try to use default value instead. exception:{}", + LOGGER.debug("Could not found property '{}', try to use default value instead. exception: {}", configFuture.getDataId(), e.getMessage()); } } @@ -350,11 +371,14 @@ private void setFailResult(ConfigFuture configFuture) { } + /** * The type FileListener. */ class FileListener implements ConfigurationChangeListener { + private final ConfigSource source; + private final Map> dataIdMap = new HashMap<>(); private final ExecutorService executor = new ThreadPoolExecutor(CORE_LISTENER_THREAD, MAX_LISTENER_THREAD, 0L, @@ -364,12 +388,14 @@ class FileListener implements ConfigurationChangeListener { /** * Instantiates a new FileListener. */ - FileListener() {} + FileListener(ConfigSource source) { + this.source = source; + } public synchronized void addListener(String dataId, ConfigurationChangeListener listener) { // only the first time add listener will trigger on process event if (dataIdMap.isEmpty()) { - fileListener.onProcessEvent(new ConfigurationChangeEvent()); + fileListener.onProcessEvent(new ConfigurationChangeEvent(source)); } dataIdMap.computeIfAbsent(dataId, value -> new HashSet<>()).add(listener); @@ -377,17 +403,19 @@ public synchronized void addListener(String dataId, ConfigurationChangeListener @Override public void onChangeEvent(ConfigurationChangeEvent event) { - Boolean enabled = Boolean.valueOf(System.getProperty("file.listener.enabled", "true")); + boolean enabled = Boolean.parseBoolean(System.getProperty("file.listener.enabled", "true")); while (enabled) { for (String dataId : dataIdMap.keySet()) { try { - String currentConfig = - ConfigurationFactory.getInstance().getLatestConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT); + String currentConfig = source.getLatestConfig(dataId); if (StringUtils.isNotBlank(currentConfig)) { String oldConfig = listenedConfigMap.get(dataId); if (ObjectUtils.notEqual(currentConfig, oldConfig)) { listenedConfigMap.put(dataId, currentConfig); - event.setDataId(dataId).setNewValue(currentConfig).setOldValue(oldConfig); + event.setDataId(dataId) + .setOldValue(oldConfig) + .setNewValue(currentConfig) + .setChangeType(ConfigChangeListenerUtils.getChangeType(oldConfig, currentConfig)); for (ConfigurationChangeListener listener : dataIdMap.get(dataId)) { listener.onChangeEvent(event); @@ -403,7 +431,7 @@ public void onChangeEvent(ConfigurationChangeEvent event) { } catch (InterruptedException e) { LOGGER.error("fileListener thread sleep error:{}", e.getMessage()); } - enabled = Boolean.valueOf(System.getProperty("file.listener.enabled", "true")); + enabled = Boolean.parseBoolean(System.getProperty("file.listener.enabled", "true")); } } diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSourceProvider.java b/config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSourceProvider.java new file mode 100644 index 00000000000..b11c3e9ffdd --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/impl/FileConfigSourceProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source.impl; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.source.ConfigSourceProvider; +import io.seata.config.util.ConfigurationUtils; + +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_CONFIG; +import static io.seata.config.source.ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + +/** + * @author xingfudeshi@gmail.com + */ +@LoadLevel(name = "File", order = 1) +public class FileConfigSourceProvider implements ConfigSourceProvider { + + private static final String DEFAULT_FILE_NAME = "file.conf"; + + private static final String FILE_TYPE = "file"; + private static final String NAME_KEY = "name"; + + @Override + public void provide(Configuration configuration) { + // the key 'config.file.name' + String fileNameConfigKey = String.join(FILE_CONFIG_SPLIT_CHAR, + FILE_ROOT_CONFIG, FILE_TYPE, NAME_KEY); + + // get configFileName from configuration + String configFileName = configuration.getString(fileNameConfigKey, DEFAULT_FILE_NAME); + + // load file sources by configFileName + ConfigurationUtils.loadFileSources(configuration, configFileName, + CONFIG_CENTER_SOURCE_ORDER, CONFIG_CENTER_SOURCE_ORDER - 100, + true, true); + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemEnvConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemEnvConfigSource.java new file mode 100644 index 00000000000..e747f4f38d5 --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemEnvConfigSource.java @@ -0,0 +1,66 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source.impl; + +import java.util.Map; + +import javax.annotation.Nonnull; + +import io.seata.common.util.StringUtils; +import io.seata.config.source.ConfigSource; + +import static io.seata.config.source.ConfigSourceOrdered.SYSTEM_ENV_SOURCE_ORDER; + +/** + * The type SystemEnvConfigSource. + * + * @author wang.liang + */ +public class SystemEnvConfigSource implements ConfigSource { + + private final Map env = System.getenv(); + + + @Override + public String getLatestConfig(String dataId, long timeoutMills) { + String config1 = env.get(dataId); + if (!StringUtils.isNotBlank(config1)) { + return config1; + } + + if (dataId.contains(".")) { + String envDataId = dataId.toUpperCase().replace(".", "_"); + String config2 = env.get(envDataId); + if (!StringUtils.isNotBlank(config2)) { + return config2; + } + } + + // May be null or blank. + return config1; + } + + @Nonnull + @Override + public String getName() { + return "system-env"; + } + + @Override + public int getOrder() { + return SYSTEM_ENV_SOURCE_ORDER; + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemPropertyConfigSource.java b/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemPropertyConfigSource.java new file mode 100644 index 00000000000..40792a94ede --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/source/impl/SystemPropertyConfigSource.java @@ -0,0 +1,95 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.source.impl; + +import java.util.Map; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +import io.seata.common.util.StringUtils; +import io.seata.config.source.AbstractScheduledUpdateConfigSource; + +import static io.seata.config.source.ConfigSourceOrdered.SYSTEM_PROPERTY_SOURCE_ORDER; + +/** + * The type SystemPropertyConfigSource. + * + * @author wang.liang + */ +public class SystemPropertyConfigSource extends AbstractScheduledUpdateConfigSource { + + public static final String DEFAULT_NAME = "system-property"; + + + public SystemPropertyConfigSource(boolean allowAutoUpdate, long executorServicePeriod) { + super(DEFAULT_NAME, allowAutoUpdate, executorServicePeriod); + } + + public SystemPropertyConfigSource(boolean allowAutoUpdate) { + super(DEFAULT_NAME, allowAutoUpdate); + } + + public SystemPropertyConfigSource(long executorServicePeriod) { + super(DEFAULT_NAME, executorServicePeriod); + } + + public SystemPropertyConfigSource(ScheduledThreadPoolExecutor executorService, long executorServicePeriod) { + super(DEFAULT_NAME, executorService, executorServicePeriod); + } + + public SystemPropertyConfigSource(ScheduledThreadPoolExecutor executorService) { + super(DEFAULT_NAME, executorService); + } + + + /** + * @see super#init() + */ + @Override + protected void initLatestConfigCacheMap(Map latestConfigCacheMap) { + super.initLatestConfigCacheMap(latestConfigCacheMap); + + System.getProperties().stringPropertyNames().forEach(key -> { + latestConfigCacheMap.put(key, System.getProperty(key)); + }); + } + + /** + * @see super#doCheckWhetherConfigChanged(String) + */ + @Override + public String getLatestConfig(String dataId, long timeoutMills) { + String config1 = System.getProperty(dataId); + if (StringUtils.isNotBlank(config1)) { + return config1; + } + + String propertyDataId = StringUtils.hump2Line(dataId); + if (!propertyDataId.equals(dataId)) { + String config2 = System.getProperty(propertyDataId); + if (StringUtils.isNotBlank(config2)) { + return config2; + } + } + + // May be null or blank. + return config1; + } + + @Override + public int getOrder() { + return SYSTEM_PROPERTY_SOURCE_ORDER; + } +} diff --git a/config/seata-config-core/src/main/java/io/seata/config/util/ConfigurationUtils.java b/config/seata-config-core/src/main/java/io/seata/config/util/ConfigurationUtils.java new file mode 100644 index 00000000000..e34e71e2d0b --- /dev/null +++ b/config/seata-config-core/src/main/java/io/seata/config/util/ConfigurationUtils.java @@ -0,0 +1,158 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.util; + +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.source.ConfigSource; +import io.seata.config.source.ConfigSourceType; +import io.seata.config.source.impl.FileConfigSource; + +import static io.seata.common.util.StringFormatUtils.DOT; + +/** + * The type Configuration utils. + * + * @author wang.liang + */ +public final class ConfigurationUtils { + + public static String getConfig(Configuration configuration, String defaultValue, String... keys) { + String config; + for (String key : keys) { + config = configuration.getString(key); + if (StringUtils.isNotBlank(config)) { + return config; + } + } + + return defaultValue; + } + + + //region get configFileName + + public static final String DEFAULT_REGISTRY_CONFIG_FILE_NAME = "registry"; + + public static final String CONFIG_FILE_NAME_SYSTEM_PROPERTY_KEY = "seataConfigName"; + public static final String CONFIG_FILE_NAME_SYSTEM_ENV_KEY = "SEATA_CONFIG_NAME"; + public static final String CONFIG_FILE_NAME_KEY1 = "seata.config.name"; + public static final String CONFIG_FILE_NAME_KEY2 = "config.name"; + + public static String getConfigFileName(Configuration configuration) { + return getConfig(configuration, DEFAULT_REGISTRY_CONFIG_FILE_NAME, + CONFIG_FILE_NAME_SYSTEM_PROPERTY_KEY, CONFIG_FILE_NAME_SYSTEM_ENV_KEY, CONFIG_FILE_NAME_KEY1, CONFIG_FILE_NAME_KEY2); + } + + //endregion + + //region get envName + + public static final String ENV_SYSTEM_PROPERTY_KEY = "seataEnv"; + public static final String ENV_SYSTEM_ENV_KEY = "SEATA_ENV"; + public static final String ENV_KEY1 = "seata.env"; + public static final String ENV_KEY2 = "env"; + + public static String getEnvName(Configuration configuration) { + return getConfig(configuration, null, + ENV_SYSTEM_PROPERTY_KEY, ENV_SYSTEM_ENV_KEY, ENV_KEY1, ENV_KEY2); + } + + //endregion + + + //region get configTypeName and configType + + public static final String DEFAULT_CONFIG_TYPE = "file"; + + public static final String CONFIG_TYPE_SYSTEM_PROPERTY_KEY = "seataConfigType"; + public static final String CONFIG_TYPE_SYSTEM_ENV_KEY = "SEATA_CONFIG_TYPE"; + public static final String CONFIG_TYPE_KEY1 = "seata.config.type"; + public static final String CONFIG_TYPE_KEY2 = "config.type"; + + + private static String getConfigTypeNameInternal(Configuration configuration) { + return getConfig(configuration, DEFAULT_CONFIG_TYPE, + CONFIG_TYPE_SYSTEM_PROPERTY_KEY, CONFIG_TYPE_SYSTEM_ENV_KEY, CONFIG_TYPE_KEY2, CONFIG_TYPE_KEY1); + } + + public static String getConfigTypeName(Configuration configuration) { + String configTypeName = getConfigTypeNameInternal(configuration); + try { + return ConfigSourceType.getType(configTypeName).name(); + } catch (IllegalArgumentException e) { + return configTypeName; + } + } + + public static ConfigSourceType getConfigType(Configuration configuration) { + String configTypeName = getConfigTypeNameInternal(configuration); + return ConfigSourceType.getType(configTypeName); + } + + //endregion + + + /** + * load file sources + * + * @param configuration the configuration + * @param configFileName the configFileName + * @param allowDynamicRefresh the allow dynamic refresh + * @param doSetMainSource if true, do set mainSource + */ + public static void loadFileSources(Configuration configuration, String configFileName, int order, int envSourceOrder, + boolean allowDynamicRefresh, boolean doSetMainSource) { + // load commonSource without env + ConfigSource commonSource = new FileConfigSource(configFileName, order, allowDynamicRefresh); + configuration.addSource(commonSource); + + + // the main file config source + ConfigSource mainSource = commonSource; + + + // get envName from configuration + String envName = getEnvName(configuration); + + // load envSource with env + if (envName != null) { + // create envConfigFileName + String envConfigFileName; + int dotIndex = configFileName.indexOf(DOT); + if (dotIndex > 0) { + envConfigFileName = configFileName.substring(0, dotIndex) + "-" + envName + configFileName.substring(dotIndex); + } else { + envConfigFileName = configFileName + "-" + envName; + } + + // build envSource, and higher than commonSource + ConfigSource envSource = new FileConfigSource(envConfigFileName, envSourceOrder, allowDynamicRefresh); + + // add envSource before commonSource + // The priority of envSource is higher than commonSource + configuration.addSource(envSource); + + mainSource = envSource; + } + + + // Set main source, if doSetMainSource is true, or the original main source is null + if (doSetMainSource || configuration.getMainSource() == null) { + configuration.setMainSource(mainSource); + } + } +} diff --git a/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.ConfigurationBuilder b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.ConfigurationBuilder new file mode 100644 index 00000000000..67b7748e598 --- /dev/null +++ b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.ConfigurationBuilder @@ -0,0 +1 @@ +io.seata.config.SeataConfigurationBuilder \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor new file mode 100644 index 00000000000..1c627f9a146 --- /dev/null +++ b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor @@ -0,0 +1,5 @@ +io.seata.config.processor.impl.SystemPropertyConfigurationProcessor +io.seata.config.processor.impl.SystemEnvConfigurationProcessor +io.seata.config.processor.impl.FilesDefaultValueConfigurationProcessor +io.seata.config.processor.impl.ConfigFilesConfigurationProcessor +io.seata.config.processor.impl.ConfigCenterConfigurationProcessor \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..39f83945ac4 --- /dev/null +++ b/config/seata-config-core/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.source.impl.FileConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-core/src/main/resources/file.conf b/config/seata-config-core/src/main/resources/seata-default-config-client.conf similarity index 100% rename from config/seata-config-core/src/main/resources/file.conf rename to config/seata-config-core/src/main/resources/seata-default-config-client.conf diff --git a/config/seata-config-core/src/main/resources/registry.conf b/config/seata-config-core/src/main/resources/seata-default-config-common.conf similarity index 100% rename from config/seata-config-core/src/main/resources/registry.conf rename to config/seata-config-core/src/main/resources/seata-default-config-common.conf diff --git a/config/seata-config-core/src/test/java/io/seata/config/ConfigurationCacheTests.java b/config/seata-config-core/src/test/java/io/seata/config/ConfigurationCacheTests.java deleted file mode 100644 index 32b97adfa12..00000000000 --- a/config/seata-config-core/src/test/java/io/seata/config/ConfigurationCacheTests.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config; - -import io.seata.common.util.DurationUtil; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.time.Duration; - -/** - * @author jsbxyyx - */ -public class ConfigurationCacheTests { - - @Test - public void testChangeValue() throws Exception { - Configuration configuration = new FileConfiguration("registry"); - configuration = ConfigurationCache.getInstance().proxy(configuration); - configuration.getBoolean("aaa", false); - ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("aaa", "true")); - boolean aaa = configuration.getBoolean("aaa", false); - Assertions.assertTrue(aaa); - - configuration.getShort("bbb", (short) 0); - ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("bbb", "1")); - short bbb = configuration.getShort("bbb", (short) 0); - Assertions.assertEquals((short) 1, bbb); - - configuration.getDuration("ccc", Duration.ZERO); - ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("ccc", "1s")); - Duration ccc = configuration.getDuration("ccc", Duration.ZERO); - Assertions.assertEquals(DurationUtil.parse("1s"), ccc); - - configuration.getInt("ddd", 0); - ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("ddd", "1")); - int ddd = configuration.getInt("ddd", 0); - Assertions.assertEquals(1, ddd); - - configuration.getLong("eee", 0); - ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("eee", "1")); - long eee = configuration.getLong("eee", 0); - Assertions.assertEquals((long) 1, eee); - } - -} diff --git a/config/seata-config-core/src/test/java/io/seata/config/FileConfigurationTest.java b/config/seata-config-core/src/test/java/io/seata/config/FileConfigurationTest.java deleted file mode 100644 index c14de3fcf92..00000000000 --- a/config/seata-config-core/src/test/java/io/seata/config/FileConfigurationTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author slievrly - */ -class FileConfigurationTest { - - - - @BeforeEach - void setUp() { - } - - @AfterEach - void tearDown() { - } - - @Test - void addConfigListener() throws InterruptedException { - Configuration fileConfig = ConfigurationFactory.getInstance(); - CountDownLatch countDownLatch = new CountDownLatch(1); - boolean value = fileConfig.getBoolean("service.disableGlobalTransaction"); - ConfigurationCache.addConfigListener("service.disableGlobalTransaction", (event) -> { - Assertions.assertEquals(Boolean.parseBoolean(event.getNewValue()), !Boolean.parseBoolean(event.getOldValue())); - countDownLatch.countDown(); - }); - System.setProperty("service.disableGlobalTransaction", String.valueOf(!value)); - countDownLatch.await(5, TimeUnit.SECONDS); - System.setProperty("file.listener.enabled", "false"); - System.setProperty("service.disableGlobalTransaction", String.valueOf(value)); - Thread.sleep(2000); - boolean currentValue = fileConfig.getBoolean("service.disableGlobalTransaction"); - Assertions.assertNotEquals(value, currentValue); - System.setProperty("service.disableGlobalTransaction", String.valueOf(!value)); - } - - @Test - void testDiffDefaultValue() { - Configuration fileConfig = ConfigurationFactory.getInstance(); - int intValue1 = fileConfig.getInt("int.not.exist", 100); - int intValue2 = fileConfig.getInt("int.not.exist", 200); - Assertions.assertNotEquals(intValue1, intValue2); - String strValue1 = fileConfig.getConfig("str.not.exist", "en"); - String strValue2 = fileConfig.getConfig("str.not.exist", "us"); - Assertions.assertNotEquals(strValue1, strValue2); - boolean bolValue1 = fileConfig.getBoolean("boolean.not.exist", true); - boolean bolValue2 = fileConfig.getBoolean("boolean.not.exist", false); - Assertions.assertNotEquals(bolValue1, bolValue2); - - String value = "QWERT"; - System.setProperty("mockDataId1", value); - String content1 = fileConfig.getConfig("mockDataId1"); - Assertions.assertEquals(content1, value); - String content2 = fileConfig.getConfig("mockDataId1", "hehe"); - Assertions.assertEquals(content2, value); - - String content3 = fileConfig.getConfig("mockDataId2"); - Assertions.assertNull(content3); - String content4 = fileConfig.getConfig("mockDataId2", value); - Assertions.assertEquals(content4, value); - String content5 = fileConfig.getConfig("mockDataId2"); - Assertions.assertEquals(content5, value); - - } - -} diff --git a/config/seata-config-core/src/test/java/io/seata/config/ProConfigurationFactoryTest.java b/config/seata-config-core/src/test/java/io/seata/config/ProConfigurationFactoryTest.java index ea5607dfc90..e14c123768a 100644 --- a/config/seata-config-core/src/test/java/io/seata/config/ProConfigurationFactoryTest.java +++ b/config/seata-config-core/src/test/java/io/seata/config/ProConfigurationFactoryTest.java @@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test; import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY; -import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT; +import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; /** * @author wangwei-ying @@ -33,14 +33,13 @@ void getInstance() { System.setProperty(ENV_PROPERTY_KEY, "test-pro"); System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME, REGISTRY_CONF_DEFAULT); ConfigurationFactory.reload(); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"), "file-test-pro.conf"); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testBlank"), ""); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testNull"), null); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testExist"), null); Configuration instance = ConfigurationFactory.getInstance(); - Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"), "true"); - Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8092"); - + Assertions.assertEquals("file-test-pro.conf", instance.getString("config.file.name")); + Assertions.assertEquals("", instance.getString("config.file.testBlank")); + Assertions.assertNull(instance.getString("config.file.testNull")); + Assertions.assertNull(instance.getString("config.file.testExist")); + Assertions.assertEquals("true", instance.getString("service.disableGlobalTransaction")); + Assertions.assertEquals("127.0.0.1:8092", instance.getString("service.default.grouplist")); } @AfterAll diff --git a/config/seata-config-core/src/test/java/io/seata/config/RegistryConfigurationFactoryTest.java b/config/seata-config-core/src/test/java/io/seata/config/RegistryConfigurationFactoryTest.java index 4052b545b13..d624e200b06 100644 --- a/config/seata-config-core/src/test/java/io/seata/config/RegistryConfigurationFactoryTest.java +++ b/config/seata-config-core/src/test/java/io/seata/config/RegistryConfigurationFactoryTest.java @@ -20,9 +20,8 @@ import org.junit.jupiter.api.Test; import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY; -import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT; - +import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; /** * @author wangwei-ying @@ -31,17 +30,17 @@ class RegistryConfigurationFactoryTest { @Test void getInstance() { - System.setProperty(ENV_PROPERTY_KEY,"test"); - System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME,REGISTRY_CONF_DEFAULT); + System.setProperty(ENV_PROPERTY_KEY, "test"); + System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME, REGISTRY_CONF_DEFAULT); ConfigurationFactory.reload(); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"),"file-test.conf"); Configuration instance = ConfigurationFactory.getInstance(); - Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"),"true"); - Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8091"); - + Assertions.assertEquals("file-test.conf", instance.getString("config.file.name")); + Assertions.assertEquals("true", instance.getString("service.disableGlobalTransaction")); + Assertions.assertEquals("127.0.0.1:8091", instance.getString("service.default.grouplist")); } + @AfterAll - public static void afterAll(){ + public static void afterAll() { System.clearProperty(ENV_PROPERTY_KEY); System.clearProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME); ConfigurationFactory.reload(); diff --git a/config/seata-config-core/src/test/java/io/seata/config/SystemPropertyConfigSourceTest.java b/config/seata-config-core/src/test/java/io/seata/config/SystemPropertyConfigSourceTest.java new file mode 100644 index 00000000000..d56b71e04e2 --- /dev/null +++ b/config/seata-config-core/src/test/java/io/seata/config/SystemPropertyConfigSourceTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * @author slievrly + * @author wang.liang + */ +class SystemPropertyConfigSourceTest { + + @BeforeEach + void setUp() { + } + + @AfterEach + void tearDown() { + } + + @Test + void testAddConfigListener() throws InterruptedException { + Configuration config = ConfigurationFactory.getInstance(); + + String dataId = "mockDataId"; + + // false + System.setProperty(dataId, "false"); + boolean value = config.getBoolean(dataId); + Assertions.assertFalse(value); + + AtomicInteger changeCount = new AtomicInteger(); + CountDownLatch countDownLatch = new CountDownLatch(1); + CountDownLatch countDownLatch2 = new CountDownLatch(2); + ConfigurationFactory.addConfigListener(dataId, (event) -> { + int count = changeCount.addAndGet(1); + if (count == 1) { + Assertions.assertEquals("false", event.getOldValue()); + Assertions.assertEquals("true", event.getNewValue()); + } else if (count == 2) { + Assertions.assertEquals("true", event.getOldValue()); + Assertions.assertEquals("false", event.getNewValue()); + } else { + throw new RuntimeException("Too many changes for the dataId '" + dataId + "'."); + } + + countDownLatch.countDown(); + countDownLatch2.countDown(); + }); + + // true + System.setProperty(dataId, "true"); + countDownLatch.await(3, TimeUnit.SECONDS); + value = config.getBoolean(dataId); + Assertions.assertTrue(value); + + // false + System.setProperty(dataId, "false"); + countDownLatch2.await(3, TimeUnit.SECONDS); + value = config.getBoolean(dataId); + Assertions.assertFalse(value); + + // clean + System.clearProperty(dataId); + ConfigurationFactory.reload(); + } + + @Test + void testDiffDefaultValue() { + Configuration config = ConfigurationFactory.getInstance(); + ConfigurationFactory.cleanCaches(); + + int intValue1 = config.getInt("int.not.exist", 100); + int intValue2 = config.getInt("int.not.exist", 200); + Assertions.assertNotEquals(intValue1, intValue2); + String strValue1 = config.getString("str.not.exist", "en"); + String strValue2 = config.getString("str.not.exist", "us"); + Assertions.assertNotEquals(strValue1, strValue2); + boolean bolValue1 = config.getBoolean("boolean.not.exist", true); + boolean bolValue2 = config.getBoolean("boolean.not.exist", false); + Assertions.assertNotEquals(bolValue1, bolValue2); + + String value = "QWERT"; + System.setProperty("mockDataId1", value); + String content1 = config.getString("mockDataId1"); + Assertions.assertEquals(content1, value); + String content2 = config.getString("mockDataId1", "hehe"); + Assertions.assertEquals(content2, value); + + String content3 = config.getString("mockDataId2"); + Assertions.assertNull(content3); + String content4 = config.getString("mockDataId2", value); + Assertions.assertEquals(content4, value); + String content5 = config.getString("mockDataId2"); + Assertions.assertNull(content5); + + + // test blank value + value = ""; + System.setProperty("mockDataId3", value); + Assertions.assertEquals(config.getString("mockDataId3"), value); + Assertions.assertNotEquals(config.getString("mockDataId3", "1"), value); + + + System.clearProperty("mockDataId1"); + System.clearProperty("mockDataId3"); + ConfigurationFactory.reload(); + } + +} diff --git a/config/seata-config-core/src/test/java/io/seata/config/YamlConfigurationFactoryTest.java b/config/seata-config-core/src/test/java/io/seata/config/YamlConfigurationFactoryTest.java index d5d4ff26060..1714ee05bc8 100644 --- a/config/seata-config-core/src/test/java/io/seata/config/YamlConfigurationFactoryTest.java +++ b/config/seata-config-core/src/test/java/io/seata/config/YamlConfigurationFactoryTest.java @@ -18,11 +18,10 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY; -import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT; +import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME; /** * @author wangwei-ying @@ -34,13 +33,13 @@ public void getInstance() { System.setProperty(ENV_PROPERTY_KEY, "test-yaml"); System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME, REGISTRY_CONF_DEFAULT); ConfigurationFactory.reload(); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"), "file-test-yaml.conf"); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testBlank"), ""); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testNull"), null); - Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testExist"), null); Configuration instance = ConfigurationFactory.getInstance(); - Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"), "true"); - Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8093"); + Assertions.assertEquals("file-test-yaml.conf", instance.getString("config.file.name")); + Assertions.assertEquals("", instance.getString("config.file.testBlank")); + Assertions.assertNull(instance.getString("config.file.testNull")); + Assertions.assertNull(instance.getString("config.file.testExist")); + Assertions.assertEquals("true", instance.getString("service.disableGlobalTransaction")); + Assertions.assertEquals("127.0.0.1:8093", instance.getString("service.default.grouplist")); } @AfterAll diff --git a/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigSourceProvider.java b/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigSourceProvider.java new file mode 100644 index 00000000000..ddb533b975c --- /dev/null +++ b/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigSourceProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.custom; + +import java.util.stream.Stream; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.LoadLevel; +import io.seata.common.util.StringUtils; +import io.seata.config.Configuration; +import io.seata.config.ConfigurationFactory; +import io.seata.config.ConfigurationKeys; +import io.seata.config.source.ConfigSourceType; +import io.seata.config.source.ConfigSourceProvider; + +/** + * @author ggndnn + */ +@LoadLevel(name = "Custom") +public class CustomConfigSourceProvider implements ConfigSourceProvider { + @Override + public void provide(Configuration configuration) { + String customProviderNameConfigKey = ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + + ConfigSourceType.Custom.name().toLowerCase() + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + + "name"; + String customProviderName = ConfigurationFactory.getInstance().getString(customProviderNameConfigKey); + if (StringUtils.isBlank(customProviderName)) { + throw new IllegalArgumentException("Provider name of custom config type must be not blank"); + } + if ("Custom".equalsIgnoreCase(customProviderName)) { + throw new IllegalArgumentException("Provider name of custom config type can't be equal to 'Custom'"); + } + + if (Stream.of(ConfigSourceType.values()) + .anyMatch(ct -> ct.name().equalsIgnoreCase(customProviderName))) { + throw new IllegalArgumentException(String.format("custom config type name %s is not allowed", customProviderName)); + } + + EnhancedServiceLoader.load(ConfigSourceProvider.class, customProviderName).provide(configuration); + } +} diff --git a/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigurationProvider.java b/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigurationProvider.java deleted file mode 100644 index 1ddb49993de..00000000000 --- a/config/seata-config-custom/src/main/java/io/seata/config/custom/CustomConfigurationProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config.custom; - -import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.loader.LoadLevel; -import io.seata.common.util.StringUtils; -import io.seata.config.ConfigType; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationKeys; -import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationProvider; - -import java.util.stream.Stream; - -/** - * @author ggndnn - */ -@LoadLevel(name = "Custom") -public class CustomConfigurationProvider implements ConfigurationProvider { - @Override - public Configuration provide() { - String pathDataId = ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR - + ConfigType.Custom.name().toLowerCase() + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR - + "name"; - String name = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig(pathDataId); - if (StringUtils.isBlank(name)) { - throw new IllegalArgumentException("name value of custom config type must not be blank"); - } - if (Stream.of(ConfigType.values()) - .anyMatch(ct -> ct.name().equalsIgnoreCase(name))) { - throw new IllegalArgumentException(String.format("custom config type name %s is not allowed", name)); - } - return EnhancedServiceLoader.load(ConfigurationProvider.class, name).provide(); - } -} diff --git a/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index 207829a6fbf..00000000000 --- a/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.custom.CustomConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..7665d684165 --- /dev/null +++ b/config/seata-config-custom/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.custom.CustomConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-custom/src/test/java/io/seata/config/ConfigurationTest.java b/config/seata-config-custom/src/test/java/io/seata/config/ConfigurationTest.java index d85734600d0..92cc579b479 100644 --- a/config/seata-config-custom/src/test/java/io/seata/config/ConfigurationTest.java +++ b/config/seata-config-custom/src/test/java/io/seata/config/ConfigurationTest.java @@ -50,38 +50,38 @@ void test_getConfig_Methods() { //string dataId = "string"; - assertThat(configuration.getConfig(dataId)).isEqualTo(STRING_VALUE); - assertThat(configuration.getConfig(dataId + NULL_POSTFIX)).isNull(); - assertThat(configuration.getConfig(dataId + DEFAULT_POSTFIX, DEFAULT_STRING_VALUE)).isEqualTo(DEFAULT_STRING_VALUE); + assertThat(configuration.getString(dataId)).isEqualTo(STRING_VALUE); + assertThat(configuration.getString(dataId + NULL_POSTFIX)).isNull(); + assertThat(configuration.getString(dataId + DEFAULT_POSTFIX, DEFAULT_STRING_VALUE)).isEqualTo(DEFAULT_STRING_VALUE); //short dataId = "short"; assertThat(configuration.getShort(dataId)).isEqualTo(SHORT_VALUE); - assertThat(configuration.getShort(dataId + NULL_POSTFIX)).isEqualTo(AbstractConfiguration.DEFAULT_SHORT); + assertThat(configuration.getShort(dataId + NULL_POSTFIX)).isEqualTo(Configuration.DEFAULT_SHORT); assertThat(configuration.getShort(dataId + DEFAULT_POSTFIX, DEFAULT_SHORT_VALUE)).isEqualTo(DEFAULT_SHORT_VALUE); //int dataId = "int"; assertThat(configuration.getInt(dataId)).isEqualTo(INT_VALUE); - assertThat(configuration.getInt(dataId + NULL_POSTFIX)).isEqualTo(AbstractConfiguration.DEFAULT_INT); + assertThat(configuration.getInt(dataId + NULL_POSTFIX)).isEqualTo(Configuration.DEFAULT_INT); assertThat(configuration.getInt(dataId + DEFAULT_POSTFIX, DEFAULT_INT_VALUE)).isEqualTo(DEFAULT_INT_VALUE); //long dataId = "long"; assertThat(configuration.getLong(dataId)).isEqualTo(LONG_VALUE); - assertThat(configuration.getLong(dataId + NULL_POSTFIX)).isEqualTo(AbstractConfiguration.DEFAULT_LONG); + assertThat(configuration.getLong(dataId + NULL_POSTFIX)).isEqualTo(Configuration.DEFAULT_LONG); assertThat(configuration.getLong(dataId + DEFAULT_POSTFIX, DEFAULT_LONG_VALUE)).isEqualTo(DEFAULT_LONG_VALUE); //duration dataId = "duration"; assertThat(configuration.getDuration(dataId)).isEqualTo(DURATION_VALUE); - assertThat(configuration.getDuration(dataId + NULL_POSTFIX)).isEqualTo(AbstractConfiguration.DEFAULT_DURATION); + assertThat(configuration.getDuration(dataId + NULL_POSTFIX)).isEqualTo(Configuration.DEFAULT_DURATION); assertThat(configuration.getDuration(dataId + DEFAULT_POSTFIX, DEFAULT_DURATION_VALUE)).isEqualTo(DEFAULT_DURATION_VALUE); //boolean dataId = "boolean"; assertThat(configuration.getBoolean(dataId)).isEqualTo(BOOLEAN_VALUE); - assertThat(configuration.getBoolean(dataId + NULL_POSTFIX)).isEqualTo(AbstractConfiguration.DEFAULT_BOOLEAN); + assertThat(configuration.getBoolean(dataId + NULL_POSTFIX)).isEqualTo(Configuration.DEFAULT_BOOLEAN); assertThat(configuration.getBoolean(dataId + DEFAULT_POSTFIX, DEFAULT_BOOLEAN_VALUE)).isEqualTo(DEFAULT_BOOLEAN_VALUE); } } \ No newline at end of file diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceForTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceForTest.java new file mode 100644 index 00000000000..c97d99ce146 --- /dev/null +++ b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceForTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import javax.annotation.Nonnull; + +import io.seata.config.source.ConfigSource; + +import static io.seata.config.source.ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + +public class CustomConfigSourceForTest implements ConfigSource { + private Properties properties; + private String name; + + public CustomConfigSourceForTest(String name) { + this.name = name; + try (InputStream input = CustomConfigSourceForTest.class.getClassLoader().getResourceAsStream(name)) { + properties = new Properties(); + properties.load(input); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Nonnull + @Override + public String getName() { + return "forTest: " + name; + } + + @Override + public int getOrder() { + return CONFIG_CENTER_SOURCE_ORDER; + } + + @Override + public String getLatestConfig(String dataId, long timeoutMills) { + return properties.getProperty(dataId); + } +} diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationProviderForTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceProviderForTest.java similarity index 72% rename from config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationProviderForTest.java rename to config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceProviderForTest.java index 5b7d5f0cc73..a19fa54664d 100644 --- a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationProviderForTest.java +++ b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceProviderForTest.java @@ -16,14 +16,15 @@ package io.seata.config; import io.seata.common.loader.LoadLevel; +import io.seata.config.source.ConfigSourceProvider; /** * @author ggndnn */ @LoadLevel(name = "forTest") -public class CustomConfigurationProviderForTest implements ConfigurationProvider { +public class CustomConfigSourceProviderForTest implements ConfigSourceProvider { @Override - public Configuration provide() { - return new CustomConfigurationForTest("custom_for_test.properties"); + public void provide(Configuration configuration) { + configuration.addSource(new CustomConfigSourceForTest("custom_for_test.properties")); } } diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceTest.java similarity index 79% rename from config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java rename to config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceTest.java index da0751ec267..82e076397ae 100644 --- a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationTest.java +++ b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigSourceTest.java @@ -17,28 +17,28 @@ import java.io.InputStream; import java.util.Properties; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * @author ggndnn */ -public class CustomConfigurationTest { +public class CustomConfigSourceTest { @Test public void testCustomConfigLoad() throws Exception { - ConfigurationCache.clear(); Configuration configuration = ConfigurationFactory.getInstance(); Assertions.assertNotNull(configuration); Properties properties; - try (InputStream input = CustomConfigurationForTest.class.getClassLoader().getResourceAsStream("custom_for_test.properties")) { + try (InputStream input = CustomConfigSourceForTest.class.getClassLoader().getResourceAsStream("custom_for_test.properties")) { properties = new Properties(); properties.load(input); } Assertions.assertNotNull(properties); for (String name : properties.stringPropertyNames()) { String value = properties.getProperty(name); - Assertions.assertNotNull(value); - Assertions.assertEquals(value, configuration.getConfig(name)); + Assertions.assertNotNull(value, name + " is null"); + Assertions.assertEquals(value, configuration.getString(name), name + " is not equal"); } } } \ No newline at end of file diff --git a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java b/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java deleted file mode 100644 index 577c195d12a..00000000000 --- a/config/seata-config-custom/src/test/java/io/seata/config/CustomConfigurationForTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.util.Set; - -public class CustomConfigurationForTest extends AbstractConfiguration { - private Properties properties; - - public CustomConfigurationForTest(String name) { - try (InputStream input = CustomConfigurationForTest.class.getClassLoader().getResourceAsStream(name)) { - properties = new Properties(); - properties.load(input); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public String getTypeName() { - return "forTest"; - } - - @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { - return properties.getProperty(dataId, defaultValue); - } - - @Override - public boolean putConfig(String dataId, String content, long timeoutMills) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeConfig(String dataId, long timeoutMills) { - throw new UnsupportedOperationException(); - } - - @Override - public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeConfigListener(String dataId, ConfigurationChangeListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public Set getConfigListeners(String dataId) { - throw new UnsupportedOperationException(); - } -} diff --git a/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index e48a98d7ad8..00000000000 --- a/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.CustomConfigurationProviderForTest \ No newline at end of file diff --git a/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..47a8af444af --- /dev/null +++ b/config/seata-config-custom/src/test/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.CustomConfigSourceProviderForTest \ No newline at end of file diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSource.java similarity index 87% rename from config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java rename to config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSource.java index 02cbd9d6287..f06ee3c8982 100644 --- a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfiguration.java +++ b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSource.java @@ -16,7 +16,6 @@ package io.seata.config.etcd3; import java.io.IOException; - import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.List; @@ -31,6 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; import io.etcd.jetcd.ByteSequence; import io.etcd.jetcd.Client; @@ -50,31 +50,33 @@ import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; import io.seata.config.ConfigFuture; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; import io.seata.config.processor.ConfigProcessor; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; +import io.seata.config.source.UpdatableConfigSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static io.netty.util.CharsetUtil.UTF_8; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_CONFIG; /** - * The type Etcd configuration. + * The type Etcd config source. * * @author xingfudeshi @gmail.com */ -public class EtcdConfiguration extends AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(EtcdConfiguration.class); - private static volatile EtcdConfiguration instance; +public class EtcdConfigSource implements RemoteConfigSource + , UpdatableConfigSource, ConfigurationChangeListenerManager { + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdConfigSource.class); + private static volatile EtcdConfigSource instance; private static volatile Client client; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; private static final String SERVER_ADDR_KEY = "serverAddr"; private static final String ETCD_CONFIG_KEY = "key"; private static final String CONFIG_TYPE = "etcd3"; @@ -83,14 +85,16 @@ public class EtcdConfiguration extends AbstractConfiguration { + FILE_CONFIG_SPLIT_CHAR; private static final int THREAD_POOL_NUM = 1; private static final int MAP_INITIAL_CAPACITY = 8; - private ExecutorService etcdConfigExecutor; - private static final ConcurrentMap> CONFIG_LISTENERS_MAP = new ConcurrentHashMap<>( - MAP_INITIAL_CAPACITY); - private static volatile Properties seataConfig = new Properties(); + private static final ConcurrentMap> CONFIG_LISTENERS_MAP = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); private static final long VERSION_NOT_EXIST = 0; - private EtcdConfiguration() { + + private ExecutorService etcdConfigExecutor; + private volatile Properties seataConfig = new Properties(); + + + private EtcdConfigSource() { etcdConfigExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcd-config-executor", THREAD_POOL_NUM)); @@ -102,29 +106,35 @@ private EtcdConfiguration() { * * @return instance */ - public static EtcdConfiguration getInstance() { + public static EtcdConfigSource getInstance() { if (instance == null) { - synchronized (EtcdConfiguration.class) { + synchronized (EtcdConfigSource.class) { if (instance == null) { - instance = new EtcdConfiguration(); + instance = new EtcdConfigSource(); } } } return instance; } + @Nonnull @Override - public String getTypeName() { + public String getName() { return CONFIG_TYPE; } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + } + + @Override + public String getLatestConfig(String dataId, long timeoutMills) { String value = seataConfig.getProperty(dataId); if (value != null) { return value; } - ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, + ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.GET, timeoutMills); etcdConfigExecutor.execute( () -> complete(getClient().getKVClient().get(ByteSequence.from(dataId, UTF_8)), configFuture)); @@ -198,10 +208,10 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene if (StringUtils.isBlank(dataId) || listener == null) { return; } - EtcdListener etcdListener = new EtcdListener(dataId, listener); + EtcdListener etcdListener = new EtcdListener(dataId, listener, this); CONFIG_LISTENERS_MAP.computeIfAbsent(dataId, key -> ConcurrentHashMap.newKeySet()) .add(etcdListener); - etcdListener.onProcessEvent(new ConfigurationChangeEvent()); + etcdListener.onProcessEvent(new ConfigurationChangeEvent(this)); } @Override @@ -223,6 +233,11 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list } } + @Override + public Set getListenedConfigDataIds() { + return CONFIG_LISTENERS_MAP.keySet(); + } + @Override public Set getConfigListeners(String dataId) { return CONFIG_LISTENERS_MAP.get(dataId); @@ -235,9 +250,9 @@ public Set getConfigListeners(String dataId) { */ private static Client getClient() { if (client == null) { - synchronized (EtcdConfiguration.class) { + synchronized (EtcdConfigSource.class) { if (client == null) { - client = Client.builder().endpoints(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)) + client = Client.builder().endpoints(ConfigurationFactory.getInstance().getString(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)) .build(); } } @@ -277,11 +292,11 @@ private static void complete(CompletableFuture completableFuture, ConfigF throw new ShouldNeverHappenException("unsupported response type"); } } catch (Exception e) { - LOGGER.error("error occurred while completing the future{}", e.getMessage(),e); + LOGGER.error("error occurred while completing the future:", e); } } - private static void initSeataConfig() { + private void initSeataConfig() { String etcdConfigKey = getEtcdConfigKey(); CompletableFuture future = getClient().getKVClient().get(ByteSequence.from(etcdConfigKey, UTF_8)); try { @@ -290,10 +305,10 @@ private static void initSeataConfig() { if (!kvs.isEmpty()) { seataConfig = ConfigProcessor.processConfig(new String(kvs.get(0).getValue().getBytes(), StandardCharsets.UTF_8), getEtcdDataType()); - EtcdListener etcdListener = new EtcdListener(etcdConfigKey, null); + EtcdListener etcdListener = new EtcdListener(etcdConfigKey, null, this); CONFIG_LISTENERS_MAP.computeIfAbsent(etcdConfigKey, key -> new ConcurrentSet<>()) .add(etcdListener); - etcdListener.onProcessEvent(new ConfigurationChangeEvent()); + etcdListener.onProcessEvent(new ConfigurationChangeEvent(this)); } } catch (Exception e) { LOGGER.error("init config properties error", e); @@ -301,12 +316,14 @@ private static void initSeataConfig() { } private static String getEtcdConfigKey() { - return FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + ETCD_CONFIG_KEY, DEFAULT_ETCD_CONFIG_KEY_VALUE); + return ConfigurationFactory.getInstance().getString(FILE_CONFIG_KEY_PREFIX + ETCD_CONFIG_KEY, DEFAULT_ETCD_CONFIG_KEY_VALUE); } + private static String getEtcdDataType() { return ConfigProcessor.resolverConfigDataType(getEtcdConfigKey()); } - private static String getSeataConfigStr() { + + private String getSeataConfigStr() { StringBuilder sb = new StringBuilder(); Enumeration enumeration = seataConfig.propertyNames(); @@ -329,6 +346,8 @@ private static class EtcdListener implements ConfigurationChangeListener { private final ExecutorService executor = new ThreadPoolExecutor(CORE_LISTENER_THREAD, MAX_LISTENER_THREAD, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("etcdListener", MAX_LISTENER_THREAD)); + private final EtcdConfigSource source; + /** * Instantiates a new Etcd listener. @@ -336,9 +355,10 @@ private static class EtcdListener implements ConfigurationChangeListener { * @param dataId the data id * @param listener the listener */ - public EtcdListener(String dataId, ConfigurationChangeListener listener) { + public EtcdListener(String dataId, ConfigurationChangeListener listener, EtcdConfigSource source) { this.dataId = dataId; this.listener = listener; + this.source = source; } /** @@ -366,7 +386,7 @@ public void onNext(WatchResponse watchResponse) { if (dataId.equals(getEtcdConfigKey())) { byte[] bytes = watchResponse.getEvents().get(0).getKeyValue().getValue().getBytes(); Properties seataConfigNew; - try { + try { seataConfigNew = ConfigProcessor.processConfig(new String(bytes, StandardCharsets.UTF_8), getEtcdDataType()); } catch (IOException e) { LOGGER.error("load config properties error", e); @@ -375,17 +395,17 @@ public void onNext(WatchResponse watchResponse) { for (Map.Entry> entry : CONFIG_LISTENERS_MAP.entrySet()) { String key = entry.getKey(); - String valueOld = seataConfig.getProperty(key, ""); + String valueOld = source.seataConfig.getProperty(key, ""); String valueNew = seataConfigNew.getProperty(key, ""); if (!valueOld.equals(valueNew)) { for (ConfigurationChangeListener changeListener : entry.getValue()) { event.setDataId(key).setNewValue(valueNew); - ConfigurationChangeListener listener = ((EtcdListener) changeListener).getTargetListener(); + ConfigurationChangeListener listener = ((EtcdListener)changeListener).getTargetListener(); listener.onProcessEvent(event); } } } - seataConfig = seataConfigNew; + source.seataConfig = seataConfigNew; return; } diff --git a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigurationProvider.java b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSourceProvider.java similarity index 77% rename from config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigurationProvider.java rename to config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSourceProvider.java index 0bf9094c131..9fdd2f7c712 100644 --- a/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigurationProvider.java +++ b/config/seata-config-etcd3/src/main/java/io/seata/config/etcd3/EtcdConfigSourceProvider.java @@ -17,15 +17,15 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; /** * @author xingfudeshi@gmail.com */ @LoadLevel(name = "Etcd3", order = 1) -public class EtcdConfigurationProvider implements ConfigurationProvider { +public class EtcdConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - return EtcdConfiguration.getInstance(); + public void provide(Configuration configuration) { + configuration.addSource(EtcdConfigSource.getInstance()); } } diff --git a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index 22d67274f7e..00000000000 --- a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.etcd3.EtcdConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..e12a28f0023 --- /dev/null +++ b/config/seata-config-etcd3/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.etcd3.EtcdConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSource.java similarity index 75% rename from config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java rename to config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSource.java index dde9431941d..5d9494f9068 100644 --- a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java +++ b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSource.java @@ -22,35 +22,44 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import javax.annotation.Nonnull; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.AbstractSharedListener; import com.alibaba.nacos.api.exception.NacosException; +import io.seata.common.ConfigurationKeys; +import io.seata.common.exception.FrameworkException; import io.seata.common.exception.NotSupportYetException; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; import io.seata.config.Configuration; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationKeys; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; import io.seata.config.processor.ConfigProcessor; +import io.seata.config.source.ConfigSource; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; +import io.seata.config.source.UpdatableConfigSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static io.seata.config.Configuration.DEFAULT_CONFIG_TIMEOUT; /** - * The type Nacos configuration. + * The type Nacos config source. * * @author slievrly * @author xingfudeshi@gmail.com */ -public class NacosConfiguration extends AbstractConfiguration { - private static volatile NacosConfiguration instance; +public class NacosConfigSource implements RemoteConfigSource + , UpdatableConfigSource, ConfigurationChangeListenerManager { - private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfiguration.class); + private static volatile NacosConfigSource instance; + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosConfigSource.class); private static final String DEFAULT_GROUP = "SEATA_GROUP"; private static final String DEFAULT_DATA_ID = "seata.properties"; private static final String GROUP_KEY = "group"; @@ -65,23 +74,27 @@ public class NacosConfiguration extends AbstractConfiguration { private static final String SECRET_KEY = "secretKey"; private static final String USE_PARSE_RULE = "false"; private static final String CONTEXT_PATH = "contextPath"; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); private static volatile ConfigService configService; private static final int MAP_INITIAL_CAPACITY = 8; private static final ConcurrentMap> CONFIG_LISTENERS_MAP = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); private static volatile Properties seataConfig = new Properties(); + private static String nacosDataId; + private static String nacosGroup; + private static String nacosDataType; + /** * Get instance of NacosConfiguration * * @return instance */ - public static NacosConfiguration getInstance() { + public static NacosConfigSource getInstance() { if (instance == null) { - synchronized (NacosConfiguration.class) { + synchronized (NacosConfigSource.class) { if (instance == null) { - instance = new NacosConfiguration(); + instance = new NacosConfigSource(); } } } @@ -91,29 +104,26 @@ public static NacosConfiguration getInstance() { /** * Instantiates a new Nacos configuration. */ - private NacosConfiguration() { - if (configService == null) { - try { - configService = NacosFactory.createConfigService(getConfigProperties()); - initSeataConfig(); - } catch (NacosException e) { - throw new RuntimeException(e); - } - } + private NacosConfigSource() { + buildConfigService(); + this.initSeataConfig(); } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { + public String getLatestConfig(String dataId, long timeoutMills) { String value = seataConfig.getProperty(dataId); + if (null == value) { try { - value = configService.getConfig(dataId, getNacosGroup(), timeoutMills); + value = configService.getConfig(dataId, this.nacosGroup, timeoutMills); } catch (NacosException exx) { - LOGGER.error(exx.getErrMsg()); + String errorMsg = "get remote config '" + dataId + "' failed"; + LOGGER.error(errorMsg + ", exception: {}", exx.getErrMsg()); + throw new FrameworkException(exx, errorMsg); } } - return value == null ? defaultValue : value; + return value; } @Override @@ -122,9 +132,9 @@ public boolean putConfig(String dataId, String content, long timeoutMills) { try { if (!seataConfig.isEmpty()) { seataConfig.setProperty(dataId, content); - result = configService.publishConfig(getNacosDataId(), getNacosGroup(), getSeataConfigStr()); + result = configService.publishConfig(this.nacosDataId, this.nacosGroup, getSeataConfigStr()); } else { - result = configService.publishConfig(dataId, getNacosGroup(), content); + result = configService.publishConfig(dataId, this.nacosGroup, content); } } catch (NacosException exx) { LOGGER.error(exx.getErrMsg()); @@ -143,9 +153,9 @@ public boolean removeConfig(String dataId, long timeoutMills) { try { if (!seataConfig.isEmpty()) { seataConfig.remove(dataId); - result = configService.publishConfig(getNacosDataId(), getNacosGroup(), getSeataConfigStr()); + result = configService.publishConfig(this.nacosDataId, this.nacosGroup, getSeataConfigStr()); } else { - result = configService.removeConfig(dataId, getNacosGroup()); + result = configService.removeConfig(dataId, this.nacosGroup); } } catch (NacosException exx) { LOGGER.error(exx.getErrMsg()); @@ -159,10 +169,10 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene return; } try { - NacosListener nacosListener = new NacosListener(dataId, listener); + NacosListener nacosListener = new NacosListener(dataId, listener, this); CONFIG_LISTENERS_MAP.computeIfAbsent(dataId, key -> new ConcurrentHashMap<>()) .put(listener, nacosListener); - configService.addListener(dataId, getNacosGroup(), nacosListener); + configService.addListener(dataId, this.nacosGroup, nacosListener); } catch (Exception exx) { LOGGER.error("add nacos listener error:{}", exx.getMessage(), exx); } @@ -184,7 +194,7 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list configListeners.remove(entry); } if (nacosListener != null) { - configService.removeListener(dataId, getNacosGroup(), nacosListener); + configService.removeListener(dataId, nacosGroup, nacosListener); } break; } @@ -192,6 +202,11 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list } } + @Override + public Set getListenedConfigDataIds() { + return CONFIG_LISTENERS_MAP.keySet(); + } + @Override public Set getConfigListeners(String dataId) { Map configListeners = CONFIG_LISTENERS_MAP.get(dataId); @@ -209,7 +224,7 @@ private static Properties getConfigProperties() { if (System.getProperty(PRO_SERVER_ADDR_KEY) != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, System.getProperty(PRO_SERVER_ADDR_KEY)); } else { - String address = FILE_CONFIG.getConfig(getNacosAddrFileKey()); + String address = CONFIG.getString(getNacosAddrFileKey()); if (address != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, address); } @@ -218,15 +233,15 @@ private static Properties getConfigProperties() { if (System.getProperty(PRO_NAMESPACE_KEY) != null) { properties.setProperty(PRO_NAMESPACE_KEY, System.getProperty(PRO_NAMESPACE_KEY)); } else { - String namespace = FILE_CONFIG.getConfig(getNacosNameSpaceFileKey()); + String namespace = CONFIG.getString(getNacosNameSpaceFileKey()); if (namespace == null) { namespace = DEFAULT_NAMESPACE; } properties.setProperty(PRO_NAMESPACE_KEY, namespace); } - String userName = StringUtils.isNotBlank(System.getProperty(USER_NAME)) ? System.getProperty(USER_NAME) : FILE_CONFIG.getConfig(getNacosUserName()); + String userName = StringUtils.isNotBlank(System.getProperty(USER_NAME)) ? System.getProperty(USER_NAME) : CONFIG.getString(getNacosUserName()); if (StringUtils.isNotBlank(userName)) { - String password = StringUtils.isNotBlank(System.getProperty(PASSWORD)) ? System.getProperty(PASSWORD) : FILE_CONFIG.getConfig(getNacosPassword()); + String password = StringUtils.isNotBlank(System.getProperty(PASSWORD)) ? System.getProperty(PASSWORD) : CONFIG.getString(getNacosPassword()); if (StringUtils.isNotBlank(password)) { properties.setProperty(USER_NAME, userName); properties.setProperty(PASSWORD, password); @@ -234,10 +249,10 @@ private static Properties getConfigProperties() { } } else { String accessKey = StringUtils.isNotBlank(System.getProperty(ACCESS_KEY)) ? - System.getProperty(ACCESS_KEY) : FILE_CONFIG.getConfig(getNacosAccessKey()); + System.getProperty(ACCESS_KEY) : CONFIG.getString(getNacosAccessKey()); if (StringUtils.isNotBlank(accessKey)) { String secretKey = StringUtils.isNotBlank(System.getProperty(SECRET_KEY)) ? - System.getProperty(SECRET_KEY) : FILE_CONFIG.getConfig(getNacosSecretKey()); + System.getProperty(SECRET_KEY) : CONFIG.getString(getNacosSecretKey()); if (StringUtils.isNotBlank(secretKey)) { properties.put(ACCESS_KEY, accessKey); properties.put(SECRET_KEY, secretKey); @@ -245,7 +260,7 @@ private static Properties getConfigProperties() { } } } - String contextPath = StringUtils.isNotBlank(System.getProperty(CONTEXT_PATH)) ? System.getProperty(CONTEXT_PATH) : FILE_CONFIG.getConfig(getNacosContextPathKey()); + String contextPath = StringUtils.isNotBlank(System.getProperty(CONTEXT_PATH)) ? System.getProperty(CONTEXT_PATH) : CONFIG.getString(getNacosContextPathKey()); if (StringUtils.isNotBlank(contextPath)) { properties.setProperty(CONTEXT_PATH, contextPath); } @@ -287,15 +302,15 @@ public static String getNacosSecretKey() { } private static String getNacosGroup() { - return FILE_CONFIG.getConfig(getNacosGroupKey(), DEFAULT_GROUP); + return CONFIG.getString(getNacosGroupKey(), DEFAULT_GROUP); } private static String getNacosDataId() { - return FILE_CONFIG.getConfig(getNacosDataIdKey(), DEFAULT_DATA_ID); + return CONFIG.getString(getNacosDataIdKey(), DEFAULT_DATA_ID); } private static String getNacosDataType() { - return ConfigProcessor.resolverConfigDataType(getNacosDataId()); + return ConfigProcessor.resolverConfigDataType(nacosDataId); } private static String getSeataConfigStr() { @@ -315,15 +330,32 @@ private static String getNacosContextPathKey() { return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_CONFIG, CONFIG_TYPE, CONTEXT_PATH); } - private static void initSeataConfig() { + private static void buildConfigService() { + if (configService == null) { + synchronized (NacosConfigSource.class) { + if (configService == null) { + try { + configService = NacosFactory.createConfigService(getConfigProperties()); + } catch (NacosException e) { + throw new RuntimeException("Create config service failed:", e); + } + } + } + } + } + + private void initSeataConfig() { try { - String nacosDataId = getNacosDataId(); - String config = configService.getConfig(nacosDataId, getNacosGroup(), DEFAULT_CONFIG_TIMEOUT); + nacosDataId = getNacosDataId(); + nacosGroup = getNacosGroup(); + nacosDataType = getNacosDataType(); + + String config = configService.getConfig(nacosDataId, nacosGroup, DEFAULT_CONFIG_TIMEOUT); if (StringUtils.isNotBlank(config)) { - seataConfig = ConfigProcessor.processConfig(config, getNacosDataType()); + seataConfig = ConfigProcessor.processConfig(config, nacosDataType); - NacosListener nacosListener = new NacosListener(nacosDataId, null); - configService.addListener(nacosDataId, getNacosGroup(), nacosListener); + NacosListener nacosListener = new NacosListener(nacosDataId, null, this); + configService.addListener(nacosDataId, nacosGroup, nacosListener); } } catch (NacosException | IOException e) { LOGGER.error("init config properties error", e); @@ -331,27 +363,36 @@ private static void initSeataConfig() { } + @Nonnull @Override - public String getTypeName() { + public String getName() { return CONFIG_TYPE; } + @Override + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + } + /** * Non-blocking subscriptions prohibit adding subscriptions in the thread pool to prevent thread termination */ public static class NacosListener extends AbstractSharedListener { private final String dataId; private final ConfigurationChangeListener listener; + private final ConfigSource source; /** * Instantiates a new Nacos listener. * * @param dataId the data id * @param listener the listener + * @param source the source */ - public NacosListener(String dataId, ConfigurationChangeListener listener) { + public NacosListener(String dataId, ConfigurationChangeListener listener, ConfigSource source) { this.dataId = dataId; this.listener = listener; + this.source = source; } /** @@ -366,11 +407,11 @@ public ConfigurationChangeListener getTargetListener() { @Override public void innerReceive(String dataId, String group, String configInfo) { //The new configuration method to puts all configurations into a dateId - if (getNacosDataId().equals(dataId)) { + if (nacosDataId.equals(dataId)) { Properties seataConfigNew = new Properties(); if (StringUtils.isNotBlank(configInfo)) { try { - seataConfigNew = ConfigProcessor.processConfig(configInfo, getNacosDataType()); + seataConfigNew = ConfigProcessor.processConfig(configInfo, nacosDataType); } catch (IOException e) { LOGGER.error("load config properties error", e); return; @@ -383,7 +424,7 @@ public void innerReceive(String dataId, String group, String configInfo) { String propertyOld = seataConfig.getProperty(listenedDataId, ""); String propertyNew = seataConfigNew.getProperty(listenedDataId, ""); if (!propertyOld.equals(propertyNew)) { - ConfigurationChangeEvent event = new ConfigurationChangeEvent() + ConfigurationChangeEvent event = new ConfigurationChangeEvent(source) .setDataId(listenedDataId) .setNewValue(propertyNew) .setNamespace(group); @@ -400,7 +441,7 @@ public void innerReceive(String dataId, String group, String configInfo) { } //Compatible with old writing - ConfigurationChangeEvent event = new ConfigurationChangeEvent().setDataId(dataId).setNewValue(configInfo) + ConfigurationChangeEvent event = new ConfigurationChangeEvent(source).setDataId(dataId).setNewValue(configInfo) .setNamespace(group); listener.onProcessEvent(event); } diff --git a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigurationProvider.java b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSourceProvider.java similarity index 77% rename from config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigurationProvider.java rename to config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSourceProvider.java index 63d3582dabd..1484eb4158d 100644 --- a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigurationProvider.java +++ b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfigSourceProvider.java @@ -17,15 +17,15 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; /** * @author xingfudeshi@gmail.com */ @LoadLevel(name = "Nacos", order = 1) -public class NacosConfigurationProvider implements ConfigurationProvider { +public class NacosConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - return NacosConfiguration.getInstance(); + public void provide(Configuration configuration) { + configuration.addSource(NacosConfigSource.getInstance()); } } diff --git a/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index 64e931fa254..00000000000 --- a/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.nacos.NacosConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..86d76c66125 --- /dev/null +++ b/config/seata-config-nacos/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.nacos.NacosConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigurationTest.java b/config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigSourceTest.java similarity index 91% rename from config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigurationTest.java rename to config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigSourceTest.java index ee8d793d744..7ab44bbc06d 100644 --- a/config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigurationTest.java +++ b/config/seata-config-nacos/src/test/java/io/seata/config/nacos/NacosConfigSourceTest.java @@ -28,11 +28,11 @@ * * @author xingfudeshi@gmail.com */ -public class NacosConfigurationTest { +public class NacosConfigSourceTest { @Test public void testGetConfigProperties() throws Exception { - Method method = ReflectionUtil.getMethod(NacosConfiguration.class, "getConfigProperties"); + Method method = ReflectionUtil.getMethod(NacosConfigSource.class, "getConfigProperties"); Properties properties = (Properties) ReflectionUtil.invokeMethod(null, method); Assertions.assertThat(properties.getProperty("contextPath")).isEqualTo("/bar"); System.setProperty("contextPath", "/foo"); diff --git a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSource.java b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSource.java new file mode 100644 index 00000000000..ed54900e4e2 --- /dev/null +++ b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSource.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.config.springcloud; + +import javax.annotation.Nonnull; + +import io.seata.common.holder.ObjectHolder; +import io.seata.common.util.StringUtils; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; +import org.springframework.context.ApplicationContext; + +/** + * The type SpringCloud config source + */ +public class SpringCloudConfigSource implements RemoteConfigSource { + + private static final String CONFIG_TYPE = "SpringCloudConfig"; + private static final String PREFIX = "seata."; + + private static volatile SpringCloudConfigSource instance; + + + public static SpringCloudConfigSource getInstance() { + if (instance == null) { + synchronized (SpringCloudConfigSource.class) { + if (instance == null) { + instance = new SpringCloudConfigSource(); + } + } + } + return instance; + } + + + private SpringCloudConfigSource() { + } + + + @Nonnull + @Override + public String getName() { + return CONFIG_TYPE; + } + + @Override + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + } + + @Override + public String getLatestConfig(String dataId, long timeoutMills) { + ApplicationContext applicationContext = ObjectHolder.INSTANCE.getObject(ApplicationContext.class); + if (applicationContext == null || applicationContext.getEnvironment() == null) { + return null; + } + String conf = applicationContext.getEnvironment().getProperty(PREFIX + dataId); + return StringUtils.isNotBlank(conf) ? conf : null; + } +} diff --git a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigurationProvider.java b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSourceProvider.java similarity index 75% rename from config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigurationProvider.java rename to config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSourceProvider.java index 130a1f96aee..3ac71846edc 100644 --- a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigurationProvider.java +++ b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfigSourceProvider.java @@ -17,12 +17,12 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; @LoadLevel(name = "SpringCloudConfig", order = 1) -public class SpringCloudConfigurationProvider implements ConfigurationProvider { +public class SpringCloudConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - return SpringCloudConfiguration.getInstance(); + public void provide(Configuration configuration) { + configuration.addSource(SpringCloudConfigSource.getInstance()); } } diff --git a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java b/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java deleted file mode 100644 index c715dc4a281..00000000000 --- a/config/seata-config-spring-cloud/src/main/java/io/seata/config/springcloud/SpringCloudConfiguration.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.config.springcloud; - -import java.util.Set; - -import io.seata.common.holder.ObjectHolder; -import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; -import io.seata.config.ConfigurationChangeListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; - -public class SpringCloudConfiguration extends AbstractConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(SpringCloudConfiguration.class); - private static final String CONFIG_TYPE = "SpringCloudConfig"; - private static volatile SpringCloudConfiguration instance; - private static final String PREFIX = "seata."; - - public static SpringCloudConfiguration getInstance() { - if (instance == null) { - synchronized (SpringCloudConfiguration.class) { - if (instance == null) { - instance = new SpringCloudConfiguration(); - } - } - } - return instance; - } - - private SpringCloudConfiguration() { - - } - - @Override - public String getTypeName() { - return CONFIG_TYPE; - } - - @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { - ApplicationContext applicationContext = ObjectHolder.INSTANCE.getObject(ApplicationContext.class); - if (applicationContext == null || applicationContext.getEnvironment() == null) { - return defaultValue; - } - String conf = applicationContext.getEnvironment().getProperty(PREFIX + dataId); - return StringUtils.isNotBlank(conf) ? conf : defaultValue; - } - - @Override - public boolean putConfig(String dataId, String content, long timeoutMills) { - return false; - } - - @Override - public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) { - return false; - } - - @Override - public boolean removeConfig(String dataId, long timeoutMills) { - return false; - } - - @Override - public void addConfigListener(String dataId, ConfigurationChangeListener listener) { - LOGGER.warn("dynamic listening is not supported spring cloud config"); - } - - @Override - public void removeConfigListener(String dataId, ConfigurationChangeListener listener) { - } - - @Override - public Set getConfigListeners(String dataId) { - return null; - } -} diff --git a/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index e5576744b6b..00000000000 --- a/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.springcloud.SpringCloudConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..da658cc42f3 --- /dev/null +++ b/config/seata-config-spring-cloud/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.springcloud.SpringCloudConfigSourceProvider \ No newline at end of file diff --git a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSource.java similarity index 86% rename from config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java rename to config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSource.java index aad2dc520f8..d65f9571c57 100644 --- a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java +++ b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSource.java @@ -28,18 +28,24 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import io.seata.common.exception.FrameworkException; import io.seata.common.exception.NotSupportYetException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; -import io.seata.config.AbstractConfiguration; import io.seata.config.Configuration; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; -import io.seata.config.ConfigurationChangeType; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; +import io.seata.config.changelistener.ConfigurationChangeListenerManager; +import io.seata.config.changelistener.ConfigurationChangeType; import io.seata.config.processor.ConfigProcessor; +import io.seata.config.source.ConfigSource; +import io.seata.config.source.ConfigSourceOrdered; +import io.seata.config.source.RemoteConfigSource; +import io.seata.config.source.UpdatableConfigSource; import org.I0Itec.zkclient.IZkDataListener; import org.I0Itec.zkclient.ZkClient; import org.I0Itec.zkclient.serialize.ZkSerializer; @@ -47,22 +53,23 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG; -import static io.seata.config.ConfigurationKeys.SEATA_FILE_ROOT_CONFIG; +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_CONFIG; +import static io.seata.common.ConfigurationKeys.SEATA_FILE_ROOT_CONFIG; /** - * The type Zookeeper configuration. + * The type Zookeeper config source. * * @author crazier.huang */ -public class ZookeeperConfiguration extends AbstractConfiguration { - private final static Logger LOGGER = LoggerFactory.getLogger(ZookeeperConfiguration.class); +public class ZookeeperConfigSource implements RemoteConfigSource, + UpdatableConfigSource, ConfigurationChangeListenerManager { + private final static Logger LOGGER = LoggerFactory.getLogger(ZookeeperConfigSource.class); private static final String CONFIG_TYPE = "zk"; private static final String ZK_PATH_SPLIT_CHAR = "/"; private static final String ROOT_PATH = ZK_PATH_SPLIT_CHAR + SEATA_FILE_ROOT_CONFIG; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Configuration FILE_CONFIG = ConfigurationFactory.getInstance(); private static final String SERVER_ADDR_KEY = "serverAddr"; private static final String SESSION_TIMEOUT_KEY = "sessionTimeout"; private static final String CONNECT_TIMEOUT_KEY = "connectTimeout"; @@ -89,17 +96,17 @@ public class ZookeeperConfiguration extends AbstractConfiguration { * Instantiates a new Zookeeper configuration. */ @SuppressWarnings("lgtm[java/unsafe-double-checked-locking-init-order]") - public ZookeeperConfiguration() { + public ZookeeperConfigSource() { if (zkClient == null) { - synchronized (ZookeeperConfiguration.class) { + synchronized (ZookeeperConfigSource.class) { if (zkClient == null) { ZkSerializer zkSerializer = getZkSerializer(); - String serverAddr = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); + String serverAddr = FILE_CONFIG.getString(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY); int sessionTimeout = FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIMEOUT_KEY, DEFAULT_SESSION_TIMEOUT); int connectTimeout = FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIMEOUT_KEY, DEFAULT_CONNECT_TIMEOUT); zkClient = new ZkClient(serverAddr, sessionTimeout, connectTimeout, zkSerializer); - String username = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_USERNAME); - String password = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_PASSWORD); + String username = FILE_CONFIG.getString(FILE_CONFIG_KEY_PREFIX + AUTH_USERNAME); + String password = FILE_CONFIG.getString(FILE_CONFIG_KEY_PREFIX + AUTH_PASSWORD); if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) { StringBuilder auth = new StringBuilder(username).append(":").append(password); zkClient.addAuthInfo("digest", auth.toString().getBytes()); @@ -113,13 +120,19 @@ public ZookeeperConfiguration() { } } + @Nonnull @Override - public String getTypeName() { + public String getName() { return CONFIG_TYPE; } @Override - public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) { + public int getOrder() { + return ConfigSourceOrdered.CONFIG_CENTER_SOURCE_ORDER; + } + + @Override + public String getLatestConfig(String dataId, long timeoutMills) { String value = seataConfig.getProperty(dataId); if (value != null) { return value; @@ -127,20 +140,19 @@ public String getLatestConfig(String dataId, String defaultValue, long timeoutMi FutureTask future = new FutureTask<>(() -> { String path = ROOT_PATH + ZK_PATH_SPLIT_CHAR + dataId; if (!zkClient.exists(path)) { - LOGGER.warn("config {} is not existed, return defaultValue {} ", - dataId, defaultValue); - return defaultValue; + LOGGER.warn("config '{}' is not existed", dataId); + return null; } String value1 = zkClient.readData(path); - return StringUtils.isNullOrEmpty(value1) ? defaultValue : value1; + return StringUtils.isNullOrEmpty(value1) ? null : value1; }); CONFIG_EXECUTOR.execute(future); try { return future.get(timeoutMills, TimeUnit.MILLISECONDS); } catch (Exception e) { - LOGGER.error("getConfig {} error or timeout, return defaultValue {}, exception:{} ", - dataId, defaultValue, e.getMessage()); - return defaultValue; + String errorMsg = "get remote config '" + dataId + "' error or timeout"; + LOGGER.error(errorMsg + ", exception: {}", e.getMessage()); + throw new FrameworkException(e, errorMsg); } } @@ -205,7 +217,7 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene } if (!seataConfig.isEmpty()) { - ZKListener zkListener = new ZKListener(dataId, listener); + ZKListener zkListener = new ZKListener(dataId, listener, this); CONFIG_LISTENERS_MAP.computeIfAbsent(dataId, key -> new ConcurrentHashMap<>()) .put(listener, zkListener); return; @@ -213,7 +225,7 @@ public void addConfigListener(String dataId, ConfigurationChangeListener listene String path = ROOT_PATH + ZK_PATH_SPLIT_CHAR + dataId; if (zkClient.exists(path)) { - ZKListener zkListener = new ZKListener(path, listener); + ZKListener zkListener = new ZKListener(path, listener, this); CONFIG_LISTENERS_MAP.computeIfAbsent(dataId, key -> new ConcurrentHashMap<>()) .put(listener, zkListener); zkClient.subscribeDataChanges(path, zkListener); @@ -247,6 +259,11 @@ public void removeConfigListener(String dataId, ConfigurationChangeListener list } } + @Override + public Set getListenedConfigDataIds() { + return CONFIG_LISTENERS_MAP.keySet(); + } + @Override public Set getConfigListeners(String dataId) { ConcurrentMap configListeners = CONFIG_LISTENERS_MAP.get(dataId); @@ -266,13 +283,13 @@ private void initSeataConfig() { } catch (IOException e) { LOGGER.error("init config properties error", e); } - ZKListener zkListener = new ZKListener(configPath, null); + ZKListener zkListener = new ZKListener(configPath, null, this); zkClient.subscribeDataChanges(configPath, zkListener); } } private static String getConfigPath() { - return FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + CONFIG_PATH_KEY, DEFAULT_CONFIG_PATH); + return FILE_CONFIG.getString(FILE_CONFIG_KEY_PREFIX + CONFIG_PATH_KEY, DEFAULT_CONFIG_PATH); } private static String getZkDataType() { @@ -299,6 +316,7 @@ public static class ZKListener implements IZkDataListener { private String path; private ConfigurationChangeListener listener; + private ConfigSource source; /** * Instantiates a new Zk listener. @@ -306,9 +324,10 @@ public static class ZKListener implements IZkDataListener { * @param path the path * @param listener the listener */ - public ZKListener(String path, ConfigurationChangeListener listener) { + public ZKListener(String path, ConfigurationChangeListener listener, ConfigSource source) { this.path = path; this.listener = listener; + this.source = source; } @Override @@ -330,7 +349,7 @@ public void handleDataChange(String s, Object o) { String propertyOld = seataConfig.getProperty(listenedDataId, ""); String propertyNew = seataConfigNew.getProperty(listenedDataId, ""); if (!propertyOld.equals(propertyNew)) { - ConfigurationChangeEvent event = new ConfigurationChangeEvent() + ConfigurationChangeEvent event = new ConfigurationChangeEvent(source) .setDataId(listenedDataId) .setNewValue(propertyNew) .setChangeType(ConfigurationChangeType.MODIFY); @@ -346,7 +365,7 @@ public void handleDataChange(String s, Object o) { return; } String dataId = s.replaceFirst(ROOT_PATH + ZK_PATH_SPLIT_CHAR, ""); - ConfigurationChangeEvent event = new ConfigurationChangeEvent().setDataId(dataId).setNewValue(o.toString()) + ConfigurationChangeEvent event = new ConfigurationChangeEvent(source).setDataId(dataId).setNewValue(o.toString()) .setChangeType(ConfigurationChangeType.MODIFY); listener.onProcessEvent(event); } @@ -354,7 +373,7 @@ public void handleDataChange(String s, Object o) { @Override public void handleDataDeleted(String s) { String dataId = s.replaceFirst(ROOT_PATH + ZK_PATH_SPLIT_CHAR, ""); - ConfigurationChangeEvent event = new ConfigurationChangeEvent().setDataId(dataId).setChangeType( + ConfigurationChangeEvent event = new ConfigurationChangeEvent(source).setDataId(dataId).setChangeType( ConfigurationChangeType.DELETE); listener.onProcessEvent(event); } @@ -362,7 +381,7 @@ public void handleDataDeleted(String s) { private ZkSerializer getZkSerializer() { ZkSerializer zkSerializer = null; - String serializer = FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERIALIZER_KEY); + String serializer = FILE_CONFIG.getString(FILE_CONFIG_KEY_PREFIX + SERIALIZER_KEY); if (StringUtils.isNotBlank(serializer)) { try { Class clazz = Class.forName(serializer); diff --git a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigurationProvider.java b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSourceProvider.java similarity index 72% rename from config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigurationProvider.java rename to config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSourceProvider.java index 09506c5a48e..3710d5ebcc0 100644 --- a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigurationProvider.java +++ b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfigSourceProvider.java @@ -17,19 +17,15 @@ import io.seata.common.loader.LoadLevel; import io.seata.config.Configuration; -import io.seata.config.ConfigurationProvider; +import io.seata.config.source.ConfigSourceProvider; /** * @author xingfudeshi@gmail.com */ @LoadLevel(name = "ZK", order = 1) -public class ZookeeperConfigurationProvider implements ConfigurationProvider { +public class ZookeeperConfigSourceProvider implements ConfigSourceProvider { @Override - public Configuration provide() { - try { - return new ZookeeperConfiguration(); - } catch (Exception e) { - throw new RuntimeException(e); - } + public void provide(Configuration configuration) { + configuration.addSource(new ZookeeperConfigSource()); } } diff --git a/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider deleted file mode 100644 index dcb677f0e86..00000000000 --- a/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.config.zk.ZookeeperConfigurationProvider \ No newline at end of file diff --git a/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider b/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider new file mode 100644 index 00000000000..0ef65e793eb --- /dev/null +++ b/config/seata-config-zk/src/main/resources/META-INF/services/io.seata.config.source.ConfigSourceProvider @@ -0,0 +1 @@ +io.seata.config.zk.ZookeeperConfigSourceProvider \ No newline at end of file diff --git a/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java b/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java index ef5d9a4ddd6..8d42ff8f323 100644 --- a/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java +++ b/core/src/main/java/io/seata/core/protocol/ProtocolConstants.java @@ -16,9 +16,9 @@ package io.seata.core.protocol; import io.seata.config.ConfigurationFactory; -import io.seata.core.serializer.SerializerType; import io.seata.core.compressor.CompressorType; import io.seata.core.constants.ConfigurationKeys; +import io.seata.core.serializer.SerializerType; /** * @author Geng Zhang @@ -45,7 +45,7 @@ public interface ProtocolConstants { * HEAD_LENGTH of protocol v1 */ int V1_HEAD_LENGTH = 16; - + /** * Message type: Request */ @@ -72,11 +72,11 @@ public interface ProtocolConstants { /** * Configured codec by user, default is SEATA - * + * * @see SerializerType#SEATA */ byte CONFIGURED_CODEC = SerializerType.getByName(ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.SERIALIZE_FOR_RPC, SerializerType.SEATA.name())).getCode(); + .getString(ConfigurationKeys.SERIALIZE_FOR_RPC, SerializerType.SEATA.name())).getCode(); /** * Configured compressor by user, default is NONE @@ -84,5 +84,5 @@ public interface ProtocolConstants { * @see CompressorType#NONE */ byte CONFIGURED_COMPRESSOR = CompressorType.getByName(ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.COMPRESSOR_FOR_RPC, CompressorType.NONE.name())).getCode(); + .getString(ConfigurationKeys.COMPRESSOR_FOR_RPC, CompressorType.NONE.name())).getCode(); } diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java index 5bf7ef99e7f..ea090308b11 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyBaseConfig.java @@ -52,20 +52,6 @@ public class NettyBaseConfig { * The constant CONFIG. */ protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - /** - * The constant BOSS_THREAD_PREFIX. - */ - protected static final String BOSS_THREAD_PREFIX = CONFIG.getConfig(ConfigurationKeys.BOSS_THREAD_PREFIX); - - /** - * The constant WORKER_THREAD_PREFIX. - */ - protected static final String WORKER_THREAD_PREFIX = CONFIG.getConfig(ConfigurationKeys.WORKER_THREAD_PREFIX); - - /** - * The constant SHARE_BOSS_WORKER. - */ - protected static final boolean SHARE_BOSS_WORKER = CONFIG.getBoolean(ConfigurationKeys.SHARE_BOSS_WORKER); /** * The constant WORKER_THREAD_SIZE. @@ -112,8 +98,8 @@ public class NettyBaseConfig { protected static final int MAX_ALL_IDLE_SECONDS = 0; static { - TRANSPORT_PROTOCOL_TYPE = TransportProtocolType.getType(CONFIG.getConfig(ConfigurationKeys.TRANSPORT_TYPE, TransportProtocolType.TCP.name())); - String workerThreadSize = CONFIG.getConfig(ConfigurationKeys.WORKER_THREAD_SIZE); + TRANSPORT_PROTOCOL_TYPE = TransportProtocolType.getType(CONFIG.getString(ConfigurationKeys.TRANSPORT_TYPE, TransportProtocolType.TCP.name())); + String workerThreadSize = CONFIG.getString(ConfigurationKeys.WORKER_THREAD_SIZE); if (StringUtils.isNotBlank(workerThreadSize) && StringUtils.isNumeric(workerThreadSize)) { WORKER_THREAD_SIZE = Integer.parseInt(workerThreadSize); } else if (WorkThreadMode.getModeByName(workerThreadSize) != null) { @@ -121,7 +107,7 @@ public class NettyBaseConfig { } else { WORKER_THREAD_SIZE = WorkThreadMode.Default.getValue(); } - TRANSPORT_SERVER_TYPE = TransportServerType.getType(CONFIG.getConfig(ConfigurationKeys.TRANSPORT_SERVER, TransportServerType.NIO.name())); + TRANSPORT_SERVER_TYPE = TransportServerType.getType(CONFIG.getString(ConfigurationKeys.TRANSPORT_SERVER, TransportServerType.NIO.name())); switch (TRANSPORT_SERVER_TYPE) { case NIO: if (TRANSPORT_PROTOCOL_TYPE == TransportProtocolType.TCP) { diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java index 96a4a7535c0..5d501e68f92 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientConfig.java @@ -367,7 +367,7 @@ public long getMaxAcquireConnMills() { * @return the string */ public String getClientSelectorThreadPrefix() { - return CONFIG.getConfig(ConfigurationKeys.CLIENT_SELECTOR_THREAD_PREFIX, DEFAULT_SELECTOR_THREAD_PREFIX); + return CONFIG.getString(ConfigurationKeys.CLIENT_SELECTOR_THREAD_PREFIX, DEFAULT_SELECTOR_THREAD_PREFIX); } /** @@ -376,7 +376,7 @@ public String getClientSelectorThreadPrefix() { * @return the string */ public String getClientWorkerThreadPrefix() { - return CONFIG.getConfig(ConfigurationKeys.CLIENT_WORKER_THREAD_PREFIX, DEFAULT_WORKER_THREAD_PREFIX); + return CONFIG.getString(ConfigurationKeys.CLIENT_WORKER_THREAD_PREFIX, DEFAULT_WORKER_THREAD_PREFIX); } /** diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java b/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java index d41e296ee97..ce99c433981 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyServerBootstrap.java @@ -123,7 +123,7 @@ public int getListenPort() { if (listenPort != 0) { return listenPort; } - String strPort = ConfigurationFactory.getInstance().getConfig(SERVER_SERVICE_PORT_CAMEL); + String strPort = ConfigurationFactory.getInstance().getString(SERVER_SERVICE_PORT_CAMEL); int port = 0; try { port = Integer.parseInt(strPort); diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyServerConfig.java b/core/src/main/java/io/seata/core/rpc/netty/NettyServerConfig.java index a326829d059..976ec338670 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyServerConfig.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyServerConfig.java @@ -254,7 +254,7 @@ public static long getRpcRequestTimeout() { * @return the string */ public String getBossThreadPrefix() { - return CONFIG.getConfig(ConfigurationKeys.BOSS_THREAD_PREFIX, DEFAULT_BOSS_THREAD_PREFIX); + return CONFIG.getString(ConfigurationKeys.BOSS_THREAD_PREFIX, DEFAULT_BOSS_THREAD_PREFIX); } /** @@ -263,7 +263,7 @@ public String getBossThreadPrefix() { * @return the string */ public String getWorkerThreadPrefix() { - return CONFIG.getConfig(ConfigurationKeys.WORKER_THREAD_PREFIX, + return CONFIG.getString(ConfigurationKeys.WORKER_THREAD_PREFIX, enableEpoll() ? EPOLL_WORKER_THREAD_PREFIX : DEFAULT_NIO_WORKER_THREAD_PREFIX); } @@ -273,7 +273,7 @@ public String getWorkerThreadPrefix() { * @return the string */ public String getExecutorThreadPrefix() { - return CONFIG.getConfig(ConfigurationKeys.SERVER_EXECUTOR_THREAD_PREFIX, + return CONFIG.getString(ConfigurationKeys.SERVER_EXECUTOR_THREAD_PREFIX, DEFAULT_EXECUTOR_THREAD_PREFIX); } diff --git a/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java b/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java index fcc0aab1c35..6ac0adaf37f 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java +++ b/core/src/main/java/io/seata/core/rpc/netty/RmNettyRemotingClient.java @@ -15,6 +15,14 @@ */ package io.seata.core.rpc.netty; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; + import io.netty.channel.Channel; import io.netty.util.concurrent.EventExecutorGroup; import io.seata.common.DefaultValues; @@ -22,10 +30,9 @@ import io.seata.common.exception.FrameworkException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.model.Resource; import io.seata.core.model.ResourceManager; @@ -42,14 +49,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; - import static io.seata.common.Constants.DBKEYS_SPLIT_CHAR; /** @@ -93,7 +92,7 @@ private RmNettyRemotingClient(NettyClientConfig nettyClientConfig, EventExecutor // set enableClientBatchSendRequest this.enableClientBatchSendRequest = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.ENABLE_RM_CLIENT_BATCH_SEND_REQUEST, ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.ENABLE_CLIENT_BATCH_SEND_REQUEST,DefaultValues.DEFAULT_ENABLE_RM_CLIENT_BATCH_SEND_REQUEST)); - ConfigurationCache.addConfigListener(ConfigurationKeys.ENABLE_RM_CLIENT_BATCH_SEND_REQUEST, new ConfigurationChangeListener() { + ConfigurationFactory.addConfigListener(ConfigurationKeys.ENABLE_RM_CLIENT_BATCH_SEND_REQUEST, new ConfigurationChangeListener() { @Override public void onChangeEvent(ConfigurationChangeEvent event) { String dataId = event.getDataId(); diff --git a/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java b/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java index e2a238b61df..2197faee030 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java +++ b/core/src/main/java/io/seata/core/rpc/netty/TmNettyRemotingClient.java @@ -29,10 +29,9 @@ import io.seata.common.thread.NamedThreadFactory; import io.seata.common.thread.RejectedPolicies; import io.seata.common.util.NetUtil; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.auth.AuthSigner; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.protocol.AbstractMessage; @@ -79,7 +78,7 @@ private TmNettyRemotingClient(NettyClientConfig nettyClientConfig, // set enableClientBatchSendRequest this.enableClientBatchSendRequest = ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.ENABLE_TM_CLIENT_BATCH_SEND_REQUEST, DefaultValues.DEFAULT_ENABLE_TM_CLIENT_BATCH_SEND_REQUEST); - ConfigurationCache.addConfigListener(ConfigurationKeys.ENABLE_TM_CLIENT_BATCH_SEND_REQUEST, new ConfigurationChangeListener() { + ConfigurationFactory.addConfigListener(ConfigurationKeys.ENABLE_TM_CLIENT_BATCH_SEND_REQUEST, new ConfigurationChangeListener() { @Override public void onChangeEvent(ConfigurationChangeEvent event) { String dataId = event.getDataId(); diff --git a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java index fee3c98f0b7..cc2d1871583 100644 --- a/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java +++ b/core/src/main/java/io/seata/core/store/db/AbstractDataSourceProvider.java @@ -24,6 +24,7 @@ import java.util.Objects; import java.util.stream.Stream; import javax.sql.DataSource; + import io.seata.common.exception.StoreException; import io.seata.common.executor.Initialize; import io.seata.common.util.ConfigTools; @@ -40,7 +41,7 @@ /** * The abstract datasource provider - * + * * @author zhangsen * @author will */ @@ -49,6 +50,7 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDataSourceProvider.class); private DataSource dataSource; + private volatile boolean initialized = false; /** * The constant CONFIG. @@ -72,6 +74,12 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, @Override public void init() { this.dataSource = generate(); + this.initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override @@ -91,7 +99,7 @@ public DataSource provide() { * @return the db type */ protected DBType getDBType() { - return DBType.valueof(CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE)); + return DBType.valueof(CONFIG.getString(ConfigurationKeys.STORE_DB_TYPE)); } /** @@ -100,7 +108,7 @@ protected DBType getDBType() { * @return the db driver class name */ protected String getDriverClassName() { - String driverClassName = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME); + String driverClassName = CONFIG.getString(ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME); if (StringUtils.isBlank(driverClassName)) { throw new StoreException( String.format("the {%s} can't be empty", ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME)); @@ -171,7 +179,7 @@ private static Map createMysqlDriverClassLoaders() { * @return the string */ protected String getUrl() { - String url = CONFIG.getConfig(ConfigurationKeys.STORE_DB_URL); + String url = CONFIG.getString(ConfigurationKeys.STORE_DB_URL); if (StringUtils.isBlank(url)) { throw new StoreException(String.format("the {%s} can't be empty", ConfigurationKeys.STORE_DB_URL)); } @@ -184,7 +192,7 @@ protected String getUrl() { * @return the string */ protected String getUser() { - String user = CONFIG.getConfig(ConfigurationKeys.STORE_DB_USER); + String user = CONFIG.getString(ConfigurationKeys.STORE_DB_USER); if (StringUtils.isBlank(user)) { throw new StoreException(String.format("the {%s} can't be empty", ConfigurationKeys.STORE_DB_USER)); } @@ -197,7 +205,7 @@ protected String getUser() { * @return the string */ protected String getPassword() { - String password = CONFIG.getConfig(ConfigurationKeys.STORE_DB_PASSWORD); + String password = CONFIG.getString(ConfigurationKeys.STORE_DB_PASSWORD); String publicKey = getPublicKey(); if (StringUtils.isNotBlank(publicKey)) { try { @@ -251,7 +259,7 @@ protected String getValidationQuery(DBType dbType) { * @return the string */ protected String getPublicKey() { - return CONFIG.getConfig(ConfigurationKeys.STORE_PUBLIC_KEY); + return CONFIG.getString(ConfigurationKeys.STORE_PUBLIC_KEY); } } diff --git a/core/src/main/java/io/seata/core/store/db/sql/lock/AbstractLockStoreSql.java b/core/src/main/java/io/seata/core/store/db/sql/lock/AbstractLockStoreSql.java index 0a2b68e1028..975ccf63d28 100644 --- a/core/src/main/java/io/seata/core/store/db/sql/lock/AbstractLockStoreSql.java +++ b/core/src/main/java/io/seata/core/store/db/sql/lock/AbstractLockStoreSql.java @@ -132,7 +132,7 @@ public String getAllLockSql(String lockTable, String whereCondition) { @Override public String getInsertLockSQL(String lockTable) { - throw new NotSupportYetException("unknown dbType:" + CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE)); + throw new NotSupportYetException("unknown dbType:" + CONFIG.getString(ConfigurationKeys.STORE_DB_TYPE)); } @Override diff --git a/dependencies/pom.xml b/dependencies/pom.xml index aa9adeba88f..1873814bb4f 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -85,6 +85,8 @@ 6.5 0.2.0-RC2 + 3.0.2 + 3.2.0 @@ -352,6 +354,11 @@ apollo-client ${apollo-client.version} + + com.google.code.findbugs + jsr305 + ${jsr305.version} + redis.clients jedis diff --git a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java index c603377dfa7..854276a6659 100644 --- a/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java +++ b/discovery/seata-discovery-consul/src/main/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java @@ -28,24 +28,21 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.ecwid.consul.v1.ConsulClient; import com.ecwid.consul.v1.QueryParams; import com.ecwid.consul.v1.Response; import com.ecwid.consul.v1.agent.model.NewService; import com.ecwid.consul.v1.health.HealthServicesRequest; import com.ecwid.consul.v1.health.model.HealthService; - +import io.seata.common.ConfigurationKeys; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.NetUtil; import io.seata.common.util.StringUtils; -import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationKeys; import io.seata.discovery.registry.RegistryHeartBeats; import io.seata.discovery.registry.RegistryService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author xingfudeshi@gmail.com @@ -56,7 +53,6 @@ public class ConsulRegistryServiceImpl implements RegistryService lookup(String key) throws Exception { if (clusterName == null) { return null; } - String endpointStr = CONFIG.getConfig( - PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST); - if (StringUtils.isNullOrEmpty(endpointStr)) { + + List endpoints = CONFIG.getList(PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST, String.class); + if (CollectionUtils.isEmpty(endpoints)) { throw new IllegalArgumentException(clusterName + POSTFIX_GROUPLIST + " is required"); } - String[] endpoints = endpointStr.split(ENDPOINT_SPLIT_CHAR); + List inetSocketAddresses = new ArrayList<>(); for (String endpoint : endpoints) { String[] ipAndPort = endpoint.split(IP_PORT_SPLIT_CHAR); diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java index dd8aaebabee..7a9123a18ad 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/MultiRegistryFactory.java @@ -48,8 +48,7 @@ public static List getInstances() { private static List buildRegistryServices() { List registryServices = new ArrayList<>(); - String registryTypeNamesStr = - ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig(ConfigurationKeys.FILE_ROOT_REGISTRY + String registryTypeNamesStr = ConfigurationFactory.getInstance().getString(ConfigurationKeys.FILE_ROOT_REGISTRY + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); if (StringUtils.isBlank(registryTypeNamesStr)) { registryTypeNamesStr = RegistryType.File.name(); diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java index 9f8cd2e4f4a..8f88f81e524 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryFactory.java @@ -17,10 +17,10 @@ import java.util.Objects; +import io.seata.common.ConfigurationKeys; import io.seata.common.exception.NotSupportYetException; import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationKeys; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +44,7 @@ public static RegistryService getInstance() { private static RegistryService buildRegistryService() { RegistryType registryType; - String registryTypeName = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig( + String registryTypeName = ConfigurationFactory.getInstance().getString( ConfigurationKeys.FILE_ROOT_REGISTRY + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + ConfigurationKeys.FILE_ROOT_TYPE); LOGGER.info("use registry center type: {}", registryTypeName); diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryHeartBeats.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryHeartBeats.java index 47956c25bf3..5ac6915094a 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryHeartBeats.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryHeartBeats.java @@ -21,12 +21,10 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import io.seata.config.ConfigurationFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.seata.config.Configuration; -import io.seata.config.ConfigurationFactory; - /** * @author xizhou * @since 2021/6/13 5:09 pm @@ -34,7 +32,6 @@ public class RegistryHeartBeats { private static final Logger LOGGER = LoggerFactory.getLogger(RegistryHeartBeats.class); - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; private static final String FILE_CONFIG_SPLIT_CHAR = "."; private static final String FILE_ROOT_REGISTRY = "registry"; private static final String HEARTBEAT_KEY = "heartbeat"; @@ -81,15 +78,15 @@ public static void close() { private static long getHeartbeatPeriod(String registryType) { String propertySuffix = String.join("-", HEARTBEAT_KEY, HEARTBEAT_PERIOD_KEY); - // FILE_CONFIG.getLong("registry.${registryType}.heartbeat-period"); - return FILE_CONFIG.getLong(String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, registryType, propertySuffix), + // ConfigurationFactory.getInstance().getLong("registry.${registryType}.heartbeat-period"); + return ConfigurationFactory.getInstance().getLong(String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, registryType, propertySuffix), DEFAULT_HEARTBEAT_PERIOD); } private static boolean getHeartbeatEnabled(String registryType) { String propertySuffix = String.join("-", HEARTBEAT_KEY, HEARTBEAT_ENABLED_KEY); - // FILE_CONFIG.getBoolean("registry.${registryType}.heartbeat-enabled"); - return FILE_CONFIG.getBoolean(String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, registryType, propertySuffix), + // ConfigurationFactory.getInstance().getBoolean("registry.${registryType}.heartbeat-enabled"); + return ConfigurationFactory.getInstance().getBoolean(String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, registryType, propertySuffix), DEFAULT_HEARTBEAT_ENABLED); } diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java index 4391bd86738..7cfe12763ce 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/RegistryService.java @@ -22,7 +22,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import io.seata.config.ConfigurationCache; + import io.seata.config.ConfigurationFactory; /** @@ -51,7 +51,8 @@ public interface RegistryService { /** * Service node health check */ - Map> CURRENT_ADDRESS_MAP = new ConcurrentHashMap<>(); + Map> CURRENT_ADDRESS_MAP = new ConcurrentHashMap<>(); + /** * Register. * @@ -97,6 +98,7 @@ public interface RegistryService { /** * Close. + * * @throws Exception the exception */ void close() throws Exception; @@ -110,10 +112,9 @@ public interface RegistryService { default String getServiceGroup(String key) { key = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key; if (!SERVICE_GROUP_NAME.contains(key)) { - ConfigurationCache.addConfigListener(key); SERVICE_GROUP_NAME.add(key); } - return ConfigurationFactory.getInstance().getConfig(key); + return ConfigurationFactory.getInstance().getString(key); } default List aliveLookup(String transactionServiceGroup) { @@ -121,7 +122,7 @@ default List aliveLookup(String transactionServiceGroup) { } default List refreshAliveLookup(String transactionServiceGroup, - List aliveAddress) { + List aliveAddress) { return CURRENT_ADDRESS_MAP.put(transactionServiceGroup, aliveAddress); } diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java index 7b45ac9fac0..12570e8dd57 100644 --- a/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java +++ b/discovery/seata-discovery-core/src/test/java/io/seata/config/ConfigurationFactoryTest.java @@ -36,7 +36,7 @@ void getInstance() { @Test void getLoadBalance() { Configuration configuration = ConfigurationFactory.getInstance(); - String loadBalanceType = configuration.getConfig(LoadBalanceFactory.LOAD_BALANCE_TYPE); + String loadBalanceType = configuration.getString(LoadBalanceFactory.LOAD_BALANCE_TYPE); int virtualNode = configuration.getInt(ConsistentHashLoadBalance.LOAD_BALANCE_CONSISTENT_HASH_VIRTUAL_NODES); Assertions.assertEquals("XID", loadBalanceType); Assertions.assertEquals(10,virtualNode); diff --git a/discovery/seata-discovery-custom/src/main/java/io/seata/discovery/registry/custom/CustomRegistryProvider.java b/discovery/seata-discovery-custom/src/main/java/io/seata/discovery/registry/custom/CustomRegistryProvider.java index 8b740b7aadb..3f7d4c72241 100644 --- a/discovery/seata-discovery-custom/src/main/java/io/seata/discovery/registry/custom/CustomRegistryProvider.java +++ b/discovery/seata-discovery-custom/src/main/java/io/seata/discovery/registry/custom/CustomRegistryProvider.java @@ -15,6 +15,8 @@ */ package io.seata.discovery.registry.custom; +import java.util.stream.Stream; + import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.loader.LoadLevel; import io.seata.common.util.StringUtils; @@ -23,8 +25,6 @@ import io.seata.discovery.registry.RegistryService; import io.seata.discovery.registry.RegistryType; -import java.util.stream.Stream; - /** * @author ggndnn */ @@ -35,7 +35,7 @@ public class CustomRegistryProvider implements RegistryProvider { private final String customName; public CustomRegistryProvider() { - String name = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig(FILE_CONFIG_KEY_PREFIX); + String name = ConfigurationFactory.getInstance().getString(FILE_CONFIG_KEY_PREFIX); if (StringUtils.isBlank(name)) { throw new IllegalArgumentException("name value of custom registry type must not be blank"); } diff --git a/discovery/seata-discovery-custom/src/test/java/io/seata/discovery/registry/custom/CustomRegistryServiceForTest.java b/discovery/seata-discovery-custom/src/test/java/io/seata/discovery/registry/custom/CustomRegistryServiceForTest.java index 804ef1fd513..7683bb41610 100644 --- a/discovery/seata-discovery-custom/src/test/java/io/seata/discovery/registry/custom/CustomRegistryServiceForTest.java +++ b/discovery/seata-discovery-custom/src/test/java/io/seata/discovery/registry/custom/CustomRegistryServiceForTest.java @@ -15,12 +15,12 @@ */ package io.seata.discovery.registry.custom; -import io.seata.config.ConfigChangeListener; -import io.seata.discovery.registry.RegistryService; - import java.net.InetSocketAddress; import java.util.List; +import io.seata.config.changelistener.ConfigChangeListener; +import io.seata.discovery.registry.RegistryService; + public class CustomRegistryServiceForTest implements RegistryService { @Override public void register(InetSocketAddress address) throws Exception { diff --git a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java index 94965c75235..edf9d225c85 100644 --- a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java +++ b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java @@ -15,6 +15,21 @@ */ package io.seata.discovery.registry.etcd3; +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import io.etcd.jetcd.ByteSequence; import io.etcd.jetcd.Client; @@ -35,26 +50,9 @@ import io.seata.config.ConfigurationFactory; import io.seata.discovery.registry.RegistryHeartBeats; import io.seata.discovery.registry.RegistryService; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.InetSocketAddress; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - import static io.netty.util.CharsetUtil.UTF_8; /** @@ -63,7 +61,8 @@ public class EtcdRegistryServiceImpl implements RegistryService { private static final Logger LOGGER = LoggerFactory.getLogger(EtcdRegistryServiceImpl.class); - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); + private static final String FILE_ROOT_REGISTRY = "registry"; private static final String FILE_CONFIG_SPLIT_CHAR = "."; private static final String REGISTRY_TYPE = "etcd3"; @@ -265,7 +264,7 @@ private Client getClient() { if (StringUtils.isNotBlank(testEndpoint)) { client = Client.builder().endpoints(testEndpoint).build(); } else { - client = Client.builder().endpoints(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)).build(); + client = Client.builder().endpoints(CONFIG.getString(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY)).build(); } } } @@ -280,7 +279,7 @@ private Client getClient() { */ private String getClusterName() { String clusterConfigName = String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, REGISTRY_TYPE, REGISTRY_CLUSTER); - return FILE_CONFIG.getConfig(clusterConfigName, DEFAULT_CLUSTER_NAME); + return CONFIG.getString(clusterConfigName, DEFAULT_CLUSTER_NAME); } /** diff --git a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java index 3217ec6e526..0f683b3992d 100644 --- a/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java +++ b/discovery/seata-discovery-eureka/src/main/java/io/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java @@ -15,6 +15,14 @@ */ package io.seata.discovery.registry.eureka; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider; @@ -34,14 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; - /** * The type Eureka registry service. * @@ -64,7 +64,7 @@ public class EurekaRegistryServiceImpl implements RegistryService> LISTENER_SERVICE_MAP = new ConcurrentHashMap<>(); private static final ConcurrentMap> CLUSTER_ADDRESS_MAP = new ConcurrentHashMap<>(); private static final ConcurrentMap CLUSTER_LOCK = new ConcurrentHashMap<>(); @@ -173,13 +173,13 @@ private Properties getEurekaProperties(boolean needRegister) { Properties eurekaProperties = new Properties(); eurekaProperties.setProperty(EUREKA_CONFIG_REFRESH_KEY, String.valueOf(EUREKA_REFRESH_INTERVAL)); - String url = FILE_CONFIG.getConfig(getEurekaServerUrlFileKey()); + String url = CONFIG.getString(getEurekaServerUrlFileKey()); if (StringUtils.isBlank(url)) { throw new EurekaRegistryException("eureka server url can not be null!"); } eurekaProperties.setProperty(EUREKA_CONFIG_SERVER_URL_KEY, url); - String weight = FILE_CONFIG.getConfig(getEurekaInstanceWeightFileKey()); + String weight = CONFIG.getString(getEurekaInstanceWeightFileKey()); if (StringUtils.isNotBlank(weight)) { eurekaProperties.setProperty(EUREKA_CONFIG_METADATA_WEIGHT, weight); } else { @@ -194,7 +194,7 @@ private Properties getEurekaProperties(boolean needRegister) { } private String getApplicationName() { - String application = FILE_CONFIG.getConfig(getEurekaApplicationFileKey()); + String application = CONFIG.getString(getEurekaApplicationFileKey()); if (application == null) { application = DEFAULT_APPLICATION; } diff --git a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java index 96ea5046973..799592ab625 100644 --- a/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java +++ b/discovery/seata-discovery-nacos/src/main/java/io/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java @@ -32,12 +32,12 @@ import com.alibaba.nacos.api.naming.listener.NamingEvent; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.Service; +import io.seata.common.ConfigurationKeys; import io.seata.common.util.CollectionUtils; import io.seata.common.util.NetUtil; import io.seata.common.util.StringUtils; import io.seata.config.Configuration; import io.seata.config.ConfigurationFactory; -import io.seata.config.ConfigurationKeys; import io.seata.discovery.registry.RegistryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +72,7 @@ public class NacosRegistryServiceImpl implements RegistryService private static final String PUBLIC_NAMING_ADDRESS_PREFIX = "public_"; private static final String PUBLIC_NAMING_SERVICE_META_IP_KEY = "publicIp"; private static final String PUBLIC_NAMING_SERVICE_META_PORT_KEY = "publicPort"; - private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE; + private static final Configuration CONFIG = ConfigurationFactory.getInstance(); private static volatile NamingService naming; private static final ConcurrentMap> LISTENER_SERVICE_MAP = new ConcurrentHashMap<>(); private static final ConcurrentMap> CLUSTER_ADDRESS_MAP = new ConcurrentHashMap<>(); @@ -83,7 +83,7 @@ public class NacosRegistryServiceImpl implements RegistryService private static volatile Boolean useSLBWay; private NacosRegistryServiceImpl() { - String configForNacosSLB = FILE_CONFIG.getConfig(getNacosUrlPatternOfSLB()); + String configForNacosSLB = CONFIG.getString(getNacosUrlPatternOfSLB()); Pattern patternOfNacosRegistryForSLB = StringUtils.isBlank(configForNacosSLB) ? DEFAULT_SLB_REGISTRY_PATTERN : Pattern.compile(configForNacosSLB); @@ -237,7 +237,7 @@ private static Properties getNamingProperties() { if (System.getProperty(PRO_SERVER_ADDR_KEY) != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, System.getProperty(PRO_SERVER_ADDR_KEY)); } else { - String address = FILE_CONFIG.getConfig(getNacosAddrFileKey()); + String address = CONFIG.getString(getNacosAddrFileKey()); if (address != null) { properties.setProperty(PRO_SERVER_ADDR_KEY, address); } @@ -245,23 +245,23 @@ private static Properties getNamingProperties() { if (System.getProperty(PRO_NAMESPACE_KEY) != null) { properties.setProperty(PRO_NAMESPACE_KEY, System.getProperty(PRO_NAMESPACE_KEY)); } else { - String namespace = FILE_CONFIG.getConfig(getNacosNameSpaceFileKey()); + String namespace = CONFIG.getString(getNacosNameSpaceFileKey()); if (namespace == null) { namespace = DEFAULT_NAMESPACE; } properties.setProperty(PRO_NAMESPACE_KEY, namespace); } - String userName = StringUtils.isNotBlank(System.getProperty(USER_NAME)) ? System.getProperty(USER_NAME) : FILE_CONFIG.getConfig(getNacosUserName()); + String userName = StringUtils.isNotBlank(System.getProperty(USER_NAME)) ? System.getProperty(USER_NAME) : CONFIG.getString(getNacosUserName()); if (StringUtils.isNotBlank(userName)) { - String password = StringUtils.isNotBlank(System.getProperty(PASSWORD)) ? System.getProperty(PASSWORD) : FILE_CONFIG.getConfig(getNacosPassword()); + String password = StringUtils.isNotBlank(System.getProperty(PASSWORD)) ? System.getProperty(PASSWORD) : CONFIG.getString(getNacosPassword()); if (StringUtils.isNotBlank(password)) { properties.setProperty(USER_NAME, userName); properties.setProperty(PASSWORD, password); } } else { - String accessKey = StringUtils.isNotBlank(System.getProperty(ACCESS_KEY)) ? System.getProperty(ACCESS_KEY) : FILE_CONFIG.getConfig(getNacosAccessKey()); + String accessKey = StringUtils.isNotBlank(System.getProperty(ACCESS_KEY)) ? System.getProperty(ACCESS_KEY) : CONFIG.getString(getNacosAccessKey()); if (StringUtils.isNotBlank(accessKey)) { - String secretKey = StringUtils.isNotBlank(System.getProperty(SECRET_KEY)) ? System.getProperty(SECRET_KEY) : FILE_CONFIG.getConfig(getNacosSecretKey()); + String secretKey = StringUtils.isNotBlank(System.getProperty(SECRET_KEY)) ? System.getProperty(SECRET_KEY) : CONFIG.getString(getNacosSecretKey()); if (StringUtils.isNotBlank(secretKey)) { properties.put(ACCESS_KEY, accessKey); properties.put(SECRET_KEY, secretKey); @@ -269,7 +269,7 @@ private static Properties getNamingProperties() { } } } - String contextPath = StringUtils.isNotBlank(System.getProperty(CONTEXT_PATH)) ? System.getProperty(CONTEXT_PATH) : FILE_CONFIG.getConfig(getNacosContextPathKey()); + String contextPath = StringUtils.isNotBlank(System.getProperty(CONTEXT_PATH)) ? System.getProperty(CONTEXT_PATH) : CONFIG.getString(getNacosContextPathKey()); if (StringUtils.isNotBlank(contextPath)) { properties.setProperty(CONTEXT_PATH, contextPath); } @@ -277,15 +277,15 @@ private static Properties getNamingProperties() { } private static String getClusterName() { - return FILE_CONFIG.getConfig(getNacosClusterFileKey(), DEFAULT_CLUSTER); + return CONFIG.getString(getNacosClusterFileKey(), DEFAULT_CLUSTER); } private static String getServiceName() { - return FILE_CONFIG.getConfig(getNacosApplicationFileKey(), DEFAULT_APPLICATION); + return CONFIG.getString(getNacosApplicationFileKey(), DEFAULT_APPLICATION); } private static String getServiceGroup() { - return FILE_CONFIG.getConfig(getNacosApplicationGroupKey(), DEFAULT_GROUP); + return CONFIG.getString(getNacosApplicationGroupKey(), DEFAULT_GROUP); } private static String getNacosAddrFileKey() { diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 6d2418e7d14..768932b79d5 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -79,10 +79,10 @@ public class RedisRegistryServiceImpl implements RegistryService new NamedThreadFactory("RedisRegistryService-updateClusterAddrMap", 1)); private RedisRegistryServiceImpl() { - Configuration seataConfig = ConfigurationFactory.CURRENT_FILE_INSTANCE; - this.clusterName = seataConfig.getConfig(REDIS_FILEKEY_PREFIX + REGISTRY_CLUSTER_KEY, DEFAULT_CLUSTER); - String password = seataConfig.getConfig(getRedisPasswordFileKey()); - String serverAddr = seataConfig.getConfig(getRedisAddrFileKey()); + Configuration seataConfig = ConfigurationFactory.getInstance(); + this.clusterName = seataConfig.getString(REDIS_FILEKEY_PREFIX + REGISTRY_CLUSTER_KEY, DEFAULT_CLUSTER); + String password = seataConfig.getString(getRedisPasswordFileKey()); + String serverAddr = seataConfig.getString(getRedisAddrFileKey()); String[] serverArr = serverAddr.split(":"); String host = serverArr[0]; int port = Integer.parseInt(serverArr[1]); diff --git a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java index ed095fc1348..7155c8fc45e 100644 --- a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java +++ b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java @@ -40,8 +40,8 @@ import io.seata.discovery.registry.RegistryService; import org.apache.commons.lang.StringUtils; -import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; -import static io.seata.config.ConfigurationKeys.FILE_ROOT_REGISTRY; +import static io.seata.common.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR; +import static io.seata.common.ConfigurationKeys.FILE_ROOT_REGISTRY; /** * The type SOFARegistry registry service. @@ -67,7 +67,7 @@ public class SofaRegistryServiceImpl implements RegistryService instances private String getClusterName() { String clusterConfigName = String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, REGISTRY_TYPE, REGISTRY_CLUSTER); - return FILE_CONFIG.getConfig(clusterConfigName); + return CONFIG.getString(clusterConfigName); } private String getRegisterPathByPath(InetSocketAddress address) { diff --git a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterFactory.java b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterFactory.java index c873c0badb6..adb661c4c52 100644 --- a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterFactory.java +++ b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/exporter/ExporterFactory.java @@ -16,11 +16,11 @@ package io.seata.metrics.exporter; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; import io.seata.common.loader.EnhancedServiceLoader; -import io.seata.common.util.StringUtils; import io.seata.config.ConfigurationFactory; import io.seata.core.constants.ConfigurationKeys; import org.slf4j.Logger; @@ -38,21 +38,23 @@ public class ExporterFactory { public static List getInstanceList() { List exporters = new ArrayList<>(); - String exporterTypeNameList = ConfigurationFactory.getInstance().getConfig( - ConfigurationKeys.METRICS_PREFIX + ConfigurationKeys.METRICS_EXPORTER_LIST, DEFAULT_METRICS_EXPORTER_LIST); - if (!StringUtils.isNullOrEmpty(exporterTypeNameList)) { - String[] exporterTypeNames = exporterTypeNameList.split(","); - for (String exporterTypeName : exporterTypeNames) { + + List exporterTypeNameList = ConfigurationFactory.getInstance().getList( + ConfigurationKeys.METRICS_PREFIX + ConfigurationKeys.METRICS_EXPORTER_LIST + , Arrays.asList(DEFAULT_METRICS_EXPORTER_LIST)); + if (exporterTypeNameList != null) { + for (String exporterTypeName : exporterTypeNameList) { ExporterType exporterType; try { exporterType = ExporterType.getType(exporterTypeName); exporters.add( EnhancedServiceLoader.load(Exporter.class, Objects.requireNonNull(exporterType).getName())); } catch (Exception exx) { - LOGGER.error("not support metrics exporter type: {}",exporterTypeName, exx); + LOGGER.error("not support metrics exporter type: {}", exporterTypeName, exx); } } } + return exporters; } } diff --git a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryFactory.java b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryFactory.java index 500428c04e1..1064f577b69 100644 --- a/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryFactory.java +++ b/metrics/seata-metrics-core/src/main/java/io/seata/metrics/registry/RegistryFactory.java @@ -33,7 +33,7 @@ public class RegistryFactory { public static Registry getInstance() { RegistryType registryType; - String registryTypeName = ConfigurationFactory.getInstance().getConfig( + String registryTypeName = ConfigurationFactory.getInstance().getString( ConfigurationKeys.METRICS_PREFIX + ConfigurationKeys.METRICS_REGISTRY_TYPE, DEFAULT_METRICS_REGISTRY_TYPE); if (!StringUtils.isNullOrEmpty(registryTypeName)) { try { diff --git a/pom.xml b/pom.xml index c60930ccad5..008a278b657 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,11 @@ slf4j-simple test + + com.google.code.findbugs + jsr305 + provided + diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/LockRetryController.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/LockRetryController.java index 14d757ead4f..8df61eae425 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/LockRetryController.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/LockRetryController.java @@ -18,10 +18,9 @@ import io.seata.common.DefaultValues; import io.seata.common.util.NumberUtils; import io.seata.config.Configuration; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.GlobalLockConfigHolder; import io.seata.core.exception.TransactionExceptionCode; @@ -37,8 +36,8 @@ public class LockRetryController { private static final GlobalConfig LISTENER = new GlobalConfig(); static { - ConfigurationCache.addConfigListener(ConfigurationKeys.CLIENT_LOCK_RETRY_INTERVAL, LISTENER); - ConfigurationCache.addConfigListener(ConfigurationKeys.CLIENT_LOCK_RETRY_TIMES, LISTENER); + ConfigurationFactory.addConfigListener(ConfigurationKeys.CLIENT_LOCK_RETRY_INTERVAL, LISTENER); + ConfigurationFactory.addConfigListener(ConfigurationKeys.CLIENT_LOCK_RETRY_TIMES, LISTENER); } private int lockRetryInterval; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLVisitorFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLVisitorFactory.java index f1bf7963152..b57af123d3c 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLVisitorFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLVisitorFactory.java @@ -34,7 +34,7 @@ public class SQLVisitorFactory { private final static SQLRecognizerFactory SQL_RECOGNIZER_FACTORY; static { - String sqlParserType = ConfigurationFactory.getInstance().getConfig(ConfigurationKeys.SQL_PARSER_TYPE, SqlParserType.SQL_PARSER_TYPE_DRUID); + String sqlParserType = ConfigurationFactory.getInstance().getString(ConfigurationKeys.SQL_PARSER_TYPE, SqlParserType.SQL_PARSER_TYPE_DRUID); SQL_RECOGNIZER_FACTORY = EnhancedServiceLoader.load(SQLRecognizerFactory.class, sqlParserType); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java index e6ae3232075..4676a197486 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java @@ -80,7 +80,7 @@ public int getValue() { } } - protected static final String UNDO_LOG_TABLE_NAME = ConfigurationFactory.getInstance().getConfig( + protected static final String UNDO_LOG_TABLE_NAME = ConfigurationFactory.getInstance().getString( ConfigurationKeys.TRANSACTION_UNDO_LOG_TABLE, DEFAULT_TRANSACTION_UNDO_LOG_TABLE); private static final String CHECK_UNDO_LOG_TABLE_EXIST_SQL = "SELECT 1 FROM " + UNDO_LOG_TABLE_NAME + " LIMIT 1"; @@ -95,10 +95,10 @@ public int getValue() { protected static final boolean ROLLBACK_INFO_COMPRESS_ENABLE = ConfigurationFactory.getInstance().getBoolean( ConfigurationKeys.CLIENT_UNDO_COMPRESS_ENABLE, DEFAULT_CLIENT_UNDO_COMPRESS_ENABLE); - protected static final CompressorType ROLLBACK_INFO_COMPRESS_TYPE = CompressorType.getByName(ConfigurationFactory.getInstance().getConfig( + protected static final CompressorType ROLLBACK_INFO_COMPRESS_TYPE = CompressorType.getByName(ConfigurationFactory.getInstance().getString( ConfigurationKeys.CLIENT_UNDO_COMPRESS_TYPE, DEFAULT_CLIENT_UNDO_COMPRESS_TYPE)); - protected static final long ROLLBACK_INFO_COMPRESS_THRESHOLD = SizeUtil.size2Long(ConfigurationFactory.getInstance().getConfig( + protected static final long ROLLBACK_INFO_COMPRESS_THRESHOLD = SizeUtil.size2Long(ConfigurationFactory.getInstance().getString( ConfigurationKeys.CLIENT_UNDO_COMPRESS_THRESHOLD, DEFAULT_CLIENT_UNDO_COMPRESS_THRESHOLD)); private static final ThreadLocal SERIALIZER_LOCAL = new ThreadLocal<>(); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogConstants.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogConstants.java index 6e30c7fd19a..7653478a57b 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogConstants.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/UndoLogConstants.java @@ -28,7 +28,7 @@ public interface UndoLogConstants { String SERIALIZER_KEY = "serializer"; String DEFAULT_SERIALIZER = ConfigurationFactory.getInstance() - .getConfig(ConfigurationKeys.TRANSACTION_UNDO_LOG_SERIALIZATION, DEFAULT_TRANSACTION_UNDO_LOG_SERIALIZATION); + .getString(ConfigurationKeys.TRANSACTION_UNDO_LOG_SERIALIZATION, DEFAULT_TRANSACTION_UNDO_LOG_SERIALIZATION); String COMPRESSOR_TYPE_KEY = "compressorType"; } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java index e97387a99dd..0f7559875af 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java @@ -20,13 +20,13 @@ import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.util.CollectionUtils; -import io.seata.sqlparser.util.ColumnUtils; import io.seata.rm.datasource.SqlGenerateUtils; import io.seata.rm.datasource.sql.struct.Field; import io.seata.rm.datasource.sql.struct.Row; import io.seata.rm.datasource.sql.struct.TableRecords; import io.seata.rm.datasource.undo.AbstractUndoExecutor; import io.seata.rm.datasource.undo.SQLUndoLog; +import io.seata.sqlparser.util.ColumnUtils; import io.seata.sqlparser.util.JdbcConstants; /** diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FastjsonUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FastjsonUndoLogParser.java index a542d1e5315..5ebe0235f53 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FastjsonUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FastjsonUndoLogParser.java @@ -35,10 +35,17 @@ public class FastjsonUndoLogParser implements UndoLogParser, Initialize { public static final String NAME = "fastjson"; private final SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); + private volatile boolean initialized = false; @Override public void init() { filter.getExcludes().add("tableMeta"); + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java index 0231db22100..a35f6de80b6 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java @@ -41,6 +41,7 @@ public class FstUndoLogParser implements UndoLogParser, Initialize { public static final String NAME = "fst"; private FstSerializerFactory fstFactory = FstSerializerFactory.getDefaultFactory(); + private volatile boolean initialized = false; @Override public void init() { @@ -62,6 +63,12 @@ public void init() { } catch (EnhancedServiceNotFoundException e) { LOGGER.warn("FstSerializer not found children class.", e); } + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java index 45e4eaa1950..3e38d47b439 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java @@ -119,6 +119,7 @@ public class JacksonUndoLogParser implements UndoLogParser, Initialize { * customize deserializer of java.time.LocalDateTime */ private final JsonDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(); + private volatile boolean initialized = false; @Override public void init() { @@ -156,6 +157,13 @@ public void init() { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); mapper.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER); + + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java index 2ab834eef8d..bee77f3eae4 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java @@ -40,6 +40,10 @@ public class KryoUndoLogParser implements UndoLogParser, Initialize { public static final String NAME = "kryo"; + + private volatile boolean initialized = false; + + @Override public void init() { try { @@ -59,6 +63,13 @@ public void init() { } catch (EnhancedServiceNotFoundException e) { LOGGER.warn("KryoTypeSerializer not found children class.", e); } + + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java index 6df392f6711..ce71a4ee070 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java @@ -58,6 +58,9 @@ public class ProtostuffUndoLogParser implements UndoLogParser, Initialize { private final Schema schema = RuntimeSchema.getSchema(BranchUndoLog.class, idStrategy); + private volatile boolean initialized = false; + + @Override public void init() { try { @@ -76,6 +79,13 @@ public void init() { idStrategy.registerDelegate(new TimestampDelegate()); idStrategy.registerDelegate(new SqlDateDelegate()); idStrategy.registerDelegate(new TimeDelegate()); + + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java index e7d59e863dc..664c7cdfecf 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/xa/ResourceManagerXA.java @@ -59,6 +59,11 @@ public void init() { LOGGER.info("ResourceManagerXA init ..."); } + @Override + public boolean isInitialized() { + return true; + } + public void initXaTwoPhaseTimeoutChecker() { if (xaTwoPhaseTimeoutChecker == null) { synchronized (this) { diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/LockRetryControllerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/LockRetryControllerTest.java index 200033f0f6d..7ff76b6494e 100644 --- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/LockRetryControllerTest.java +++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/LockRetryControllerTest.java @@ -16,7 +16,8 @@ package io.seata.rm.datasource.exec; import io.seata.common.DefaultValues; -import io.seata.config.ConfigurationChangeEvent; +import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.GlobalLockConfigHolder; import io.seata.core.model.GlobalLockConfig; @@ -76,7 +77,7 @@ void testNoCustomizedConfig() { @Test void testLockConfigListener() { LockRetryController.GlobalConfig config = new LockRetryController.GlobalConfig(); - ConfigurationChangeEvent event = new ConfigurationChangeEvent(); + ConfigurationChangeEvent event = new ConfigurationChangeEvent(ConfigurationFactory.getInstance().getMainSource()); event.setDataId(ConfigurationKeys.CLIENT_LOCK_RETRY_INTERVAL); int retryInterval = 100; diff --git a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java index 7a7a476e922..dc45ece57ae 100644 --- a/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java +++ b/saga/seata-saga-engine-store/src/main/java/io/seata/saga/engine/config/DbStateMachineConfig.java @@ -67,11 +67,11 @@ public DbStateMachineConfig() { if (configuration != null) { this.rmReportSuccessEnable = configuration.getBoolean(ConfigurationKeys.CLIENT_REPORT_SUCCESS_ENABLE, DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE); this.sagaBranchRegisterEnable = configuration.getBoolean(ConfigurationKeys.CLIENT_SAGA_BRANCH_REGISTER_ENABLE, DEFAULT_CLIENT_SAGA_BRANCH_REGISTER_ENABLE); - setSagaJsonParser(configuration.getConfig(ConfigurationKeys.CLIENT_SAGA_JSON_PARSER, DEFAULT_SAGA_JSON_PARSER)); - this.applicationId = configuration.getConfig(ConfigurationKeys.APPLICATION_ID); - this.txServiceGroup = configuration.getConfig(ConfigurationKeys.TX_SERVICE_GROUP); - this.accessKey = configuration.getConfig(ConfigurationKeys.ACCESS_KEY,null); - this.secretKey = configuration.getConfig(ConfigurationKeys.SECRET_KEY,null); + setSagaJsonParser(configuration.getString(ConfigurationKeys.CLIENT_SAGA_JSON_PARSER, DEFAULT_SAGA_JSON_PARSER)); + this.applicationId = configuration.getString(ConfigurationKeys.APPLICATION_ID); + this.txServiceGroup = configuration.getString(ConfigurationKeys.TX_SERVICE_GROUP); + this.accessKey = configuration.getString(ConfigurationKeys.ACCESS_KEY,null); + this.secretKey = configuration.getString(ConfigurationKeys.SECRET_KEY,null); setSagaRetryPersistModeUpdate(configuration.getBoolean(ConfigurationKeys.CLIENT_SAGA_RETRY_PERSIST_MODE_UPDATE, DEFAULT_CLIENT_SAGA_RETRY_PERSIST_MODE_UPDATE)); setSagaCompensatePersistModeUpdate(configuration.getBoolean(ConfigurationKeys.CLIENT_SAGA_COMPENSATE_PERSIST_MODE_UPDATE, diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java index a427af72ae9..065672716e2 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/io/seata/spring/boot/autoconfigure/properties/client/LoadBalancePropertiesTest.java @@ -15,10 +15,8 @@ */ package io.seata.spring.boot.autoconfigure.properties.client; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.config.springcloud.SpringApplicationContextProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -30,7 +28,6 @@ import static io.seata.spring.boot.autoconfigure.StarterConstants.LOAD_BALANCE_PREFIX; import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author xingfudeshi@gmail.com @@ -54,13 +51,11 @@ LoadBalanceProperties loadBalanceProperties() { @Test public void testLoadBalanceProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = - EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); System.setProperty("seata.client.loadBalance.virtualNodes", "30"); assertEquals(30, currentConfiguration.getInt("client.loadBalance.virtualNodes")); System.setProperty("seata.client.loadBalance.type", "test"); - assertEquals("test", currentConfiguration.getConfig("client.loadBalance.type")); + assertEquals("test", currentConfiguration.getString("client.loadBalance.type")); } @AfterAll diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/PropertyObjectDefaultValueConfigurationProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/PropertyObjectDefaultValueConfigurationProcessor.java new file mode 100644 index 00000000000..cb8aa5c1804 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/PropertyObjectDefaultValueConfigurationProcessor.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.spring.boot.autoconfigure.config.processor; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.spring.boot.autoconfigure.config.source.PropertyObjectDefaultValueConfigSource; + +import static io.seata.config.processor.ConfigProcessorOrdered.PROPERTY_OBJECT_DEFAULT_VALUE_PROCESSOR_ORDER; + +/** + * The type Property object default config source provider. + * + * @author wang.liang + */ +@LoadLevel(name = "property-object-default-value-processor", order = PROPERTY_OBJECT_DEFAULT_VALUE_PROCESSOR_ORDER) +public class PropertyObjectDefaultValueConfigurationProcessor implements ConfigurationProcessor { + + @Override + public void process(Configuration configuration) { + configuration.addSource(new PropertyObjectDefaultValueConfigSource()); + } +} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/SpringEnvironmentConfigurationProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/SpringEnvironmentConfigurationProcessor.java new file mode 100644 index 00000000000..dfac706ad3b --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/processor/SpringEnvironmentConfigurationProcessor.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.spring.boot.autoconfigure.config.processor; + +import io.seata.common.loader.LoadLevel; +import io.seata.config.Configuration; +import io.seata.config.processor.ConfigurationProcessor; +import io.seata.spring.boot.autoconfigure.config.source.SpringEnvironmentConfigSource; + +import static io.seata.config.processor.ConfigProcessorOrdered.SPRING_ENVIRONMENT_PROCESSOR_ORDER; + +/** + * The type SpringEnvironmentConfigurationProcessor. + * + * @author wang.liang + */ +@LoadLevel(name = "spring-environment-processor", order = SPRING_ENVIRONMENT_PROCESSOR_ORDER) +public class SpringEnvironmentConfigurationProcessor implements ConfigurationProcessor { + + @Override + public void process(Configuration configuration) { + configuration.addSource(new SpringEnvironmentConfigSource()); + } +} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/PropertyObjectDefaultValueConfigSource.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/PropertyObjectDefaultValueConfigSource.java new file mode 100644 index 00000000000..e711c373fb1 --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/PropertyObjectDefaultValueConfigSource.java @@ -0,0 +1,189 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.spring.boot.autoconfigure.config.source; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Stream; +import javax.annotation.Nonnull; + +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.util.CollectionUtils; +import io.seata.common.util.StringFormatUtils; +import io.seata.config.source.ConfigSource; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.Nullable; + +import static io.seata.config.source.ConfigSourceOrdered.PROPERTY_OBJECT_DEFAULT_VALUE_CONFIG_SOURCE_ORDER; +import static io.seata.config.util.ConfigurationUtils.CONFIG_FILE_NAME_SYSTEM_ENV_KEY; +import static io.seata.config.util.ConfigurationUtils.CONFIG_FILE_NAME_SYSTEM_PROPERTY_KEY; +import static io.seata.config.util.ConfigurationUtils.CONFIG_TYPE_SYSTEM_ENV_KEY; +import static io.seata.config.util.ConfigurationUtils.CONFIG_TYPE_SYSTEM_PROPERTY_KEY; +import static io.seata.config.util.ConfigurationUtils.ENV_KEY1; +import static io.seata.config.util.ConfigurationUtils.ENV_KEY2; +import static io.seata.config.util.ConfigurationUtils.ENV_SYSTEM_ENV_KEY; +import static io.seata.config.util.ConfigurationUtils.ENV_SYSTEM_PROPERTY_KEY; +import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_GROUPLIST; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_VGROUP_MAPPING; + +/** + * The type Property object default value ConfigSource. + * + * @author wang.liang + */ +public class PropertyObjectDefaultValueConfigSource implements ConfigSource { + + private static final Logger LOGGER = LoggerFactory.getLogger(PropertyObjectDefaultValueConfigSource.class); + + private static final String DOT = String.valueOf(StringFormatUtils.DOT); + + private static final Map PROPERTY_BEAN_INSTANCE_MAP = new ConcurrentHashMap<>(64); + + // The excludes dataIds will print the debug log when throw exception, not error log. + private static final Set EXCLUDES = new HashSet<>(Arrays.asList( + // configFileName keys + CONFIG_FILE_NAME_SYSTEM_PROPERTY_KEY, CONFIG_FILE_NAME_SYSTEM_ENV_KEY, + // env keys + ENV_SYSTEM_PROPERTY_KEY, ENV_SYSTEM_ENV_KEY, ENV_KEY1, ENV_KEY2, + // configType keys + CONFIG_TYPE_SYSTEM_PROPERTY_KEY, CONFIG_TYPE_SYSTEM_ENV_KEY + )); + + + @Override + public String getLatestConfig(final String rawDataId, long timeoutMills) { + // Splice the prefix 'seata.' + String dataId = SpringEnvironmentConfigSource.splicePrefixSeataDot(rawDataId); + + try { + return getDefaultValueFromPropertyObject(dataId); + } catch (Throwable t) { + if (!EXCLUDES.contains(rawDataId)) { + LOGGER.error("Get config '{}' defaultValue from the property object failed:", dataId, t); + } else { + LOGGER.debug("Get config '{}' defaultValue from the property object failed:", dataId, t); + } + return null; + } + } + + private String getDefaultValueFromPropertyObject(String dataId) throws IllegalAccessException { + // property name + String propertyName = getPropertyPrefix(dataId); + + // Get the property class + final Class propertyClass = PROPERTY_BEAN_MAP.get(propertyName); + if (propertyClass == null) { + throw new ShouldNeverHappenException("PropertyClass for prefix: [" + propertyName + "] should not be null."); + } + + // Instantiate the property object + Object propertyObj = CollectionUtils.computeIfAbsent(PROPERTY_BEAN_INSTANCE_MAP, propertyName, k -> { + try { + return propertyClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + LOGGER.warn("PropertyClass for prefix: [" + propertyName + "] should not be null. error :" + e.getMessage(), e); + return null; + } + }); + Objects.requireNonNull(propertyObj, () -> "Instantiate the property object fail: " + propertyClass.getName()); + + // property field name + String propertyFieldName = getPropertySuffix(dataId); + // Get defaultValue from the property object + return getDefaultValueFromPropertyObject(propertyObj, propertyFieldName); + } + + /** + * Get defaultValue from the property object + * + * @param propertyObj the property object + * @param fieldName the field name + * @return defaultValue + * @author xingfudeshi@gmail.com + */ + @Nullable + private String getDefaultValueFromPropertyObject(Object propertyObj, String fieldName) throws IllegalAccessException { + Optional fieldOptional = Stream.of(propertyObj.getClass().getDeclaredFields()) + .filter(f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); + + // Get defaultValue from the field + if (fieldOptional.isPresent()) { + Field field = fieldOptional.get(); + if (!Map.class.isAssignableFrom(field.getType())) { + field.setAccessible(true); + Object value = field.get(propertyObj); + return value != null ? String.valueOf(value) : null; + } + } + + return null; + } + + /** + * Get property prefix + * + * @param dataId the dataId + * @return propertyPrefix + */ + private String getPropertyPrefix(String dataId) { + if (dataId.contains(SPECIAL_KEY_VGROUP_MAPPING)) { + return SERVICE_PREFIX; + } + if (dataId.contains(SPECIAL_KEY_GROUPLIST)) { + return SERVICE_PREFIX; + } + return StringUtils.substringBeforeLast(dataId, DOT); + } + + /** + * Get property suffix + * + * @param dataId the dataId + * @return propertySuffix + */ + private String getPropertySuffix(String dataId) { + if (dataId.contains(SPECIAL_KEY_VGROUP_MAPPING)) { + return SPECIAL_KEY_VGROUP_MAPPING; + } + if (dataId.contains(SPECIAL_KEY_GROUPLIST)) { + return SPECIAL_KEY_GROUPLIST; + } + return StringUtils.substringAfterLast(dataId, DOT); + } + + + @Nonnull + @Override + public String getName() { + return "default-value-from-property-object"; + } + + @Override + public int getOrder() { + return PROPERTY_OBJECT_DEFAULT_VALUE_CONFIG_SOURCE_ORDER; + } +} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/SpringEnvironmentConfigSource.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/SpringEnvironmentConfigSource.java new file mode 100644 index 00000000000..cad2fb1853c --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/config/source/SpringEnvironmentConfigSource.java @@ -0,0 +1,128 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed 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. + */ +package io.seata.spring.boot.autoconfigure.config.source; + +import javax.annotation.Nonnull; + +import io.seata.common.exception.ShouldNeverHappenException; +import io.seata.common.holder.ObjectHolder; +import io.seata.common.util.StringUtils; +import io.seata.config.source.ConfigSource; +import org.springframework.core.env.ConfigurableEnvironment; + +import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; +import static io.seata.common.util.StringFormatUtils.DOT; +import static io.seata.config.source.ConfigSourceOrdered.SPRING_ENVIRONMENT_SOURCE_ORDER; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_GROUPLIST; +import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_SERVICE; + +/** + * The type SpringEnvironmentConfigSource. + * + * @author wang.liang + */ +public class SpringEnvironmentConfigSource implements ConfigSource { + + @Override + public String getLatestConfig(String rawDataId, long timeoutMills) { + ConfigurableEnvironment environment = (ConfigurableEnvironment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); + if (environment == null) { + throw new ShouldNeverHappenException("The environment should never set to the ObjectHolder."); + } + + // Splice the prefix 'seata.' + String dataId = splicePrefixSeataDot(rawDataId); + // hump to line + String dataIdLineFormat = StringUtils.hump2Line(dataId); + + // 1. get by dataIdLineFormat + String value = environment.getProperty(dataIdLineFormat); + if (StringUtils.isNotBlank(value)) { + return value; + } + + // 2. get by dataId + if (!dataId.equals(dataIdLineFormat)) { + value = environment.getProperty(dataId); + if (StringUtils.isNotBlank(value)) { + return value; + } + } + + // 3. If the rawDataId format is 'service.{txServiceGroup}.grouplist', change and get again + if (this.isGrouplistDataId(rawDataId)) { + String grouplistDataId = this.changeGrouplistDataIdFormat(rawDataId); + value = environment.getProperty(grouplistDataId); + if (StringUtils.isNotBlank(value)) { + return value; + } + } + + return null; + } + + @Nonnull + @Override + public String getName() { + return "spring-environment"; + } + + @Override + public int getOrder() { + return SPRING_ENVIRONMENT_SOURCE_ORDER; + } + + /** + * Splice the prefix 'seata.' + * + * @param rawDataId the rawDataId + * @return the real dataId for spring environment + */ + public static String splicePrefixSeataDot(String rawDataId) { + if (rawDataId.startsWith(SEATA_PREFIX + DOT)) { + return rawDataId; + } + + return SEATA_PREFIX + DOT + rawDataId; + } + + /** + * Whether the format is 'service.{txServiceGroup}.grouplist' + * + * @param rawDataId the rawDataId + * @return the boolean + */ + private boolean isGrouplistDataId(String rawDataId) { + return rawDataId.startsWith(SPECIAL_KEY_SERVICE + DOT) && rawDataId.endsWith(DOT + SPECIAL_KEY_GROUPLIST); + } + + /** + * Change the format of 'service.{txServiceGroup}.grouplist' to 'seata.service.grouplist.{txServiceGroup}' + * + * @param rawDataId the rawDataId + * @return the real dataId + */ + private String changeGrouplistDataIdFormat(final String rawDataId) { + String txServiceGroup = org.apache.commons.lang.StringUtils.removeStart( + org.apache.commons.lang.StringUtils.removeEnd(rawDataId, DOT + SPECIAL_KEY_GROUPLIST), + SPECIAL_KEY_SERVICE + DOT + ); + + return SERVICE_PREFIX + DOT + SPECIAL_KEY_GROUPLIST + DOT + txServiceGroup; + } +} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringApplicationContextProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringApplicationContextProvider.java index a3b36822d88..dbdd0c50c83 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringApplicationContextProvider.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringApplicationContextProvider.java @@ -23,8 +23,9 @@ import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; /** - * @author xingfudeshi@gmail.com * The type spring application context provider + * + * @author xingfudeshi@gmail.com */ public class SpringApplicationContextProvider implements ApplicationContextAware { diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java deleted file mode 100644 index 5a3c4cdd07c..00000000000 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/io/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 1999-2019 Seata.io Group. - * - * Licensed 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. - */ -package io.seata.spring.boot.autoconfigure.provider; - -import java.lang.reflect.Field; -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Stream; - -import io.seata.common.exception.ShouldNeverHappenException; -import io.seata.common.holder.ObjectHolder; -import io.seata.common.util.CollectionUtils; -import io.seata.common.util.ReflectionUtil; -import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.cglib.proxy.Enhancer; -import org.springframework.cglib.proxy.MethodInterceptor; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.lang.Nullable; - -import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; -import static io.seata.common.util.StringFormatUtils.DOT; -import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SEATA_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SERVICE_PREFIX; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_GROUPLIST; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_SERVICE; -import static io.seata.spring.boot.autoconfigure.StarterConstants.SPECIAL_KEY_VGROUP_MAPPING; - -/** - * @author xingfudeshi@gmail.com - * @author funkye - */ -public class SpringBootConfigurationProvider implements ExtConfigurationProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(SpringBootConfigurationProvider.class); - - private static final String INTERCEPT_METHOD_PREFIX = "get"; - - private static final Map PROPERTY_BEAN_INSTANCE_MAP = new ConcurrentHashMap<>(64); - - @Override - public Configuration provide(Configuration originalConfiguration) { - return (Configuration)Enhancer.create(originalConfiguration.getClass(), - (MethodInterceptor)(proxy, method, args, methodProxy) -> { - if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) { - Object result; - String rawDataId = (String)args[0]; - Class dataType = ReflectionUtil.getWrappedClass(method.getReturnType()); - - // 1. Get config value from the system property - result = originalConfiguration.getConfigFromSys(rawDataId); - - if (result == null) { - String dataId = convertDataId(rawDataId); - - // 2. Get config value from the springboot environment - result = getConfigFromEnvironment(dataId, dataType); - if (result != null) { - return result; - } - - // 3. Get config defaultValue from the arguments - if (args.length > 1) { - result = args[1]; - - if (result != null) { - // See Configuration#getConfig(String dataId, long timeoutMills) - if (dataType.isAssignableFrom(result.getClass())) { - return result; - } else { - result = null; - } - } - } - - // 4. Get config defaultValue from the property object - try { - result = getDefaultValueFromPropertyObject(dataId); - } catch (Throwable t) { - LOGGER.error("Get config '{}' default value from the property object failed:", dataId, t); - } - } - - if (result != null) { - if (dataType.isAssignableFrom(result.getClass())) { - return result; - } - - // Convert type - return this.convertType(result, dataType); - } - } - - return method.invoke(originalConfiguration, args); - }); - } - - private Object getDefaultValueFromPropertyObject(String dataId) throws IllegalAccessException { - String propertyPrefix = getPropertyPrefix(dataId); - String propertySuffix = getPropertySuffix(dataId); - - // Get the property class - final Class propertyClass = PROPERTY_BEAN_MAP.get(propertyPrefix); - if (propertyClass == null) { - throw new ShouldNeverHappenException("PropertyClass for prefix: [" + propertyPrefix + "] should not be null."); - } - - // Instantiate the property object - Object propertyObj = CollectionUtils.computeIfAbsent(PROPERTY_BEAN_INSTANCE_MAP, propertyPrefix, k -> { - try { - return propertyClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - LOGGER.warn("PropertyClass for prefix: [" + propertyPrefix + "] should not be null. error :" + e.getMessage(), e); - } - return null; - }); - Objects.requireNonNull(propertyObj, () -> "Instantiate the property object fail: " + propertyClass.getName()); - - // Get defaultValue from the property object - return getDefaultValueFromPropertyObject(propertyObj, propertySuffix); - } - - /** - * Get defaultValue from the property object - * - * @param propertyObj the property object - * @param fieldName the field name - * @return defaultValue - * @author xingfudeshi@gmail.com - */ - @Nullable - private Object getDefaultValueFromPropertyObject(Object propertyObj, String fieldName) throws IllegalAccessException { - Optional fieldOptional = Stream.of(propertyObj.getClass().getDeclaredFields()) - .filter(f -> f.getName().equalsIgnoreCase(fieldName)).findAny(); - - // Get defaultValue from the field - if (fieldOptional.isPresent()) { - Field field = fieldOptional.get(); - if (!Map.class.isAssignableFrom(field.getType())) { - field.setAccessible(true); - return field.get(propertyObj); - } - } - - return null; - } - - /** - * convert data id - * - * @param rawDataId - * @return dataId - */ - private String convertDataId(String rawDataId) { - if (rawDataId.endsWith(SPECIAL_KEY_GROUPLIST)) { - String suffix = StringUtils.removeStart(StringUtils.removeEnd(rawDataId, DOT + SPECIAL_KEY_GROUPLIST), - SPECIAL_KEY_SERVICE + DOT); - // change the format of default.grouplist to grouplist.default - return SERVICE_PREFIX + DOT + SPECIAL_KEY_GROUPLIST + DOT + suffix; - } - return SEATA_PREFIX + DOT + rawDataId; - } - - /** - * Get property prefix - * - * @param dataId - * @return propertyPrefix - */ - private String getPropertyPrefix(String dataId) { - if (dataId.contains(SPECIAL_KEY_VGROUP_MAPPING)) { - return SERVICE_PREFIX; - } - if (dataId.contains(SPECIAL_KEY_GROUPLIST)) { - return SERVICE_PREFIX; - } - return StringUtils.substringBeforeLast(dataId, String.valueOf(DOT)); - } - - /** - * Get property suffix - * - * @param dataId - * @return propertySuffix - */ - private String getPropertySuffix(String dataId) { - if (dataId.contains(SPECIAL_KEY_VGROUP_MAPPING)) { - return SPECIAL_KEY_VGROUP_MAPPING; - } - if (dataId.contains(SPECIAL_KEY_GROUPLIST)) { - return SPECIAL_KEY_GROUPLIST; - } - return StringUtils.substringAfterLast(dataId, String.valueOf(DOT)); - } - - /** - * get spring config - * - * @param dataId data id - * @param dataType data type - * @return object - */ - @Nullable - private Object getConfigFromEnvironment(String dataId, Class dataType) { - ConfigurableEnvironment environment = (ConfigurableEnvironment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); - Object value = environment.getProperty(dataId, dataType); - if (value == null) { - value = environment.getProperty(io.seata.common.util.StringUtils.hump2Line(dataId), dataType); - } - return value; - } - - private Object convertType(Object configValue, Class dataType) { - if (String.class.equals(dataType)) { - return String.valueOf(configValue); - } - if (Long.class.equals(dataType)) { - return Long.parseLong(String.valueOf(configValue)); - } - if (Integer.class.equals(dataType)) { - return Integer.parseInt(String.valueOf(configValue)); - } - if (Short.class.equals(dataType)) { - return Short.parseShort(String.valueOf(configValue)); - } - if (Boolean.class.equals(dataType)) { - return Boolean.parseBoolean(String.valueOf(configValue)); - } - if (Duration.class.equals(dataType)) { - return Duration.parse(String.valueOf(configValue)); - } - return configValue; - } - -} diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 3c17919d667..3986aa954a8 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -136,7 +136,7 @@ { "name": "handle-as", "parameters": { - "target": "io.seata.config.ConfigType" + "target": "io.seata.config.source.ConfigSourceType" } } ] diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.ExtConfigurationProvider b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.ExtConfigurationProvider deleted file mode 100644 index 8ee3b2b4f45..00000000000 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.ExtConfigurationProvider +++ /dev/null @@ -1 +0,0 @@ -io.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor new file mode 100644 index 00000000000..85a09fc804d --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/resources/META-INF/services/io.seata.config.processor.ConfigurationProcessor @@ -0,0 +1,2 @@ +io.seata.spring.boot.autoconfigure.config.processor.PropertyObjectDefaultValueConfigurationProcessor +io.seata.spring.boot.autoconfigure.config.processor.SpringEnvironmentConfigurationProcessor \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java index e450017a2bb..d39a2aa4dee 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/BasePropertiesTest.java @@ -15,19 +15,18 @@ */ package io.seata.spring.boot.autoconfigure; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; - -import io.seata.common.holder.ObjectHolder; -import org.springframework.core.env.PropertiesPropertySource; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import io.seata.common.holder.ObjectHolder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.env.PropertiesPropertySource; + import static io.seata.common.Constants.OBJECT_KEY_SPRING_APPLICATION_CONTEXT; import static io.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; @@ -48,18 +47,17 @@ public class BasePropertiesTest { @BeforeEach public void setUp() throws IOException { - applicationContex = new AnnotationConfigApplicationContext( - new String[] {"io.seata.spring.boot.autoconfigure.properties.config.test"}); + applicationContex = new AnnotationConfigApplicationContext("io.seata.spring.boot.autoconfigure.properties.config.test"); SeataCoreEnvironmentPostProcessor processor = new SeataCoreEnvironmentPostProcessor(); processor.postProcessEnvironment(null, null); // set new applicationContex for test cases in extension test classes ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_APPLICATION_CONTEXT, applicationContex); ObjectHolder.INSTANCE.setObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT, applicationContex.getEnvironment()); - Properties properties=new Properties(); + Properties properties = new Properties(); ClassLoader classLoader = getClass().getClassLoader(); File f = new File(classLoader.getResource("application-test.properties").getFile()); - try(InputStream in =new FileInputStream(f)) { + try (InputStream in = new FileInputStream(f)) { properties.load(in); } applicationContex.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("serverProperties", properties)); @@ -68,7 +66,7 @@ public void setUp() throws IOException { @AfterEach public void closeContext() { - if(applicationContex!=null) { + if (applicationContex != null) { applicationContex.close(); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ApolloPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ApolloPropertiesTest.java index cc8425ad3df..dbc5a3db90d 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ApolloPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ApolloPropertiesTest.java @@ -15,20 +15,15 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; -import io.seata.config.apollo.ApolloConfiguration; +import io.seata.config.ConfigurationFactory; +import io.seata.config.apollo.ApolloConfigSource; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigApolloProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -37,23 +32,15 @@ @Import(SpringApplicationContextProvider.class) class ApolloPropertiesTest extends BasePropertiesTest { - @Bean("testConfigApolloProperties") - public ConfigApolloProperties configApolloProperties() { - return new ConfigApolloProperties().setApolloMeta(STR_TEST_AAA).setApolloAccessKeySecret(STR_TEST_BBB).setAppId( - STR_TEST_CCC).setNamespace(STR_TEST_DDD).setCluster(STR_TEST_EEE).setApolloConfigService(STR_TEST_FFF); - } - @Test public void testConfigApolloProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide( - configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig(ApolloConfiguration.getApolloMetaFileKey())); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig(ApolloConfiguration.getApolloSecretFileKey())); - assertEquals(STR_TEST_CCC, currentConfiguration.getConfig(ApolloConfiguration.getApolloAppIdFileKey())); - assertEquals(STR_TEST_DDD, currentConfiguration.getConfig(ApolloConfiguration.getApolloNamespaceKey())); - assertEquals(STR_TEST_EEE, currentConfiguration.getConfig(ApolloConfiguration.getApolloCluster())); - assertEquals(STR_TEST_FFF, currentConfiguration.getConfig(ApolloConfiguration.getApolloConfigService())); + assertEquals(STR_TEST_AAA, currentConfiguration.getString(ApolloConfigSource.getApolloMetaFileKey())); + assertEquals(STR_TEST_BBB, currentConfiguration.getString(ApolloConfigSource.getApolloSecretFileKey())); + assertEquals(STR_TEST_CCC, currentConfiguration.getString(ApolloConfigSource.getApolloAppIdFileKey())); + assertEquals(STR_TEST_DDD, currentConfiguration.getString(ApolloConfigSource.getApolloNamespaceKey())); + assertEquals(STR_TEST_EEE, currentConfiguration.getString(ApolloConfigSource.getApolloCluster())); + assertEquals(STR_TEST_FFF, currentConfiguration.getString(ApolloConfigSource.getApolloConfigService())); } } \ No newline at end of file diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConfigPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConfigPropertiesTest.java index f4c7fc1066f..1573d7de6b2 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConfigPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConfigPropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -35,17 +30,12 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class ConfigPropertiesTest extends BasePropertiesTest { - @Bean("testConfigProperties") - public ConfigProperties configProperties() { - return new ConfigProperties().setType(STR_TEST_AAA).setDataType(STR_TEST_BBB); - } @Test public void testConfigFileProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.type")); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig("config.dataType")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.type")); + assertEquals(STR_TEST_BBB, currentConfiguration.getString("config.dataType")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConsulPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConsulPropertiesTest.java index 8670ef57579..e33b795d614 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConsulPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ConsulPropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigConsulProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -35,18 +30,13 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class ConsulPropertiesTest extends BasePropertiesTest { - @Bean("testConfigConsulProperties") - public ConfigConsulProperties configConsulProperties() { - return new ConfigConsulProperties().setServerAddr(STR_TEST_AAA).setAclToken(STR_TEST_BBB).setKey(STR_TEST_CCC); - } @Test public void testConfigConsulProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.consul.serverAddr")); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig("config.consul.aclToken")); - assertEquals(STR_TEST_CCC, currentConfiguration.getConfig("config.consul.key")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.consul.serverAddr")); + assertEquals(STR_TEST_BBB, currentConfiguration.getString("config.consul.aclToken")); + assertEquals(STR_TEST_CCC, currentConfiguration.getString("config.consul.key")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/CustomPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/CustomPropertiesTest.java index fd362508bf6..05674d8699b 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/CustomPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/CustomPropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigCustomProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -36,17 +31,11 @@ @Import(SpringApplicationContextProvider.class) public class CustomPropertiesTest extends BasePropertiesTest { - @Bean("testConfigCustomProperties") - public ConfigCustomProperties configCustomProperties() { - return new ConfigCustomProperties().setName(STR_TEST_AAA); - } - @Test public void testConfigCustomProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.custom.name")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.custom.name")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/Etcd3PropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/Etcd3PropertiesTest.java index 99c5cb6b2fd..87cde5ba9b9 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/Etcd3PropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/Etcd3PropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigEtcd3Properties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -35,17 +30,12 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class Etcd3PropertiesTest extends BasePropertiesTest { - @Bean("testConfigEtcd3Properties") - public ConfigEtcd3Properties configEtcd3Properties() { - return new ConfigEtcd3Properties().setServerAddr(STR_TEST_AAA).setKey(STR_TEST_BBB); - } @Test public void testConfigEtcd3Properties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.etcd3.serverAddr")); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig("config.etcd3.key")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.etcd3.serverAddr")); + assertEquals(STR_TEST_BBB, currentConfiguration.getString("config.etcd3.key")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/FilePropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/FilePropertiesTest.java index 2e9bd5c0db5..efce43aceed 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/FilePropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/FilePropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigFileProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -35,16 +30,11 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class FilePropertiesTest extends BasePropertiesTest { - @Bean("testConfigFileProperties") - public ConfigFileProperties configFileProperties() { - return new ConfigFileProperties().setName(STR_TEST_AAA); - } @Test public void testConfigFileProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.file.name")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.file.name")); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/NacosPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/NacosPropertiesTest.java index 6cbb2635221..d69e69e8f2d 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/NacosPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/NacosPropertiesTest.java @@ -15,20 +15,15 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; -import io.seata.config.nacos.NacosConfiguration; +import io.seata.config.ConfigurationFactory; +import io.seata.config.nacos.NacosConfigSource; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigNacosProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -36,21 +31,16 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class NacosPropertiesTest extends BasePropertiesTest { - @Bean("testConfigNacosProperties") - public ConfigNacosProperties configNacosProperties() { - return new ConfigNacosProperties().setServerAddr(STR_TEST_AAA).setDataId(STR_TEST_BBB).setGroup(STR_TEST_CCC).setNamespace(STR_TEST_DDD).setUsername(STR_TEST_EEE).setPassword(STR_TEST_FFF); - } @Test public void testConfigNacosProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig(NacosConfiguration.getNacosAddrFileKey())); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig(NacosConfiguration.getNacosDataIdKey())); - assertEquals(STR_TEST_CCC, currentConfiguration.getConfig(NacosConfiguration.getNacosGroupKey())); - assertEquals(STR_TEST_DDD, currentConfiguration.getConfig(NacosConfiguration.getNacosNameSpaceFileKey())); - assertEquals(STR_TEST_EEE, currentConfiguration.getConfig(NacosConfiguration.getNacosUserName())); - assertEquals(STR_TEST_FFF, currentConfiguration.getConfig(NacosConfiguration.getNacosPassword())); + assertEquals(STR_TEST_AAA, currentConfiguration.getString(NacosConfigSource.getNacosAddrFileKey())); + assertEquals(STR_TEST_BBB, currentConfiguration.getString(NacosConfigSource.getNacosDataIdKey())); + assertEquals(STR_TEST_CCC, currentConfiguration.getString(NacosConfigSource.getNacosGroupKey())); + assertEquals(STR_TEST_DDD, currentConfiguration.getString(NacosConfigSource.getNacosNameSpaceFileKey())); + assertEquals(STR_TEST_EEE, currentConfiguration.getString(NacosConfigSource.getNacosUserName())); + assertEquals(STR_TEST_FFF, currentConfiguration.getString(NacosConfigSource.getNacosPassword())); } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java index a86afbae9ca..09d23254c73 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/io/seata/spring/boot/autoconfigure/properties/config/test/ZooKeeperPropertiesTest.java @@ -15,19 +15,14 @@ */ package io.seata.spring.boot.autoconfigure.properties.config.test; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.spring.boot.autoconfigure.BasePropertiesTest; -import io.seata.spring.boot.autoconfigure.properties.config.ConfigZooKeeperProperties; import io.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider; import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author slievrly @@ -35,20 +30,15 @@ @org.springframework.context.annotation.Configuration @Import(SpringApplicationContextProvider.class) public class ZooKeeperPropertiesTest extends BasePropertiesTest { - @Bean("testConfigZooKeeperProperties") - public ConfigZooKeeperProperties configZooKeeperProperties() { - return new ConfigZooKeeperProperties().setNodePath(STR_TEST_AAA).setServerAddr(STR_TEST_BBB).setUsername(STR_TEST_CCC).setPassword(STR_TEST_DDD).setConnectTimeout(LONG_TEST_ONE).setSessionTimeout(LONG_TEST_TWO); - } @Test public void testConfigZooKeeperProperties() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); - assertEquals(STR_TEST_AAA, currentConfiguration.getConfig("config.zk.nodePath")); - assertEquals(STR_TEST_BBB, currentConfiguration.getConfig("config.zk.serverAddr")); - assertEquals(STR_TEST_CCC, currentConfiguration.getConfig("config.zk.username")); - assertEquals(STR_TEST_DDD, currentConfiguration.getConfig("config.zk.password")); + assertEquals(STR_TEST_AAA, currentConfiguration.getString("config.zk.nodePath")); + assertEquals(STR_TEST_BBB, currentConfiguration.getString("config.zk.serverAddr")); + assertEquals(STR_TEST_CCC, currentConfiguration.getString("config.zk.username")); + assertEquals(STR_TEST_DDD, currentConfiguration.getString("config.zk.password")); assertEquals(LONG_TEST_ONE, currentConfiguration.getInt("config.zk.connectTimeout")); assertEquals(LONG_TEST_TWO, currentConfiguration.getInt("config.zk.sessionTimeout")); } diff --git a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java index 61f8baef129..0937d81f951 100644 --- a/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java +++ b/seata-spring-boot-starter/src/test/java/io/seata/spring/boot/autoconfigure/RedisAutoInjectionTypeConvertTest.java @@ -15,10 +15,8 @@ */ package io.seata.spring.boot.autoconfigure; -import io.seata.common.loader.EnhancedServiceLoader; import io.seata.config.Configuration; -import io.seata.config.ExtConfigurationProvider; -import io.seata.config.FileConfiguration; +import io.seata.config.ConfigurationFactory; import io.seata.config.springcloud.SpringApplicationContextProvider; import io.seata.spring.boot.autoconfigure.properties.registry.RegistryRedisProperties; import org.junit.jupiter.api.AfterAll; @@ -31,7 +29,6 @@ import static io.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP; import static io.seata.spring.boot.autoconfigure.StarterConstants.REGISTRY_REDIS_PREFIX; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; /** * @author zhangheng @@ -56,15 +53,13 @@ RegistryRedisProperties registryRedisProperties() { @Test public void testReadConfigurationItems() { - FileConfiguration configuration = mock(FileConfiguration.class); - Configuration currentConfiguration = - EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration); + Configuration currentConfiguration = ConfigurationFactory.getInstance(); System.setProperty("seata.registry.redis.db","1"); assertEquals(1, currentConfiguration.getInt("registry.redis.db")); System.setProperty("seata.registry.redis.password","123456"); - assertEquals("123456", currentConfiguration.getConfig("registry.redis.password")); + assertEquals("123456", currentConfiguration.getString("registry.redis.password")); System.setProperty("seata.registry.redis.serverAddr","localhost:123456"); - assertEquals("localhost:123456", currentConfiguration.getConfig("registry.redis.serverAddr")); + assertEquals("localhost:123456", currentConfiguration.getString("registry.redis.serverAddr")); } @AfterAll diff --git a/server/src/main/java/io/seata/server/ParameterParser.java b/server/src/main/java/io/seata/server/ParameterParser.java index 55690fcaf31..4ebad112143 100644 --- a/server/src/main/java/io/seata/server/ParameterParser.java +++ b/server/src/main/java/io/seata/server/ParameterParser.java @@ -24,7 +24,7 @@ import io.seata.server.env.ContainerHelper; import io.seata.server.store.StoreConfig; -import static io.seata.config.ConfigurationFactory.ENV_PROPERTY_KEY; +import static io.seata.config.util.ConfigurationUtils.ENV_SYSTEM_PROPERTY_KEY; /** * The type Parameter parser. @@ -68,6 +68,7 @@ public ParameterParser(String... args) { /** * startup args > docker env + * * @param args */ private void init(String[] args) { @@ -75,7 +76,7 @@ private void init(String[] args) { getCommandParameters(args); getEnvParameters(); if (StringUtils.isNotBlank(seataEnv)) { - System.setProperty(ENV_PROPERTY_KEY, seataEnv); + System.setProperty(ENV_SYSTEM_PROPERTY_KEY, seataEnv); } StoreConfig.setStartupParameter(storeMode, sessionStoreMode, lockStoreMode); } catch (ParameterException e) { @@ -192,8 +193,8 @@ public String getSeataEnv() { * Clean up. */ public void cleanUp() { - if (null != System.getProperty(ENV_PROPERTY_KEY)) { - System.clearProperty(ENV_PROPERTY_KEY); + if (null != System.getProperty(ENV_SYSTEM_PROPERTY_KEY)) { + System.clearProperty(ENV_SYSTEM_PROPERTY_KEY); } } diff --git a/server/src/main/java/io/seata/server/Server.java b/server/src/main/java/io/seata/server/Server.java index 30c73c36c71..2535e06203d 100644 --- a/server/src/main/java/io/seata/server/Server.java +++ b/server/src/main/java/io/seata/server/Server.java @@ -63,7 +63,7 @@ public static void start(String[] args) { if (NetUtil.isValidIp(parameterParser.getHost(), false)) { XID.setIpAddress(parameterParser.getHost()); } else { - String preferredNetworks = ConfigurationFactory.getInstance().getConfig(REGISTRY_PREFERED_NETWORKS); + String preferredNetworks = ConfigurationFactory.getInstance().getString(REGISTRY_PREFERED_NETWORKS); if (StringUtils.isNotBlank(preferredNetworks)) { XID.setIpAddress(NetUtil.getLocalIp(preferredNetworks.split(REGEX_SPLIT_CHAR))); } else { diff --git a/server/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java b/server/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java index 214bceb9d40..7ee20f52f05 100644 --- a/server/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java +++ b/server/src/main/java/io/seata/server/console/impl/db/BranchSessionDBServiceImpl.java @@ -60,12 +60,12 @@ public class BranchSessionDBServiceImpl implements BranchSessionService { public BranchSessionDBServiceImpl() { Configuration configuration = ConfigurationFactory.getInstance(); - branchTable = configuration.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); + branchTable = configuration.getString(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); + dbType = configuration.getString(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + String dbDataSource = configuration.getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); if (StringUtils.isBlank(dbDataSource)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); } diff --git a/server/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java b/server/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java index 58e2183db4f..b40eae247ce 100644 --- a/server/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java +++ b/server/src/main/java/io/seata/server/console/impl/db/GlobalLockDBServiceImpl.java @@ -63,12 +63,12 @@ public class GlobalLockDBServiceImpl implements GlobalLockService { public GlobalLockDBServiceImpl() { Configuration configuration = ConfigurationFactory.getInstance(); - lockTable = configuration.getConfig(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); + lockTable = configuration.getString(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); + dbType = configuration.getString(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + String dbDataSource = configuration.getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); if (StringUtils.isBlank(dbDataSource)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); } diff --git a/server/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java b/server/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java index 7583cf3c2b1..bcef972dbd7 100644 --- a/server/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java +++ b/server/src/main/java/io/seata/server/console/impl/db/GlobalSessionDBServiceImpl.java @@ -70,12 +70,12 @@ public class GlobalSessionDBServiceImpl implements GlobalSessionService { public GlobalSessionDBServiceImpl() { Configuration configuration = ConfigurationFactory.getInstance(); - globalTable = configuration.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); + globalTable = configuration.getString(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); + dbType = configuration.getString(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_TYPE + " should not be blank"); } - String dbDataSource = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + String dbDataSource = configuration.getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); if (StringUtils.isBlank(dbDataSource)) { throw new IllegalArgumentException(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE + " should not be blank"); } diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java index df366274f96..0db7a84fdce 100644 --- a/server/src/main/java/io/seata/server/session/SessionHolder.java +++ b/server/src/main/java/io/seata/server/session/SessionHolder.java @@ -114,7 +114,7 @@ public static void init(SessionMode sessionMode) { DISTRIBUTED_LOCKER = DistributedLockerFactory.getDistributedLocker(SessionMode.DB.getName()); } else if (SessionMode.FILE.equals(sessionMode)) { - String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR, + String sessionStorePath = CONFIG.getString(ConfigurationKeys.STORE_FILE_DIR, DEFAULT_SESSION_STORE_FILE_DIR); if (StringUtils.isBlank(sessionStorePath)) { throw new StoreException("the {store.file.dir} is empty."); diff --git a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java index 0b39a0126c7..d03481c69db 100644 --- a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java +++ b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseDistributedLocker.java @@ -22,6 +22,7 @@ import java.sql.SQLException; import java.util.Objects; import javax.sql.DataSource; + import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.loader.EnhancedServiceLoader; import io.seata.common.loader.LoadLevel; @@ -29,10 +30,9 @@ import io.seata.common.util.IOUtil; import io.seata.common.util.StringUtils; import io.seata.config.Configuration; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.constants.ServerTableColumnsName; import io.seata.core.store.DistributedLockDO; @@ -72,13 +72,13 @@ public class DataBaseDistributedLocker implements DistributedLocker { public DataBaseDistributedLocker() { Configuration configuration = ConfigurationFactory.getInstance(); - distributedLockTable = configuration.getConfig(DISTRIBUTED_LOCK_DB_TABLE); - dbType = configuration.getConfig(ConfigurationKeys.STORE_DB_TYPE); - datasourceType = configuration.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + distributedLockTable = configuration.getString(DISTRIBUTED_LOCK_DB_TABLE); + dbType = configuration.getString(ConfigurationKeys.STORE_DB_TYPE); + datasourceType = configuration.getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); if (StringUtils.isBlank(distributedLockTable)) { demotion = true; - ConfigurationCache.addConfigListener(DISTRIBUTED_LOCK_DB_TABLE, new ConfigurationChangeListener() { + ConfigurationFactory.addConfigListener(DISTRIBUTED_LOCK_DB_TABLE, new ConfigurationChangeListener() { @Override public void onChangeEvent(ConfigurationChangeEvent event) { String newValue = event.getNewValue(); @@ -86,7 +86,7 @@ public void onChangeEvent(ConfigurationChangeEvent event) { distributedLockTable = newValue; init(); demotion = false; - ConfigurationCache.removeConfigListener(DISTRIBUTED_LOCK_DB_TABLE, this); + ConfigurationFactory.removeConfigListener(DISTRIBUTED_LOCK_DB_TABLE, this); } } }); diff --git a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java index 1e4736fbe07..1de804ba1a1 100644 --- a/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java +++ b/server/src/main/java/io/seata/server/storage/db/lock/DataBaseLockManager.java @@ -40,13 +40,20 @@ public class DataBaseLockManager extends AbstractLockManager implements Initiali * The locker. */ private Locker locker; + private volatile boolean initialized = false; @Override public void init() { // init dataSource - String datasourceType = ConfigurationFactory.getInstance().getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + String datasourceType = ConfigurationFactory.getInstance().getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); DataSource lockStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); locker = new DataBaseLocker(lockStoreDataSource); + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/server/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java b/server/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java index 5ad6eaa41ac..3dd54fcd8b9 100644 --- a/server/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java +++ b/server/src/main/java/io/seata/server/storage/db/lock/LockStoreDataBaseDAO.java @@ -84,8 +84,8 @@ public class LockStoreDataBaseDAO implements LockStore { */ public LockStoreDataBaseDAO(DataSource lockStoreDataSource) { this.lockStoreDataSource = lockStoreDataSource; - lockTable = CONFIG.getConfig(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); + lockTable = CONFIG.getString(ConfigurationKeys.LOCK_DB_TABLE, DEFAULT_LOCK_DB_TABLE); + dbType = CONFIG.getString(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { throw new StoreException("there must be db type."); } diff --git a/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java b/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java index 053853527eb..9def8e7bcd7 100644 --- a/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java +++ b/server/src/main/java/io/seata/server/storage/db/session/DataBaseSessionManager.java @@ -53,6 +53,7 @@ public class DataBaseSessionManager extends AbstractSessionManager * The Task name. */ protected String taskName; + private volatile boolean initialized = false; /** * Instantiates a new Data base session manager. @@ -74,6 +75,12 @@ public DataBaseSessionManager(String name) { @Override public void init() { transactionStoreManager = DataBaseTransactionStoreManager.getInstance(); + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java b/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java index d4daefa23ec..bfdc3ecb9f0 100644 --- a/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java +++ b/server/src/main/java/io/seata/server/storage/db/store/DataBaseTransactionStoreManager.java @@ -89,7 +89,7 @@ public static DataBaseTransactionStoreManager getInstance() { */ private DataBaseTransactionStoreManager() { logQueryLimit = CONFIG.getInt(ConfigurationKeys.STORE_DB_LOG_QUERY_LIMIT, DEFAULT_QUERY_LIMIT); - String datasourceType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); + String datasourceType = CONFIG.getString(ConfigurationKeys.STORE_DB_DATASOURCE_TYPE); //init dataSource DataSource logStoreDataSource = EnhancedServiceLoader.load(DataSourceProvider.class, datasourceType).provide(); logStore = new LogStoreDataBaseDAO(logStoreDataSource); diff --git a/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java b/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java index 3aa86db0dce..c63c183b3c0 100644 --- a/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java +++ b/server/src/main/java/io/seata/server/storage/db/store/LogStoreDataBaseDAO.java @@ -91,11 +91,11 @@ public class LogStoreDataBaseDAO implements LogStore { */ public LogStoreDataBaseDAO(DataSource logStoreDataSource) { this.logStoreDataSource = logStoreDataSource; - globalTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, + globalTable = CONFIG.getString(ConfigurationKeys.STORE_DB_GLOBAL_TABLE, DEFAULT_STORE_DB_GLOBAL_TABLE); - branchTable = CONFIG.getConfig(ConfigurationKeys.STORE_DB_BRANCH_TABLE, + branchTable = CONFIG.getString(ConfigurationKeys.STORE_DB_BRANCH_TABLE, DEFAULT_STORE_DB_BRANCH_TABLE); - dbType = CONFIG.getConfig(ConfigurationKeys.STORE_DB_TYPE); + dbType = CONFIG.getString(ConfigurationKeys.STORE_DB_TYPE); if (StringUtils.isBlank(dbType)) { throw new StoreException("there must be db type."); } diff --git a/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java b/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java index d3d1a442eed..8aa1468b44b 100644 --- a/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java +++ b/server/src/main/java/io/seata/server/storage/redis/JedisPooledFactory.java @@ -59,7 +59,7 @@ public class JedisPooledFactory { /** * get the RedisPool instance (singleton) - * + * * @return redisPool */ public static JedisPoolAbstract getJedisPoolInstance(JedisPoolAbstract... jedisPools) { @@ -70,11 +70,11 @@ public static JedisPoolAbstract getJedisPoolInstance(JedisPoolAbstract... jedisP if (jedisPools != null && jedisPools.length > 0) { tempJedisPool = jedisPools[0]; } else { - String password = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_PASSWORD); + String password = CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_PASSWORD); if (StringUtils.isBlank(password)) { password = null; } else { - String publicKey = CONFIGURATION.getConfig(ConfigurationKeys.STORE_PUBLIC_KEY); + String publicKey = CONFIGURATION.getString(ConfigurationKeys.STORE_PUBLIC_KEY); if (StringUtils.isNotBlank(publicKey)) { try { password = ConfigTools.publicDecrypt(password, publicKey); @@ -89,19 +89,19 @@ public static JedisPoolAbstract getJedisPoolInstance(JedisPoolAbstract... jedisP poolConfig.setMaxIdle(CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MAX_CONN, DEFAULT_REDIS_MAX_IDLE)); poolConfig.setMaxTotal(CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_MAX_TOTAL, DEFAULT_REDIS_MAX_TOTAL)); - String mode = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_MODE,ConfigurationKeys.REDIS_SINGLE_MODE); + String mode = CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_MODE,ConfigurationKeys.REDIS_SINGLE_MODE); if (mode.equals(ConfigurationKeys.REDIS_SENTINEL_MODE)) { - String masterName = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_SENTINEL_MASTERNAME); + String masterName = CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_SENTINEL_MASTERNAME); if (StringUtils.isBlank(masterName)) { throw new RedisException("The masterName is null in redis sentinel mode"); } Set sentinels = new HashSet<>(SENTINEL_HOST_NUMBER); - String[] sentinelHosts = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_SENTINEL_HOST).split(","); + String[] sentinelHosts = CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_SENTINEL_HOST).split(","); Arrays.asList(sentinelHosts).forEach(sentinelHost -> sentinels.add(sentinelHost)); tempJedisPool = new JedisSentinelPool(masterName, sentinels, poolConfig, 60000, password, CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_DATABASE, DATABASE)); } else if (mode.equals(ConfigurationKeys.REDIS_SINGLE_MODE)) { - String host = CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_SINGLE_HOST); - host = StringUtils.isBlank(host) ? CONFIGURATION.getConfig(ConfigurationKeys.STORE_REDIS_HOST, HOST) : host; + String host = CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_SINGLE_HOST); + host = StringUtils.isBlank(host) ? CONFIGURATION.getString(ConfigurationKeys.STORE_REDIS_HOST, HOST) : host; int port = CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_SINGLE_PORT); port = port == 0 ? CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_PORT, PORT) : port; tempJedisPool = new JedisPool(poolConfig, host, port, 60000, password, CONFIGURATION.getInt(ConfigurationKeys.STORE_REDIS_DATABASE, DATABASE)); @@ -121,7 +121,7 @@ public static JedisPoolAbstract getJedisPoolInstance(JedisPoolAbstract... jedisP /** * get an instance of Jedis (connection) from the connection pool - * + * * @return jedis */ public static Jedis getJedisInstance() { diff --git a/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java index 067fd50d622..19bf7e0bc4a 100644 --- a/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java +++ b/server/src/main/java/io/seata/server/storage/redis/lock/RedisLockManager.java @@ -33,10 +33,17 @@ public class RedisLockManager extends AbstractLockManager implements Initialize * The locker. */ private Locker locker; + private volatile boolean initialized = false; @Override public void init() { locker = new RedisLocker(); + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java b/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java index c2b2dfc39b7..53993dcb271 100644 --- a/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java +++ b/server/src/main/java/io/seata/server/storage/redis/session/RedisSessionManager.java @@ -51,6 +51,7 @@ public class RedisSessionManager extends AbstractSessionManager * The Task name. */ protected String taskName; + private volatile boolean initialized = false; /** * Instantiates a new Data base session manager. @@ -73,6 +74,12 @@ public RedisSessionManager(String name) { @Override public void init() { transactionStoreManager = RedisTransactionStoreManager.getInstance(); + initialized = true; + } + + @Override + public boolean isInitialized() { + return initialized; } @Override diff --git a/server/src/main/java/io/seata/server/store/StoreConfig.java b/server/src/main/java/io/seata/server/store/StoreConfig.java index 362c7992e1d..3b7f1ecd4a9 100644 --- a/server/src/main/java/io/seata/server/store/StoreConfig.java +++ b/server/src/main/java/io/seata/server/store/StoreConfig.java @@ -82,7 +82,7 @@ public static int getFileWriteBufferCacheSize() { } public static FlushDiskMode getFlushDiskMode() { - return FlushDiskMode.findDiskMode(CONFIGURATION.getConfig(STORE_FILE_PREFIX + "flushDiskMode")); + return FlushDiskMode.findDiskMode(CONFIGURATION.getString(STORE_FILE_PREFIX + "flushDiskMode")); } /** @@ -101,7 +101,7 @@ private static StoreMode getStoreMode() { return StoreMode.get(storeModeEnv); } //config - String storeModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_MODE, SERVER_DEFAULT_STORE_MODE); + String storeModeConfig = CONFIGURATION.getString(ConfigurationKeys.STORE_MODE, SERVER_DEFAULT_STORE_MODE); return StoreMode.get(storeModeConfig); } @@ -116,7 +116,7 @@ public static SessionMode getSessionMode() { return SessionMode.get(sessionModeEnv); } //config - String sessionModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_SESSION_MODE); + String sessionModeConfig = CONFIGURATION.getString(ConfigurationKeys.STORE_SESSION_MODE); if (StringUtils.isNotBlank(sessionModeConfig)) { return SessionMode.get(sessionModeConfig); } @@ -135,7 +135,7 @@ public static LockMode getLockMode() { return LockMode.get(lockModeEnv); } //config - String lockModeConfig = CONFIGURATION.getConfig(ConfigurationKeys.STORE_LOCK_MODE); + String lockModeConfig = CONFIGURATION.getString(ConfigurationKeys.STORE_LOCK_MODE); if (StringUtils.isNotBlank(lockModeConfig)) { return LockMode.get(lockModeConfig); } diff --git a/server/src/test/java/io/seata/server/session/FileSessionManagerTest.java b/server/src/test/java/io/seata/server/session/FileSessionManagerTest.java index 9b2b74856c8..05743ce3a32 100644 --- a/server/src/test/java/io/seata/server/session/FileSessionManagerTest.java +++ b/server/src/test/java/io/seata/server/session/FileSessionManagerTest.java @@ -67,7 +67,7 @@ public class FileSessionManagerTest { @Resource(type = GlobalSessionService.class) private GlobalSessionService globalSessionService; - private static String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR, + private static String sessionStorePath = CONFIG.getString(ConfigurationKeys.STORE_FILE_DIR, DEFAULT_SESSION_STORE_FILE_DIR); @BeforeAll diff --git a/server/src/test/java/io/seata/server/session/SessionHolderTest.java b/server/src/test/java/io/seata/server/session/SessionHolderTest.java index aa259cde9fc..84d81bcd85b 100644 --- a/server/src/test/java/io/seata/server/session/SessionHolderTest.java +++ b/server/src/test/java/io/seata/server/session/SessionHolderTest.java @@ -48,7 +48,7 @@ public class SessionHolderTest { @BeforeEach public void before() { - String sessionStorePath = SessionHolder.CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR); + String sessionStorePath = SessionHolder.CONFIG.getString(ConfigurationKeys.STORE_FILE_DIR); //delete file previously created pathname = sessionStorePath + File.separator + ROOT_SESSION_MANAGER_NAME; // SessionHolder.init(StoreMode.REDIS.getName()); diff --git a/server/src/test/java/io/seata/server/store/SessionStoreTest.java b/server/src/test/java/io/seata/server/store/SessionStoreTest.java index 49ade6dce27..83a51e5a15f 100644 --- a/server/src/test/java/io/seata/server/store/SessionStoreTest.java +++ b/server/src/test/java/io/seata/server/store/SessionStoreTest.java @@ -65,7 +65,7 @@ public static void setUp(ApplicationContext context) { */ @BeforeEach public void clean() throws Exception { - String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR); + String sessionStorePath = CONFIG.getString(ConfigurationKeys.STORE_FILE_DIR); File rootDataFile = new File(sessionStorePath + File.separator + SessionHolder.ROOT_SESSION_MANAGER_NAME); File rootDataFileHis = new File( sessionStorePath + File.separator + SessionHolder.ROOT_SESSION_MANAGER_NAME + ".1"); diff --git a/server/src/test/java/io/seata/server/util/StoreUtil.java b/server/src/test/java/io/seata/server/util/StoreUtil.java index 9f3f88b56b4..4104ca77a53 100644 --- a/server/src/test/java/io/seata/server/util/StoreUtil.java +++ b/server/src/test/java/io/seata/server/util/StoreUtil.java @@ -27,7 +27,7 @@ public class StoreUtil { private static String sessionStorePath = - ConfigurationFactory.getInstance().getConfig(ConfigurationKeys.STORE_FILE_DIR, DEFAULT_SESSION_STORE_FILE_DIR); + ConfigurationFactory.getInstance().getString(ConfigurationKeys.STORE_FILE_DIR, DEFAULT_SESSION_STORE_FILE_DIR); public static void deleteDataFile() { try { diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java index ef455ea6e54..aa40573f4e4 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java @@ -22,15 +22,13 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; - import javax.annotation.Nullable; import io.seata.common.util.CollectionUtils; import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.rpc.ShutdownHook; import io.seata.core.rpc.netty.RmNettyRemotingClient; @@ -282,7 +280,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) TCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), applicationContext); //TCC interceptor, proxy bean of sofa:reference/dubbo:reference, and LocalTCC interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName)); - ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, + ConfigurationFactory.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener)interceptor); } else { Class serviceInterface = SpringProxyUtils.findTargetClass(bean); @@ -295,7 +293,7 @@ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) if (globalTransactionalInterceptor == null) { globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook); - ConfigurationCache.addConfigListener( + ConfigurationFactory.addConfigListener( ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener)globalTransactionalInterceptor); } @@ -504,7 +502,7 @@ public void afterPropertiesSet() { if (LOGGER.isInfoEnabled()) { LOGGER.info("Global transaction is disabled."); } - ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, + ConfigurationFactory.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, (ConfigurationChangeListener)this); return; } @@ -527,7 +525,7 @@ public void onChangeEvent(ConfigurationChangeEvent event) { LOGGER.info("{} config changed, old value:true, new value:{}", ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, event.getNewValue()); initClient(); - ConfigurationCache.removeConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, this); + ConfigurationFactory.removeConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION, this); } } } diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java index 088e7462866..d6006d548d3 100644 --- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java +++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java @@ -24,13 +24,13 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import com.google.common.eventbus.Subscribe; import io.seata.common.exception.ShouldNeverHappenException; import io.seata.common.thread.NamedThreadFactory; import io.seata.common.util.StringUtils; -import io.seata.config.ConfigurationCache; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.event.EventBus; import io.seata.core.event.GuavaEventBus; @@ -49,8 +49,6 @@ import io.seata.tm.api.transaction.NoRollbackRule; import io.seata.tm.api.transaction.RollbackRule; import io.seata.tm.api.transaction.TransactionInfo; - -import com.google.common.eventbus.Subscribe; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; @@ -141,7 +139,7 @@ public GlobalTransactionalInterceptor(FailureHandler failureHandler) { if (degradeCheck && degradeCheckPeriod > 0 && degradeCheckAllowTimes > 0) { startDegradeCheck(); } - ConfigurationCache.addConfigListener(ConfigurationKeys.CLIENT_DEGRADE_CHECK, this); + ConfigurationFactory.addConfigListener(ConfigurationKeys.CLIENT_DEGRADE_CHECK, this); this.initDefaultGlobalTransactionTimeout(); } diff --git a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java b/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java index b09f282ec72..1a106daa477 100644 --- a/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java +++ b/spring/src/main/java/io/seata/spring/tcc/TccActionInterceptor.java @@ -19,9 +19,9 @@ import javax.annotation.Nullable; import io.seata.common.DefaultValues; -import io.seata.config.ConfigurationChangeEvent; -import io.seata.config.ConfigurationChangeListener; import io.seata.config.ConfigurationFactory; +import io.seata.config.changelistener.ConfigurationChangeEvent; +import io.seata.config.changelistener.ConfigurationChangeListener; import io.seata.core.constants.ConfigurationKeys; import io.seata.core.context.RootContext; import io.seata.core.model.BranchType;