From 0398bf1d2b394a403754ec91102eae6ed6008b9e Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 11:27:16 +0800 Subject: [PATCH 1/6] Config SPI definition and implementation --- brook-common/pom.xml | 5 + .../common/extension/ExtensionLoader.java | 12 +- .../brook/common/utils/FieldUtils.java | 28 +- .../mytang0/brook/common/utils/JsonUtils.java | 6 + .../brook/common/utils/MethodUtils.java | 17 ++ .../brook/common/utils/ReflectUtils.java | 7 + .../core/config/DefaultConfigurator.java | 194 ++++++++++++ .../xyz.mytang0.brook.spi.config.Configurator | 1 + .../core/config/DefaultConfiguratorTest.java | 288 ++++++++++++++++++ .../brook/spi/config/ConfigProperties.java | 19 ++ .../brook/spi/config/ConfigSource.java | 12 + .../brook/spi/config/ConfigValidator.java | 17 ++ .../brook/spi/config/Configurator.java | 11 + 13 files changed, 608 insertions(+), 9 deletions(-) create mode 100644 brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java create mode 100644 brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.Configurator create mode 100644 brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java create mode 100644 brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigProperties.java create mode 100644 brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigSource.java create mode 100644 brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigValidator.java create mode 100644 brook-spi/src/main/java/xyz/mytang0/brook/spi/config/Configurator.java diff --git a/brook-common/pom.xml b/brook-common/pom.xml index e531221..949def8 100644 --- a/brook-common/pom.xml +++ b/brook-common/pom.xml @@ -50,5 +50,10 @@ com.fasterxml.jackson.core jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + \ No newline at end of file diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java b/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java index a1daafe..d741149 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java @@ -229,15 +229,15 @@ public List getExtensionInstances() { return (List) this.cachedInstances.values() .stream() .map(Holder::get) + .sorted(OrderComparator.INSTANCE) .collect(Collectors.toList()); } // Dynamic Loading - List instances = new ArrayList<>(); - extensionClasses.keySet().forEach(name -> - Optional.ofNullable(this.getExtension(name)) - .ifPresent(instances::add) - ); - return instances; + return extensionClasses.keySet() + .stream() + .map(this::getExtension) + .sorted(OrderComparator.INSTANCE) + .collect(Collectors.toList()); } @SuppressWarnings("unchecked") diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/FieldUtils.java b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/FieldUtils.java index 77c79c4..81fa8d1 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/FieldUtils.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/FieldUtils.java @@ -4,6 +4,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Map; @@ -179,17 +180,38 @@ public static Object getValueByName(Object obj, String fieldName) public static Field getFieldByName(Object obj, String fieldName) { Class superClass = obj.getClass(); + return getFieldByName(superClass, fieldName); + } - while (superClass != Object.class) { + public static Field getFieldByName(Class clazz, String fieldName) { + while (clazz != Object.class) { try { - return superClass.getDeclaredField(fieldName); + return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException var4) { - superClass = superClass.getSuperclass(); + clazz = clazz.getSuperclass(); } } return null; } + public static void setFieldValue(Method method, Object instance, Object value) { + boolean isInaccessible = !method.isAccessible(); + if (isInaccessible) { + method.setAccessible(true); + } + try { + method.invoke(instance, value); + } catch (IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { + throw new RuntimeException(method.getName(), e); + } finally { + if (isInaccessible) { + method.setAccessible(false); + } + } + } + public static Map objectToMap(Object fromValue) { return JsonUtils.convertValue(fromValue, new TypeReference>() { }); diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/JsonUtils.java b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/JsonUtils.java index b7787ea..bd8585d 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/JsonUtils.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/JsonUtils.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.io.IOException; import java.io.InputStream; @@ -22,6 +23,7 @@ public abstract class JsonUtils { private static final ObjectMapper DEFAULT = new ObjectMapper() .configure(FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(FAIL_ON_UNRESOLVED_OBJECT_IDS, false) + .registerModule(new JavaTimeModule()) .setSerializationInclusion(JsonInclude.Include.NON_NULL); private static volatile ObjectMapper objectMapper = DEFAULT; @@ -30,6 +32,10 @@ public static void setObjectMapper(ObjectMapper objectMapper) { JsonUtils.objectMapper = Optional.ofNullable(objectMapper).orElse(DEFAULT); } + public static ObjectMapper getObjectMapper() { + return objectMapper; + } + public static String toJsonString(Object object) { Objects.requireNonNull(objectMapper); try { diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/MethodUtils.java b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/MethodUtils.java index 726d314..1aacb2f 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/MethodUtils.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/MethodUtils.java @@ -203,4 +203,21 @@ private static void getAllInterfaces(Class cls, cls = cls.getSuperclass(); } } + + public static List getSetterMethods(Class cls) { + List setters = new ArrayList<>(); + Method[] methods = cls.getMethods(); + for (Method method : methods) { + if (isSetter(method)) { + setters.add(method); + } + } + return setters; + } + + private static boolean isSetter(Method method) { + return method.getName().startsWith("set") + && method.getParameterCount() == 1 + && method.getReturnType().equals(void.class); + } } diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/ReflectUtils.java b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/ReflectUtils.java index 7caf2f8..89c3678 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/utils/ReflectUtils.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/utils/ReflectUtils.java @@ -14,4 +14,11 @@ public static boolean isPrimitives(Class cls) { public static boolean isPrimitive(Class cls) { return ClassUtils.isPrimitiveOrWrapper(cls); } + + public static boolean isJdkClass(Class cls) { + String packageName = cls.getPackage().getName(); + return packageName.startsWith("java.") || + packageName.startsWith("javax.") || + packageName.startsWith("com.sun."); + } } diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java new file mode 100644 index 0000000..cadefe7 --- /dev/null +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java @@ -0,0 +1,194 @@ +package xyz.mytang0.brook.core.config; + +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; +import xyz.mytang0.brook.common.constants.Delimiter; +import xyz.mytang0.brook.common.extension.ExtensionDirector; +import xyz.mytang0.brook.common.utils.FieldUtils; +import xyz.mytang0.brook.common.utils.JsonUtils; +import xyz.mytang0.brook.common.utils.MethodUtils; +import xyz.mytang0.brook.common.utils.ReflectUtils; +import xyz.mytang0.brook.spi.config.ConfigProperties; +import xyz.mytang0.brook.spi.config.ConfigSource; +import xyz.mytang0.brook.spi.config.ConfigValidator; +import xyz.mytang0.brook.spi.config.Configurator; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + +import static xyz.mytang0.brook.common.utils.FieldUtils.setFieldValue; + +public class DefaultConfigurator implements Configurator { + + private static final Map, Optional> + INSTANCES = new ConcurrentHashMap<>(); + + @SuppressWarnings("unchecked") + @Override + public T getConfig(Class type) { + Optional optional = INSTANCES.get(type); + if (optional == null) { + optional = INSTANCES.computeIfAbsent(type, + __ -> Optional.ofNullable(bind(type))); + } + + return (T) optional.orElse(null); + } + + @Override + public T refreshConfig(Class type) { + INSTANCES.remove(type); + return getConfig(type); + } + + public T bind(Class type) { + if (Modifier.isInterface(type.getModifiers()) + || Modifier.isAbstract(type.getModifiers())) { + throw new IllegalArgumentException("Not instantiable!"); + } + + ConfigProperties annotation = + type.getAnnotation(ConfigProperties.class); + if (annotation == null) { + throw new IllegalArgumentException( + String.format("Missing @%s on class '%s'.", + ConfigProperties.class.getSimpleName(), + type.getName())); + } + + return bind(type, annotation.prefix(), annotation); + } + + @SuppressWarnings("unchecked") + private static T bind(Class type, String prefix, ConfigProperties annotation) { + + // Already sorted according to @Order. + List configSources = + ExtensionDirector + .getExtensionLoader(ConfigSource.class) + .getExtensionInstances(); + + AtomicReference instanceReference = new AtomicReference<>(); + + if (!configSources.isEmpty()) { + MethodUtils.getSetterMethods(type) + .forEach(setter -> { + Object value = getFieldValue(configSources, prefix, setter); + if (value != null) { + if (instanceReference.get() == null) { + instanceReference.set(newInstance(type)); + } + setFieldValue(setter, instanceReference.get(), value); + } + } + ); + } + + // Validity verification. + if (annotation != null) { + Class> validator = + (Class>) annotation.validator(); + if (!ConfigValidator.NULL.class.isAssignableFrom(validator)) { + Type generictype = validator.getGenericInterfaces()[0]; + if (generictype instanceof ParameterizedTypeImpl) { + generictype = ((ParameterizedTypeImpl) generictype) + .getActualTypeArguments()[0]; + if (generictype instanceof Class + && type.isAssignableFrom((Class) generictype)) { + validate(validator, instanceReference.get()); + } + } + } + } + + return instanceReference.get(); + } + + private static Object getFieldValue(List configSources, String prefix, Method setter) { + + String propertyName = extractPropertyName(setter); + if (propertyName == null) { + return null; + } + + Class type = setter.getParameterTypes()[0]; + + ConfigProperties annotation = + Optional.ofNullable(FieldUtils.getFieldByName( + setter.getDeclaringClass(), propertyName)) + .map(field -> field.getAnnotation(ConfigProperties.class)) + .orElse(null); + + Object value = null; + + if (annotation != null) { + prefix = getConfigKey(prefix, annotation.prefix()); + value = bind(type, prefix, annotation); + } else { + propertyName = getConfigKey(prefix, propertyName); + for (ConfigSource configSource : configSources) { + if ((value = configSource.getProperty(propertyName)) != null) { + value = convertPropertyValue(value, type); + } + } + + // Initialized from a collection with the same prefix. + if (value == null + && !ReflectUtils.isPrimitives(type) + && !ReflectUtils.isJdkClass(type)) { + + value = bind(type, propertyName, null); + } + } + + return value; + } + + private static String extractPropertyName(Method method) { + String methodName = method.getName(); + String propertyName = methodName.substring(3); + if (propertyName.isEmpty()) { + return null; + } + char[] chars = propertyName.toCharArray(); + chars[0] = Character.toLowerCase(chars[0]); + return new String(chars); + } + + private static Object convertPropertyValue(Object value, Class type) { + try { + return JsonUtils.convertValue(value, type); + } catch (IllegalArgumentException e) { + if (value instanceof String) { + return JsonUtils.readValue((String) value, type); + } + throw e; + } + } + + private static String getConfigKey(String prefix, String property) { + return prefix + Delimiter.DOT + property; + } + + private static void validate( + Class> validator, T target) { + + ConfigValidator instance = newInstance(validator); + + instance.validate(target); + } + + @SuppressWarnings("unchecked") + private static T newInstance(Class type) { + try { + return (T) type.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.Configurator b/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.Configurator new file mode 100644 index 0000000..dfb2126 --- /dev/null +++ b/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.Configurator @@ -0,0 +1 @@ +default=xyz.mytang0.brook.core.config.DefaultConfigurator \ No newline at end of file diff --git a/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java new file mode 100644 index 0000000..8e4816c --- /dev/null +++ b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java @@ -0,0 +1,288 @@ +package xyz.mytang0.brook.core.config; + +import lombok.Data; +import org.apache.commons.lang3.Validate; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import xyz.mytang0.brook.common.extension.ExtensionDirector; +import xyz.mytang0.brook.common.extension.ExtensionLoader; +import xyz.mytang0.brook.common.utils.JsonUtils; +import xyz.mytang0.brook.spi.config.ConfigProperties; +import xyz.mytang0.brook.spi.config.ConfigSource; +import xyz.mytang0.brook.spi.config.ConfigValidator; + +import javax.annotation.Nullable; +import java.time.Duration; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +public class DefaultConfiguratorTest { + + private final Map properties = new HashMap<>(); + + private DefaultConfigurator configurator; + + + @Before + public void setup() { + ExtensionLoader loader = + ExtensionDirector + .getExtensionLoader(ConfigSource.class); + + loader.addExtension("test", + TestConfigSource.class, + new TestConfigSource(properties)); + + configurator = new DefaultConfigurator(); + } + + @Test(expected = IllegalArgumentException.class) + public void testRefreshConfig1() { + configurator.refreshConfig(Interface.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testRefreshConfig2() { + configurator.refreshConfig(Abstract.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testRefreshConfig3() { + configurator.refreshConfig(Config1.class); + } + + @Test(expected = RuntimeException.class) + public void testRefreshConfig4() { + properties.put("config2.name", "Brook"); + configurator.refreshConfig(Config2.class); + } + + @Test(expected = RuntimeException.class) + public void testRefreshConfig5() { + properties.put("config3.name", "Brook"); + configurator.refreshConfig(Config3.class); + } + + @Test + public void testRefreshConfig6() { + properties.put("config4.name", "Brook"); + properties.put("config4.desc", "Brook is an orchestration engine, supports microservices and in-app logic (embedded use) orchestration."); + properties.put("config4.year", new GregorianCalendar().get(Calendar.YEAR) - 1900); + properties.put("config4.embeddable", "true"); + properties.put("config4.duration", "PT10S"); + Config4 config4 = configurator.refreshConfig(Config4.class); + Assert.assertNotNull(config4); + Assert.assertEquals(properties.get("config4.name"), config4.getName()); + Assert.assertEquals(properties.get("config4.desc"), config4.getDesc()); + Assert.assertEquals(properties.get("config4.year"), config4.getYear()); + Assert.assertEquals(Boolean.parseBoolean( + properties.get("config4.embeddable").toString() + ), config4.isEmbeddable()); + Assert.assertEquals('B', config4.getCharacter().charValue()); + Assert.assertEquals(properties.get("config4.duration"), config4.getDuration().toString()); + } + + @Test + public void testRefreshConfig7() { + properties.put("config5.name", "Brook"); + Config5 config5 = configurator.refreshConfig(Config5.class); + Assert.assertNotNull(config5); + Assert.assertEquals(properties.get("config5.name"), config5.getName()); + + Config6 config6 = config5.getConfig6(); + Assert.assertNull(config6); + + String inner = "object"; + Config6 origin = new Config6(); + origin.setInner(inner); + properties.put("config5.config6", JsonUtils.toJsonString(origin)); + + config5 = configurator.refreshConfig(Config5.class); + config6 = config5.getConfig6(); + Assert.assertNotNull(config6); + Assert.assertEquals(inner, config6.getInner()); + + // Contains escape characters. + properties.put("config5.config6", "{\"inner\":\"" + inner + "\"}"); + config5 = configurator.refreshConfig(Config5.class); + config6 = config5.getConfig6(); + Assert.assertNotNull(config6); + Assert.assertEquals(inner, config6.getInner()); + } + + @Test + public void testRefreshConfig8() { + properties.put("config7.name", "Brook"); + Config7 config7 = configurator.refreshConfig(Config7.class); + Assert.assertNotNull(config7); + Assert.assertEquals(properties.get("config7.name"), config7.getName()); + + Config6 config6 = config7.getConfig6(); + Assert.assertNull(config6); + + String inner = "object"; + Config6 origin = new Config6(); + origin.setInner(inner); + properties.put("config7.config6.inner", origin.getInner()); + + config7 = configurator.refreshConfig(Config7.class); + config6 = config7.getConfig6(); + Assert.assertNotNull(config6); + Assert.assertEquals(inner, config6.getInner()); + } + + @Test + public void testRefreshConfig9() { + properties.put("config8.name", "Brook"); + Config8 config8 = configurator.refreshConfig(Config8.class); + Assert.assertNotNull(config8); + Assert.assertEquals(properties.get("config8.name"), config8.getName()); + + Config6 config6 = config8.getConfig6(); + Assert.assertNull(config6); + + String inner = "object"; + Config6 origin = new Config6(); + origin.setInner(inner); + properties.put("config8.config.inner", origin.getInner()); + + config8 = configurator.refreshConfig(Config8.class); + config6 = config8.getConfig6(); + Assert.assertNotNull(config6); + Assert.assertEquals(inner, config6.getInner()); + } + + @Test + public void testGetConfig1() { + properties.put("config8.name", "Brook"); + Config8 config8 = configurator.getConfig(Config8.class); + Assert.assertNotNull(config8); + Assert.assertEquals(properties.get("config8.name"), config8.getName()); + + Config6 config6 = config8.getConfig6(); + Assert.assertNull(config6); + + String inner = "object"; + Config6 origin = new Config6(); + origin.setInner(inner); + properties.put("config8.config.inner", origin.getInner()); + + Config8 newConfig8 = configurator.getConfig(Config8.class); + config6 = newConfig8.getConfig6(); + Assert.assertNull(config6); + + Assert.assertEquals(config8, newConfig8); + } + + interface Interface { + + } + + abstract static class Abstract { + + } + + static class Config1 { + + } + + @Data + @ConfigProperties(prefix = "config2") + static class Config2 { + + private String name; + + private Config2() { + + } + } + + @Data + @ConfigProperties(prefix = "config3") + static class Config3 { + + private String name; + + public Config3(String s) { + + } + } + + @Data + @ConfigProperties(prefix = "config4", validator = Config4.Config4ConfigValidator.class) + static class Config4 { + + private String name; + + private String desc; + + private Integer year; + + private boolean embeddable; + + private Character character = 'B'; + + private Duration duration; + + static class Config4ConfigValidator implements ConfigValidator { + + @Override + public void validate(@Nullable Config4 target) { + Validate.notNull(target); + Validate.notBlank(target.getName()); + } + } + } + + @Data + @ConfigProperties(prefix = "config5") + static class Config5 { + + private String name; + + private Config6 config6; + } + + @Data + static class Config6 { + + private String inner; + } + + @Data + @ConfigProperties(prefix = "config7") + static class Config7 { + + private String name; + + private Config6 config6; + } + + @Data + @ConfigProperties(prefix = "config8") + static class Config8 { + + private String name; + + @ConfigProperties(prefix = "config") + private Config6 config6; + } + + static class TestConfigSource implements ConfigSource { + + private final Map properties; + + public TestConfigSource(Map properties) { + this.properties = properties; + } + + @Nullable + @Override + public Object getProperty(String key) { + return properties.get(key); + } + } +} \ No newline at end of file diff --git a/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigProperties.java b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigProperties.java new file mode 100644 index 0000000..f8f7ab7 --- /dev/null +++ b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigProperties.java @@ -0,0 +1,19 @@ +package xyz.mytang0.brook.spi.config; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ConfigProperties { + + String prefix(); + + Class> validator() + default ConfigValidator.NULL.class; +} diff --git a/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigSource.java b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigSource.java new file mode 100644 index 0000000..8e16500 --- /dev/null +++ b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigSource.java @@ -0,0 +1,12 @@ +package xyz.mytang0.brook.spi.config; + +import xyz.mytang0.brook.common.extension.SPI; + +import javax.annotation.Nullable; + +@SPI +public interface ConfigSource { + + @Nullable + Object getProperty(String key); +} diff --git a/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigValidator.java b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigValidator.java new file mode 100644 index 0000000..59ddf57 --- /dev/null +++ b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/ConfigValidator.java @@ -0,0 +1,17 @@ +package xyz.mytang0.brook.spi.config; + +import javax.annotation.Nullable; + +public interface ConfigValidator { + + void validate(@Nullable T target); + + + class NULL implements ConfigValidator { + + @Override + public void validate(@Nullable Object target) { + + } + } +} diff --git a/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/Configurator.java b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/Configurator.java new file mode 100644 index 0000000..5015cef --- /dev/null +++ b/brook-spi/src/main/java/xyz/mytang0/brook/spi/config/Configurator.java @@ -0,0 +1,11 @@ +package xyz.mytang0.brook.spi.config; + +import xyz.mytang0.brook.common.extension.SPI; + +@SPI(value = "default") +public interface Configurator { + + T getConfig(Class type); + + T refreshConfig(Class type); +} From 5b2203fbdc6fb8b4cc4f1e1a64567f705fb48d2e Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 13:38:52 +0800 Subject: [PATCH 2/6] Implement Env and Properties ConfigSource --- .../brook/core/config/EnvConfigSource.java | 20 +++++++++ .../core/config/PropertiesConfigSource.java | 45 +++++++++++++++++++ .../xyz.mytang0.brook.spi.config.ConfigSource | 2 + .../core/config/DefaultConfiguratorTest.java | 2 +- 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 brook-core/src/main/java/xyz/mytang0/brook/core/config/EnvConfigSource.java create mode 100644 brook-core/src/main/java/xyz/mytang0/brook/core/config/PropertiesConfigSource.java create mode 100644 brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.ConfigSource diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/EnvConfigSource.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/EnvConfigSource.java new file mode 100644 index 0000000..66887cf --- /dev/null +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/EnvConfigSource.java @@ -0,0 +1,20 @@ +package xyz.mytang0.brook.core.config; + +import xyz.mytang0.brook.common.annotation.Order; +import xyz.mytang0.brook.spi.config.ConfigSource; + +import javax.annotation.Nullable; + +@Order(Integer.MIN_VALUE) +public class EnvConfigSource implements ConfigSource { + + @Nullable + @Override + public Object getProperty(String key) { + Object value = System.getProperty(key); + if (value == null) { + value = System.getenv(key); + } + return value; + } +} diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/PropertiesConfigSource.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/PropertiesConfigSource.java new file mode 100644 index 0000000..1df38a8 --- /dev/null +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/PropertiesConfigSource.java @@ -0,0 +1,45 @@ +package xyz.mytang0.brook.core.config; + +import lombok.extern.slf4j.Slf4j; +import xyz.mytang0.brook.common.annotation.Order; +import xyz.mytang0.brook.spi.config.ConfigSource; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +@Slf4j +@Order(Integer.MIN_VALUE + 1) +public class PropertiesConfigSource implements ConfigSource { + + private static final String CONFIG_FILE_NAME = "brook.properties"; + + private volatile Properties properties; + + @Nullable + @Override + public Object getProperty(String key) { + loadProperties(); + return properties.getProperty(key); + } + + private void loadProperties() { + if (properties == null) { + synchronized (this) { + if (properties == null) { + properties = new Properties(); + try (InputStream inputStream = + ConfigSource.class.getClassLoader() + .getResourceAsStream(CONFIG_FILE_NAME)) { + if (inputStream != null) { + properties.load(inputStream); + } + } catch (IOException e) { + log.warn("Load " + CONFIG_FILE_NAME + " fail!", e); + } + } + } + } + } +} diff --git a/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.ConfigSource b/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.ConfigSource new file mode 100644 index 0000000..0ee3d4e --- /dev/null +++ b/brook-core/src/main/resources/META-INF/brook/xyz.mytang0.brook.spi.config.ConfigSource @@ -0,0 +1,2 @@ +env=xyz.mytang0.brook.core.config.EnvConfigSource +properties=xyz.mytang0.brook.core.config.PropertiesConfigSource \ No newline at end of file diff --git a/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java index 8e4816c..b6e336e 100644 --- a/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java +++ b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java @@ -158,7 +158,7 @@ public void testRefreshConfig9() { @Test public void testGetConfig1() { properties.put("config8.name", "Brook"); - Config8 config8 = configurator.getConfig(Config8.class); + Config8 config8 = configurator.refreshConfig(Config8.class); Assert.assertNotNull(config8); Assert.assertEquals(properties.get("config8.name"), config8.getName()); From 6e291c0ef7a284fc4fc77ef773f2cb736bd06e04 Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 15:03:35 +0800 Subject: [PATCH 3/6] Bugfix --- .../java/xyz/mytang0/brook/core/config/DefaultConfigurator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java index cadefe7..7af3c07 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java @@ -134,6 +134,7 @@ private static Object getFieldValue(List configSources, String pre for (ConfigSource configSource : configSources) { if ((value = configSource.getProperty(propertyName)) != null) { value = convertPropertyValue(value, type); + break; } } From 9b589a6a76a990a863cd403e6faf705a9516437d Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 15:31:19 +0800 Subject: [PATCH 4/6] Implement Spring ConfigSource --- .../SpringConfigSourceInitializer.java | 38 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 2 + 2 files changed, 40 insertions(+) create mode 100644 brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/SpringConfigSourceInitializer.java diff --git a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/SpringConfigSourceInitializer.java b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/SpringConfigSourceInitializer.java new file mode 100644 index 0000000..0ce1e8c --- /dev/null +++ b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/SpringConfigSourceInitializer.java @@ -0,0 +1,38 @@ +package xyz.mytang0.brook.spring.boot.autoconfigure; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import xyz.mytang0.brook.common.extension.ExtensionDirector; +import xyz.mytang0.brook.spi.config.ConfigSource; + +import javax.annotation.Nullable; +import java.util.Optional; + +public class SpringConfigSourceInitializer implements ConfigSource, EnvironmentPostProcessor, Ordered { + + private static final String NAME = "spring"; + + private volatile ConfigurableEnvironment environment; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + this.environment = environment; + ExtensionDirector.getExtensionLoader(ConfigSource.class) + .addExtension(NAME, SpringConfigSourceInitializer.class, this); + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Nullable + @Override + public Object getProperty(String key) { + return Optional.ofNullable(environment) + .map(__ -> __.getProperty(key, Object.class)) + .orElse(null); + } +} diff --git a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 47c8471..b48dcde 100644 --- a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,2 +1,4 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ xyz.mytang0.brook.spring.boot.autoconfigure.FlowAutoConfiguration +org.springframework.boot.env.EnvironmentPostProcessor=\ + xyz.mytang0.brook.spring.boot.autoconfigure.SpringConfigSourceInitializer From 4b15ed9a1c815872cdd14c87cad8b46940baa62a Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 16:21:52 +0800 Subject: [PATCH 5/6] Fix compilation warning --- .../xyz/mytang0/brook/core/config/DefaultConfigurator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java index 7af3c07..216dfcd 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java @@ -1,6 +1,5 @@ package xyz.mytang0.brook.core.config; -import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; import xyz.mytang0.brook.common.constants.Delimiter; import xyz.mytang0.brook.common.extension.ExtensionDirector; import xyz.mytang0.brook.common.utils.FieldUtils; @@ -14,6 +13,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; @@ -95,8 +95,8 @@ private static T bind(Class type, String prefix, ConfigProperties annotat (Class>) annotation.validator(); if (!ConfigValidator.NULL.class.isAssignableFrom(validator)) { Type generictype = validator.getGenericInterfaces()[0]; - if (generictype instanceof ParameterizedTypeImpl) { - generictype = ((ParameterizedTypeImpl) generictype) + if (generictype instanceof ParameterizedType) { + generictype = ((ParameterizedType) generictype) .getActualTypeArguments()[0]; if (generictype instanceof Class && type.isAssignableFrom((Class) generictype)) { From 54046dd9f56745656043723b54a1cc8d09f6089e Mon Sep 17 00:00:00 2001 From: mytang0 Date: Wed, 24 Apr 2024 17:04:42 +0800 Subject: [PATCH 6/6] Apply ConfigSource --- .../common/extension/ExtensionLoader.java | 6 +- .../xyz/mytang0/brook/core/FlowExecutor.java | 47 ++++++------ .../core/config/DefaultConfigurator.java | 44 ++++++----- .../core/execution/ExecutionProperties.java | 2 + .../brook/core/lock/LockProperties.java | 2 + .../core/metadata/MetadataProperties.java | 2 + .../monitor/DelayedTaskMonitorProperties.java | 2 + .../brook/core/queue/QueueProperties.java | 2 + .../brook/core/service/FlowLogService.java | 11 ++- .../core/config/DefaultConfiguratorTest.java | 6 +- .../controller/FlowMetadataController.java | 17 +++-- .../autoconfigure/FlowAutoConfiguration.java | 75 ++----------------- .../spring-configuration-metadata.json | 12 --- 13 files changed, 92 insertions(+), 136 deletions(-) diff --git a/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java b/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java index d741149..8b9bcd3 100644 --- a/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java +++ b/brook-common/src/main/java/xyz/mytang0/brook/common/extension/ExtensionLoader.java @@ -1,13 +1,13 @@ package xyz.mytang0.brook.common.extension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import xyz.mytang0.brook.common.annotation.OrderComparator; import xyz.mytang0.brook.common.extension.injector.ExtensionInjector; import xyz.mytang0.brook.common.extension.loading.LoadingStrategy; import xyz.mytang0.brook.common.utils.Holder; import xyz.mytang0.brook.common.utils.ReflectUtils; import xyz.mytang0.brook.common.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; @@ -15,13 +15,11 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; -import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.TreeSet; diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/FlowExecutor.java b/brook-core/src/main/java/xyz/mytang0/brook/core/FlowExecutor.java index 63407be..17a59ff 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/FlowExecutor.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/FlowExecutor.java @@ -1,5 +1,11 @@ package xyz.mytang0.brook.core; +import com.google.common.base.Joiner; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; import xyz.mytang0.brook.common.configuration.Configuration; import xyz.mytang0.brook.common.constants.Delimiter; import xyz.mytang0.brook.common.context.FlowContext; @@ -26,6 +32,7 @@ import xyz.mytang0.brook.core.exception.TerminateException; import xyz.mytang0.brook.core.execution.ExecutionProperties; import xyz.mytang0.brook.core.lock.FlowLockFacade; +import xyz.mytang0.brook.core.lock.LockProperties; import xyz.mytang0.brook.core.metadata.MetadataFacade; import xyz.mytang0.brook.core.metadata.MetadataProperties; import xyz.mytang0.brook.core.monitor.DelayedTaskMonitor; @@ -34,17 +41,12 @@ import xyz.mytang0.brook.spi.cache.FlowCache; import xyz.mytang0.brook.spi.cache.FlowCacheFactory; import xyz.mytang0.brook.spi.computing.EngineActuator; +import xyz.mytang0.brook.spi.config.Configurator; import xyz.mytang0.brook.spi.execution.ExecutionDAO; import xyz.mytang0.brook.spi.executor.ExecutorFactory; import xyz.mytang0.brook.spi.metadata.MetadataService; import xyz.mytang0.brook.spi.queue.QueueService; import xyz.mytang0.brook.spi.task.FlowTask; -import com.google.common.base.Joiner; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; import javax.validation.ValidationException; import java.util.ArrayList; @@ -64,6 +66,7 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +import static java.util.Objects.requireNonNull; import static xyz.mytang0.brook.core.constants.FlowConstants.DEFAULT_ENGINE_TYPE; import static xyz.mytang0.brook.core.constants.FlowConstants.DEFAULT_TIMEOUT_MS; import static xyz.mytang0.brook.core.constants.FlowConstants.LOCK_TRY_TIME_MS; @@ -72,7 +75,6 @@ import static xyz.mytang0.brook.core.exception.FlowErrorCode.FLOW_EXECUTION_ERROR; import static xyz.mytang0.brook.core.exception.FlowErrorCode.FLOW_NOT_EXIST; import static xyz.mytang0.brook.core.exception.FlowErrorCode.TASK_NOT_EXIST; -import static xyz.mytang0.brook.core.executor.ExecutorEnum.ASYNC_EXECUTOR; import static xyz.mytang0.brook.core.executor.ExecutorEnum.FLOW_STARTER; import static xyz.mytang0.brook.core.utils.ParameterUtils.flowContext; import static xyz.mytang0.brook.core.utils.ParameterUtils.getFlowInput; @@ -81,7 +83,6 @@ import static xyz.mytang0.brook.core.utils.ParameterUtils.getTaskInput; import static xyz.mytang0.brook.core.utils.ParameterUtils.getTaskOutput; import static xyz.mytang0.brook.core.utils.QueueUtils.getTaskDelayQueueName; -import static java.util.Objects.requireNonNull; @Slf4j public class FlowExecutor { @@ -96,8 +97,6 @@ public class FlowExecutor { private final ExecutorService flowStarter; - private final ExecutorService asyncExecutor; - private final FlowCacheFactory flowCacheFactory; private final FlowAspect flowAspect; @@ -111,17 +110,19 @@ public class FlowExecutor { private final DelayedTaskMonitorProperties delayedTaskMonitorProperties; - public FlowExecutor(FlowLockFacade flowLockFacade, - FlowTaskRegistry flowTaskRegistry, - QueueProperties queueProperties, - MetadataProperties metadataProperties, - ExecutionProperties executionProperties, - DelayedTaskMonitorProperties delayedTaskMonitorProperties) { - this.flowLockFacade = flowLockFacade; + public FlowExecutor(FlowTaskRegistry flowTaskRegistry) { + Configurator configurator = ExtensionDirector + .getExtensionLoader(Configurator.class) + .getDefaultExtension(); + this.flowLockFacade = new FlowLockFacade( + configurator.getConfig(LockProperties.class) + ); this.flowTaskRegistry = flowTaskRegistry; this.flowAspect = new FlowAspect(); this.taskAspect = new TaskAspect(); - this.metadataService = new MetadataFacade(metadataProperties); + this.metadataService = new MetadataFacade( + configurator.getConfig(MetadataProperties.class) + ); this.engineActuator = ExtensionDirector .getExtensionLoader(EngineActuator.class) .getDefaultExtension(); @@ -132,13 +133,9 @@ public FlowExecutor(FlowLockFacade flowLockFacade, .getExtensionLoader(ExecutorFactory.class) .getDefaultExtension() .getExecutor(FLOW_STARTER); - this.asyncExecutor = ExtensionDirector - .getExtensionLoader(ExecutorFactory.class) - .getDefaultExtension() - .getExecutor(ASYNC_EXECUTOR); - this.queueProperties = queueProperties; - this.executionProperties = executionProperties; - this.delayedTaskMonitorProperties = delayedTaskMonitorProperties; + this.queueProperties = configurator.getConfig(QueueProperties.class); + this.executionProperties = configurator.getConfig(ExecutionProperties.class); + this.delayedTaskMonitorProperties = configurator.getConfig(DelayedTaskMonitorProperties.class); DelayedTaskMonitor.init(this, flowLockFacade, delayedTaskMonitorProperties); } diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java index 216dfcd..2ea9924 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/config/DefaultConfigurator.java @@ -67,6 +67,31 @@ public T bind(Class type) { @SuppressWarnings("unchecked") private static T bind(Class type, String prefix, ConfigProperties annotation) { + T instance = Optional.ofNullable(bind(type, prefix)) + .orElseGet(() -> newInstance(type)); + + // Validity verification. + if (annotation != null) { + Class> validator = + (Class>) annotation.validator(); + if (!ConfigValidator.NULL.class.isAssignableFrom(validator)) { + Type generictype = validator.getGenericInterfaces()[0]; + if (generictype instanceof ParameterizedType) { + generictype = ((ParameterizedType) generictype) + .getActualTypeArguments()[0]; + if (generictype instanceof Class + && type.isAssignableFrom((Class) generictype)) { + validate(validator, instance); + } + } + } + } + + return instance; + } + + private static T bind(Class type, String prefix) { + // Already sorted according to @Order. List configSources = ExtensionDirector @@ -89,23 +114,6 @@ private static T bind(Class type, String prefix, ConfigProperties annotat ); } - // Validity verification. - if (annotation != null) { - Class> validator = - (Class>) annotation.validator(); - if (!ConfigValidator.NULL.class.isAssignableFrom(validator)) { - Type generictype = validator.getGenericInterfaces()[0]; - if (generictype instanceof ParameterizedType) { - generictype = ((ParameterizedType) generictype) - .getActualTypeArguments()[0]; - if (generictype instanceof Class - && type.isAssignableFrom((Class) generictype)) { - validate(validator, instanceReference.get()); - } - } - } - } - return instanceReference.get(); } @@ -143,7 +151,7 @@ private static Object getFieldValue(List configSources, String pre && !ReflectUtils.isPrimitives(type) && !ReflectUtils.isJdkClass(type)) { - value = bind(type, propertyName, null); + value = bind(type, propertyName); } } diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/execution/ExecutionProperties.java b/brook-core/src/main/java/xyz/mytang0/brook/core/execution/ExecutionProperties.java index f1a6f41..cd88559 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/execution/ExecutionProperties.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/execution/ExecutionProperties.java @@ -1,7 +1,9 @@ package xyz.mytang0.brook.core.execution; import lombok.Data; +import xyz.mytang0.brook.spi.config.ConfigProperties; +@ConfigProperties(prefix = "brook.execution-dao") @Data public class ExecutionProperties { diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/lock/LockProperties.java b/brook-core/src/main/java/xyz/mytang0/brook/core/lock/LockProperties.java index f4b70fa..bd16210 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/lock/LockProperties.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/lock/LockProperties.java @@ -1,9 +1,11 @@ package xyz.mytang0.brook.core.lock; import lombok.Data; +import xyz.mytang0.brook.spi.config.ConfigProperties; import java.time.Duration; +@ConfigProperties(prefix = "brook.lock") @Data public class LockProperties { diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/metadata/MetadataProperties.java b/brook-core/src/main/java/xyz/mytang0/brook/core/metadata/MetadataProperties.java index a0bd6f2..6ce6840 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/metadata/MetadataProperties.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/metadata/MetadataProperties.java @@ -1,7 +1,9 @@ package xyz.mytang0.brook.core.metadata; import lombok.Data; +import xyz.mytang0.brook.spi.config.ConfigProperties; +@ConfigProperties(prefix = "brook.metadata") @Data public class MetadataProperties { diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/monitor/DelayedTaskMonitorProperties.java b/brook-core/src/main/java/xyz/mytang0/brook/core/monitor/DelayedTaskMonitorProperties.java index e5f8ef7..87c9547 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/monitor/DelayedTaskMonitorProperties.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/monitor/DelayedTaskMonitorProperties.java @@ -1,9 +1,11 @@ package xyz.mytang0.brook.core.monitor; import lombok.Data; +import xyz.mytang0.brook.spi.config.ConfigProperties; import java.util.Set; +@ConfigProperties(prefix = "brook.delayed.task.monitor") @Data public class DelayedTaskMonitorProperties { diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/queue/QueueProperties.java b/brook-core/src/main/java/xyz/mytang0/brook/core/queue/QueueProperties.java index c200319..2da39f1 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/queue/QueueProperties.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/queue/QueueProperties.java @@ -2,7 +2,9 @@ import lombok.Data; import xyz.mytang0.brook.core.constants.FlowConstants; +import xyz.mytang0.brook.spi.config.ConfigProperties; +@ConfigProperties(prefix = "brook.queue") @Data public class QueueProperties { diff --git a/brook-core/src/main/java/xyz/mytang0/brook/core/service/FlowLogService.java b/brook-core/src/main/java/xyz/mytang0/brook/core/service/FlowLogService.java index 932ddf8..73bbf99 100644 --- a/brook-core/src/main/java/xyz/mytang0/brook/core/service/FlowLogService.java +++ b/brook-core/src/main/java/xyz/mytang0/brook/core/service/FlowLogService.java @@ -3,6 +3,9 @@ import lombok.Data; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; +import xyz.mytang0.brook.common.extension.ExtensionDirector; +import xyz.mytang0.brook.spi.config.ConfigProperties; +import xyz.mytang0.brook.spi.config.Configurator; import java.nio.file.Paths; @@ -12,8 +15,11 @@ public class FlowLogService { private final FlowLogProperties properties; - public FlowLogService(FlowLogProperties properties) { - this.properties = properties; + public FlowLogService() { + this.properties = ExtensionDirector + .getExtensionLoader(Configurator.class) + .getDefaultExtension() + .getConfig(FlowLogProperties.class); } public String getLog(String id) { @@ -21,6 +27,7 @@ public String getLog(String id) { + id + properties.getSuffix(); } + @ConfigProperties(prefix = "brook.log") @Data public static class FlowLogProperties { diff --git a/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java index b6e336e..98d7c07 100644 --- a/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java +++ b/brook-core/src/test/java/xyz/mytang0/brook/core/config/DefaultConfiguratorTest.java @@ -142,7 +142,7 @@ public void testRefreshConfig9() { Assert.assertEquals(properties.get("config8.name"), config8.getName()); Config6 config6 = config8.getConfig6(); - Assert.assertNull(config6); + Assert.assertNotNull(config6); String inner = "object"; Config6 origin = new Config6(); @@ -163,7 +163,7 @@ public void testGetConfig1() { Assert.assertEquals(properties.get("config8.name"), config8.getName()); Config6 config6 = config8.getConfig6(); - Assert.assertNull(config6); + Assert.assertNotNull(config6); String inner = "object"; Config6 origin = new Config6(); @@ -172,7 +172,7 @@ public void testGetConfig1() { Config8 newConfig8 = configurator.getConfig(Config8.class); config6 = newConfig8.getConfig6(); - Assert.assertNull(config6); + Assert.assertNotNull(config6); Assert.assertEquals(config8, newConfig8); } diff --git a/brook-demo/brook-demo-spring/src/main/java/xyz/mytang0/brook/demo/controller/FlowMetadataController.java b/brook-demo/brook-demo-spring/src/main/java/xyz/mytang0/brook/demo/controller/FlowMetadataController.java index 8417303..7d4822c 100644 --- a/brook-demo/brook-demo-spring/src/main/java/xyz/mytang0/brook/demo/controller/FlowMetadataController.java +++ b/brook-demo/brook-demo-spring/src/main/java/xyz/mytang0/brook/demo/controller/FlowMetadataController.java @@ -1,8 +1,5 @@ package xyz.mytang0.brook.demo.controller; -import xyz.mytang0.brook.common.metadata.definition.FlowDef; -import xyz.mytang0.brook.core.metadata.MetadataFacade; -import xyz.mytang0.brook.core.metadata.MetadataProperties; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -11,6 +8,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import xyz.mytang0.brook.common.extension.ExtensionDirector; +import xyz.mytang0.brook.common.metadata.definition.FlowDef; +import xyz.mytang0.brook.core.metadata.MetadataFacade; +import xyz.mytang0.brook.core.metadata.MetadataProperties; +import xyz.mytang0.brook.spi.config.Configurator; import javax.validation.Valid; @@ -20,8 +22,13 @@ public class FlowMetadataController { private final MetadataFacade metadataFacade; - public FlowMetadataController(MetadataProperties metadataProperties) { - this.metadataFacade = new MetadataFacade(metadataProperties); + public FlowMetadataController() { + this.metadataFacade = new MetadataFacade( + ExtensionDirector + .getExtensionLoader(Configurator.class) + .getDefaultExtension() + .getConfig(MetadataProperties.class) + ); } @PostMapping diff --git a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/FlowAutoConfiguration.java b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/FlowAutoConfiguration.java index 179ae4c..100c31d 100644 --- a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/FlowAutoConfiguration.java +++ b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/java/xyz/mytang0/brook/spring/boot/autoconfigure/FlowAutoConfiguration.java @@ -1,20 +1,13 @@ package xyz.mytang0.brook.spring.boot.autoconfigure; -import xyz.mytang0.brook.core.FlowExecutor; -import xyz.mytang0.brook.core.FlowTaskRegistry; -import xyz.mytang0.brook.core.execution.ExecutionProperties; -import xyz.mytang0.brook.core.lock.FlowLockFacade; -import xyz.mytang0.brook.core.lock.LockProperties; -import xyz.mytang0.brook.core.metadata.MetadataProperties; -import xyz.mytang0.brook.core.monitor.DelayedTaskMonitorProperties; -import xyz.mytang0.brook.core.queue.QueueProperties; -import xyz.mytang0.brook.core.service.FlowLogService; -import xyz.mytang0.brook.spi.task.FlowTask; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import xyz.mytang0.brook.core.FlowExecutor; +import xyz.mytang0.brook.core.FlowTaskRegistry; +import xyz.mytang0.brook.core.service.FlowLogService; +import xyz.mytang0.brook.spi.task.FlowTask; @Configuration @ComponentScan("xyz.mytang0.brook.spring.boot") @@ -22,49 +15,8 @@ public class FlowAutoConfiguration { @Bean - @ConfigurationProperties(prefix = "brook.lock") - public LockProperties flowLockProperties() { - return new LockProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "brook.log") - public FlowLogService.FlowLogProperties flowLogProperties() { - return new FlowLogService.FlowLogProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "brook.queue") - public QueueProperties queueProperties() { - return new QueueProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "brook.execution-dao") - public ExecutionProperties executionProperties() { - return new ExecutionProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "brook.metadata") - public MetadataProperties metadataProperties() { - return new MetadataProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "brook.delayed.task.monitor") - public DelayedTaskMonitorProperties delayedTaskMonitorProperties() { - return new DelayedTaskMonitorProperties(); - } - - @Bean - public FlowLockFacade flowLockFacade(LockProperties properties) { - return new FlowLockFacade(properties); - } - - @Bean - public FlowLogService flowLogService(FlowLogService.FlowLogProperties properties) { - return new FlowLogService(properties); + public FlowLogService flowLogService() { + return new FlowLogService(); } @Bean @@ -73,18 +25,7 @@ public FlowTaskRegistry flowTaskRegistry() { } @Bean - public FlowExecutor flowExecutor(FlowLockFacade flowLockFacade, - FlowTaskRegistry flowTaskRegistry, - QueueProperties queueProperties, - MetadataProperties metadataProperties, - ExecutionProperties executionProperties, - DelayedTaskMonitorProperties delayedTaskMonitorProperties) { - return new FlowExecutor<>( - flowLockFacade, - flowTaskRegistry, - queueProperties, - metadataProperties, - executionProperties, - delayedTaskMonitorProperties); + public FlowExecutor flowExecutor(FlowTaskRegistry flowTaskRegistry) { + return new FlowExecutor<>(flowTaskRegistry); } } diff --git a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json index 5fde066..26c61ff 100644 --- a/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/brook-spring-boot/brook-spring-boot-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json @@ -1,18 +1,6 @@ { "hints": [], "groups": [ - { - "sourceType": "xyz.mytang0.brook.spring.boot.autoconfigure.FlowAutoConfiguration", - "name": "brook.lock", - "sourceMethod": "flowLockProperties()", - "type": "xyz.mytang0.brook.core.lock.FlowLockFacade$LockProperties" - }, - { - "sourceType": "xyz.mytang0.brook.spring.boot.autoconfigure.FlowAutoConfiguration", - "name": "brook.log", - "sourceMethod": "flowLogProperties()", - "type": "xyz.mytang0.brook.core.service.FlowLogService$FlowLogProperties" - } ], "properties": [ {