diff --git a/pom.xml b/pom.xml index 53b03fa356a1f4951228f1f23a857a2456e971f7..6290330b3457f92ffba26d2a92e23f1959f789b9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.smartboot.flow smart-flow-parent - 1.1.2 + 1.1.3 4.0.0 pom smart-flow @@ -13,17 +13,16 @@ smart-flow-core - smart-flow-spring-extension smart-flow-manager smart-flow-script - smart-flow-springboot-starter smart-flow-helper smart-flow-admin smart-flow-plugin + smart-flow-integration - 1.1.2 + 1.1.3 https://gitee.com/smartboot/smart-flow diff --git a/smart-flow-admin/pom.xml b/smart-flow-admin/pom.xml index 85828cc18769b85ea2b9b805160e539fd49d57e7..023f141bf9789ddf452f9551c719dad16232ddb0 100644 --- a/smart-flow-admin/pom.xml +++ b/smart-flow-admin/pom.xml @@ -5,16 +5,17 @@ smart-flow-parent org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 - 1.1.2 + 1.1.3 smart-flow-admin 8 8 + UTF-8 diff --git a/smart-flow-admin/src/main/java/org/smartboot/smart/flow/admin/controller/WebUtils.java b/smart-flow-admin/src/main/java/org/smartboot/smart/flow/admin/controller/WebUtils.java index 01fc33c3eae65a494cc716019ef6097926784715..0809d91c4ec573634c5eeba4526da55d8c559ead 100644 --- a/smart-flow-admin/src/main/java/org/smartboot/smart/flow/admin/controller/WebUtils.java +++ b/smart-flow-admin/src/main/java/org/smartboot/smart/flow/admin/controller/WebUtils.java @@ -5,6 +5,7 @@ import org.smartboot.flow.core.exception.FlowException; import org.smartboot.flow.core.parser.DefaultParser; import org.smartboot.flow.core.util.AssertUtil; import org.smartboot.flow.helper.mock.FakeObjectCreator; +import org.smartboot.flow.helper.mock.FakeValueResolver; import java.io.ByteArrayInputStream; import java.net.URLDecoder; @@ -21,6 +22,7 @@ public final class WebUtils { public static FlowEngine parseValidate(String content, boolean decodeIfNecessary) { DefaultParser parser = new DefaultParser(); parser.setObjectCreator(new FakeObjectCreator()); + parser.setAttributeValueResolver(new FakeValueResolver()); try { if (decodeIfNecessary) { diff --git a/smart-flow-core/pom.xml b/smart-flow-core/pom.xml index 35b721c8dd621b7d3114c5b53dcfe1f2ba432155..f7cf83182d592189382c28187bb2a9f0cfe71ff9 100644 --- a/smart-flow-core/pom.xml +++ b/smart-flow-core/pom.xml @@ -5,7 +5,7 @@ org.smartboot.flow smart-flow-parent - 1.1.2 + 1.1.3 4.0.0 diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/EngineContextHelper.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/EngineContextHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..fb3864b2ce5285f3e2d84b31cfa4d41bf913a1c8 --- /dev/null +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/EngineContextHelper.java @@ -0,0 +1,39 @@ +package org.smartboot.flow.core; + +/** + * @author qinluo + * @date 2023-07-27 14:55:42 + * @since 1.1.3 + */ +@SuppressWarnings("rawtypes") +public class EngineContextHelper { + + private static final ThreadLocal HOLDER = new ThreadLocal<>(); + + public static void set(EngineContext ctx) { + HOLDER.set(ctx); + } + + public static EngineContext get() { + return HOLDER.get(); + } + + public static void remove() { + HOLDER.remove(); + } + + public static void broken() { + EngineContext ctx = get(); + if (ctx != null) { + ctx.broken(true); + } + } + + public static void brokenAll() { + EngineContext ctx = get(); + if (ctx != null) { + ctx.brokenAll(true); + } + } + +} diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/FlowEngine.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/FlowEngine.java index 5ee4d81a4f794b7cf16b405bc57dfa6db4bbf54f..530660e76cf1cb79cc8e8e73117a21c7e50775b7 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/FlowEngine.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/FlowEngine.java @@ -85,6 +85,7 @@ public class FlowEngine implements Describable, Validator, Measurable { } private void start(EngineContext context) { + EngineContextHelper.set(context); context.executedAt = System.currentTimeMillis(); context.listener.start(context); } @@ -92,6 +93,7 @@ public class FlowEngine implements Describable, Validator, Measurable { private void complete(EngineContext context) { context.completedAt = System.currentTimeMillis(); context.listener.completed(context); + EngineContextHelper.remove(); } protected void initContext(EngineContext context) { diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/attribute/Attributes.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/attribute/Attributes.java index ad293f74a0f53358f199860eeaff9db1e9309ba1..0290bdc7b50cd0a3d05436e602b0fe32c2cef3c8 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/attribute/Attributes.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/attribute/Attributes.java @@ -21,7 +21,6 @@ public enum Attributes { NAME("name", "组件名称", String.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setName((String) value); } }, @@ -29,7 +28,6 @@ public enum Attributes { ROLLBACK("rollback", "是否开启回滚", Boolean.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setRollback((Boolean) value); } }, @@ -37,7 +35,6 @@ public enum Attributes { DEGRADABLE("degradable", "是否开启降级", Boolean.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setDegradable((Boolean) value); } }, @@ -45,7 +42,6 @@ public enum Attributes { ASYNC("async", "是否开启异步", Boolean.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setAsync((Boolean) value); } }, @@ -53,7 +49,6 @@ public enum Attributes { TIMEOUT("timeout", "异步超时时间", Long.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setTimeout(((Number) value).longValue()); } }, @@ -61,7 +56,6 @@ public enum Attributes { DEPENDS_ON("dependsOn", "依赖的异步组件", List.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); //noinspection unchecked component.setDependsOn((List)value); } @@ -75,7 +69,6 @@ public enum Attributes { ENABLED("enabled", "启用开关", Boolean.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setEnabled((Boolean) value); } }, @@ -88,7 +81,6 @@ public enum Attributes { DEGRADE_CALLBACK("degrade-callback", "降级回调", DegradeCallback.class) { @Override public void apply(Component component, Object value) { - super.apply(component, value); component.setDegradeCallback((DegradeCallback) value); } }, @@ -140,12 +132,16 @@ public enum Attributes { return name; } + public Class getAccept() { + return accept; + } + public boolean accept(Object value) { return accept.isInstance(value); } public void apply(Component component, Object value) { - component.addAttribute(AttributeHolder.of(this, value)); + } public boolean isVisible() { diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/executable/Executable.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/executable/Executable.java index 0b7cffd03772e0dea5400222dff14cae2b1958d3..02384ac92daae6c7dd6520dcd88ef47095ab9d59 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/executable/Executable.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/executable/Executable.java @@ -3,6 +3,7 @@ package org.smartboot.flow.core.executable; import org.smartboot.flow.core.Describable; import org.smartboot.flow.core.EngineContext; +import org.smartboot.flow.core.EngineContextHelper; import org.smartboot.flow.core.Rollback; import org.smartboot.flow.core.visitor.ExecutableVisitor; @@ -30,4 +31,23 @@ public interface Executable extends Rollback, Describable { default void visit(ExecutableVisitor visitor) { visitor.visitSource(this); } + + + /** + * Broken current subprocess. + * + * @since 1.1.3 + */ + default void broken() { + EngineContextHelper.broken(); + } + + /** + * Broken whole process. + * + * @since 1.1.3 + */ + default void brokenAll() { + EngineContextHelper.brokenAll(); + } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/invoker/AsyncRunner.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/invoker/AsyncRunner.java index 842ce479951e339d10273e326aa4c491e3d24fa4..c02a484f2e256ac8530903a9835566eeb92e3d14 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/invoker/AsyncRunner.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/invoker/AsyncRunner.java @@ -1,5 +1,7 @@ package org.smartboot.flow.core.invoker; +import org.smartboot.flow.core.EngineContext; +import org.smartboot.flow.core.EngineContextHelper; import org.smartboot.flow.core.trace.Node; import org.smartboot.flow.core.trace.Tracer; @@ -10,15 +12,18 @@ import java.util.concurrent.Callable; * @date 2022-12-07 21:57:39 * @since 1.0.0 */ +@SuppressWarnings("rawtypes") public class AsyncRunner implements Callable { private final Callable task; private final Node root; private final long threadId; + private final EngineContext ctx; public AsyncRunner(Callable task) { this.task = task; this.root = Tracer.get(); + this.ctx = EngineContextHelper.get(); this.threadId = Thread.currentThread().getId(); } @@ -38,6 +43,7 @@ public class AsyncRunner implements Callable { if (tid != threadId) { Tracer.setNode(root); } + EngineContextHelper.set(ctx); } protected void doAfterRun() { @@ -45,5 +51,6 @@ public class AsyncRunner implements Callable { if (tid != threadId) { Tracer.remove(); } + EngineContextHelper.remove(); } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/ComponentModel.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/ComponentModel.java index 34cf89bdfced562bf765c08234f3366aaf4c2f48..8aef0c242217bfc7a427e241db75554e2f5030c8 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/ComponentModel.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/ComponentModel.java @@ -6,6 +6,7 @@ import org.smartboot.flow.core.common.Uniqueness; import org.smartboot.flow.core.attribute.AttributeHolder; import org.smartboot.flow.core.component.Component; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,6 +25,7 @@ public class ComponentModel extends Uniqueness { private final Map components = new ConcurrentHashMap<>(); private final ComponentType type; PipelineModel pipeline; + private List holders = new ArrayList<>(); ComponentModel(ComponentType type, String name) { this.name = name; @@ -31,6 +33,10 @@ public class ComponentModel extends Uniqueness { this.identifier = name; } + public void setHolders(List holders) { + this.holders = holders; + } + Map collect() { this.component.setName(name); if (type == ComponentType.SUBPROCESS) { @@ -57,13 +63,22 @@ public class ComponentModel extends Uniqueness { @SuppressWarnings("unchecked") public void changeAttributes(List holders) { AttributeValueResolver valueResolver = AttributeValueResolver.getInstance(); + List backup = new ArrayList<>(this.holders); + try { holders.forEach(p -> { Object resolvedValue = valueResolver.resolve(p.getAttribute(), p.getValue()); p.getAttribute().apply(component, resolvedValue); + // Remove and add new. + backup.removeIf(o -> p.getAttribute() == o.getAttribute()); + backup.add(p); }); + } catch (Exception ignored) { + } finally { + this.holders.clear(); + this.holders.addAll(backup); } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/DefaultEngineManager.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/DefaultEngineManager.java index d13f34aeef83a63016115549a48ca6a0c947a86e..49e7fa64d24c16279cb0bcb46419babcf6c9d69a 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/DefaultEngineManager.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/DefaultEngineManager.java @@ -23,17 +23,6 @@ public class DefaultEngineManager implements EngineManager { private final Map registeredEngines = new ConcurrentHashMap<>(); - /** - * Return singleton instance. - * Will remove at 1.1.0, please use {@link EngineManager#defaultManager()}. - * - * @return singleton instance. - */ - @Deprecated - public static EngineManager getDefaultManager() { - return INSTANCE; - } - /** * Rename getDefaultManager to getInstance. * diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/EngineManager.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/EngineManager.java index ec449bf292aa9c7f1a6e12ed69accbf7c74ce1e6..bd826c049cbd29977262e92456047813328f5873 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/EngineManager.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/EngineManager.java @@ -83,4 +83,22 @@ public interface EngineManager { static EngineManager defaultManager() { return DefaultEngineManager.getInstance(); } + + /* Static delegate methods */ + + /** + * @since 1.1.3 + * + * @param name engine name. + * @param request generic type + * @param response generic type + * @return engine + */ + static FlowEngine getEngine(String name) { + EngineModel model = DefaultEngineManager.getInstance().getEngineModel(name); + if (model != null) { + return model.getSource(); + } + return null; + } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/RegisteredComponentVisitor.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/RegisteredComponentVisitor.java index 2a9418b9ff0755d0f6bae240b8cb259d3144f373..ec5f85295a7faf8ec00f94b1fa627272dff28876 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/RegisteredComponentVisitor.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/manager/RegisteredComponentVisitor.java @@ -1,11 +1,13 @@ package org.smartboot.flow.core.manager; +import org.smartboot.flow.core.attribute.AttributeHolder; import org.smartboot.flow.core.common.ComponentType; import org.smartboot.flow.core.component.Component; import org.smartboot.flow.core.util.AuxiliaryUtils; import org.smartboot.flow.core.visitor.ComponentVisitor; import org.smartboot.flow.core.visitor.PipelineVisitor; +import java.util.List; import java.util.Set; /** @@ -66,4 +68,9 @@ public class RegisteredComponentVisitor extends ComponentVisitor { this.model.addComponent(model); return new RegisteredComponentVisitor(model, visited, allocator); } + + @Override + public void visitAttributes(List attributes) { + this.model.setHolders(attributes); + } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/BuilderDefinitionVisitor.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/BuilderDefinitionVisitor.java index 7a3f899c1e80ca0bd01ef64afcb0127352b4facf..a78492c408e1544ece00e3bb7113ec4f7f2e394a 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/BuilderDefinitionVisitor.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/BuilderDefinitionVisitor.java @@ -149,6 +149,7 @@ public class BuilderDefinitionVisitor implements DefinitionVisitor { this.collect(ed.getPipeline(), (pipelineComponent::setPipeline)); } pipelineComponent.setAttributeMap(ed.getAttributeMap()); + pipelineComponent.setAttributes(ed.getAttributes()); this.namedComponents.put(engineName, pipelineComponent); } @@ -192,6 +193,7 @@ public class BuilderDefinitionVisitor implements DefinitionVisitor { .withResolver(valueResolver) .apply(ed.getAttributes()) .build(); + component.setAttributes(ed.getAttributes()); component.setAttributeMap(ed.getAttributeMap()); namedComponents.put(ed.getIdentifier(), component); } @@ -252,6 +254,7 @@ public class BuilderDefinitionVisitor implements DefinitionVisitor { Component build = Builders.newIf().test(condition).withResolver(valueResolver) .apply(ed.getAttributes()).then(then).otherwise(elseBranch).build(); build.setAttributeMap(ed.getAttributeMap()); + build.setAttributes(ed.getAttributes()); this.namedComponents.put(ed.getIdentifier(), build); } @@ -310,6 +313,7 @@ public class BuilderDefinitionVisitor implements DefinitionVisitor { ChooseComponent build = chooseBuilder.build(); build.setAllBranchWasString(true); build.setAttributeMap(ed.getAttributeMap()); + build.setAttributes(ed.getAttributes()); this.namedComponents.put(ed.getIdentifier(), build); } @@ -331,6 +335,7 @@ public class BuilderDefinitionVisitor implements DefinitionVisitor { AdapterComponent adapterComponent = adapterBuilder.build(); adapterComponent.setAttributeMap(ed.getAttributeMap()); + adapterComponent.setAttributes(ed.getAttributes()); this.namedComponents.put(ed.getIdentifier(), adapterComponent); } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/ThreadPoolCreator.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/ThreadPoolCreator.java index 078d97bce3b4d74af53c44a18b9e63c0e5cc488f..3ac153f9d67d22e3775d960e8ebb212867540881 100644 --- a/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/ThreadPoolCreator.java +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/parser/ThreadPoolCreator.java @@ -43,7 +43,7 @@ public class ThreadPoolCreator { executor.setThreadFactory(new NamedThreadFactory(attr.getValue())); break; case "prestartAllCoreThreads": - prestartAllCoreThreads = true; + prestartAllCoreThreads = Boolean.parseBoolean(attr.getValue()); break; } } diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanContext.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanContext.java new file mode 100644 index 0000000000000000000000000000000000000000..84f616f7ff917a8d0ca6e04ed0fd580dff979868 --- /dev/null +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanContext.java @@ -0,0 +1,27 @@ +package org.smartboot.flow.core.util; + +import java.util.List; + +/** + * @author qinluo + * @date 2023-08-09 11:39:16 + * @since 1.1.3 + */ +public interface BeanContext { + + default T getBean(String name) { + throw new UnsupportedOperationException(); + } + + default T getBean(String name, Class type) { + throw new UnsupportedOperationException(); + } + + default List getBean(Class type) { + throw new UnsupportedOperationException(); + } + + default void init() { + BeanUtils.init(this); + } +} diff --git a/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanUtils.java b/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0b8b6a9347d5f64a3ad18925f7f98cdf3f995f6f --- /dev/null +++ b/smart-flow-core/src/main/java/org/smartboot/flow/core/util/BeanUtils.java @@ -0,0 +1,31 @@ +package org.smartboot.flow.core.util; + +import java.util.List; + +/** + * @author qinluo + * @date 2023-08-09 11:36:35 + * @since 1.1.3 + */ +public class BeanUtils { + + private static BeanContext instance = null; + + public static T getBean(String name) { + return instance.getBean(name); + } + + public static T getBean(String name, Class type) { + return instance.getBean(name, type); + } + + public static T getBean(Class type) { + List beans = instance.getBean(type); + return beans != null && beans.size() > 0 ? beans.get(0) : null; + } + + static void init(BeanContext ctx) { + instance = ctx; + } + +} diff --git a/smart-flow-helper/pom.xml b/smart-flow-helper/pom.xml index 3d8489ef2c784b0ffe84509ce22156fb5f4a1bef..23c8f4e1c760b4dd74fa06001f50470ec9d8f56c 100644 --- a/smart-flow-helper/pom.xml +++ b/smart-flow-helper/pom.xml @@ -5,7 +5,7 @@ smart-flow-parent org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 diff --git a/smart-flow-helper/src/main/java/org/smartboot/flow/helper/mock/FakeValueResolver.java b/smart-flow-helper/src/main/java/org/smartboot/flow/helper/mock/FakeValueResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..9e3f61541f54537ff5344bc262ade24fa8e4c6f9 --- /dev/null +++ b/smart-flow-helper/src/main/java/org/smartboot/flow/helper/mock/FakeValueResolver.java @@ -0,0 +1,39 @@ +package org.smartboot.flow.helper.mock; + +import org.smartboot.flow.core.attribute.AttributeValueResolver; +import org.smartboot.flow.core.attribute.Attributes; + +/** + * Fake value resolver + * + * @author qinluo + * @date 2023/1/27 12:35 + * @since 1.1.3 + */ +public class FakeValueResolver extends AttributeValueResolver { + + public FakeValueResolver() { + this.setObjectCreator(new FakeObjectCreator()); + } + + @Override + public Object resolve(Attributes attribute, Object value) { + try { + return super.resolve(attribute, value); + } catch (Exception ignored) { + + } + + // Miss parsed, as default value. + Class accepted = attribute.getAccept(); + if (accepted == String.class) { + return String.valueOf(value); + } else if (accepted == Long.class) { + return 0L; + } else if (accepted == Boolean.class) { + return false; + } else { + return null; + } + } +} diff --git a/smart-flow-integration/pom.xml b/smart-flow-integration/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..4b1f46d90d0b929d53fb3c16c03138d54ff71454 --- /dev/null +++ b/smart-flow-integration/pom.xml @@ -0,0 +1,26 @@ + + + + smart-flow-parent + org.smartboot.flow + 1.1.3 + + 4.0.0 + + smart-flow-integration + pom + + smart-flow-integration-nacos + smart-flow-spring-extension + smart-flow-springboot-starter + + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/smart-flow-integration/smart-flow-integration-nacos/pom.xml b/smart-flow-integration/smart-flow-integration-nacos/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..aca264249e1dbfd88b7a77d242eb263518b3ad78 --- /dev/null +++ b/smart-flow-integration/smart-flow-integration-nacos/pom.xml @@ -0,0 +1,41 @@ + + + + smart-flow-integration + org.smartboot.flow + 1.1.3 + + 4.0.0 + + smart-flow-integration-nacos + + + 8 + 8 + UTF-8 + + + + + org.smartboot.flow + smart-flow-manager + ${smart-flow.version} + + + + com.alibaba.nacos + nacos-client + 2.1.1 + + + + com.alibaba.nacos + nacos-spring-context + 1.1.1 + provided + + + + \ No newline at end of file diff --git a/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosConfiguration.java b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..c8a4b27e873e8e35179f2e0f8546d71151f2ebce --- /dev/null +++ b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosConfiguration.java @@ -0,0 +1,61 @@ +package org.smartboot.flow.integration.nacos; + +import com.alibaba.nacos.api.config.ConfigService; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author qinluo + * @date 2023-08-09 10:44:55 + * @since 1.1.3 + */ +public class NacosConfiguration { + + protected ConfigService configService; + + protected String dataId; + protected String engine; + protected String groupId = "DEFAULT_GROUP"; + protected Map nacosProperties = new HashMap<>(); + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public String getEngine() { + return engine; + } + + public void setEngine(String engine) { + this.engine = engine; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public Map getNacosProperties() { + return nacosProperties; + } + + public void setNacosProperties(Map nacosProperties) { + this.nacosProperties = nacosProperties; + } + + public ConfigService getConfigService() { + return configService; + } + + public void setConfigService(ConfigService configService) { + this.configService = configService; + } +} diff --git a/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosFlowUtil.java b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosFlowUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..d79610da4030c530878f8aca4c91cc84e2c99ca7 --- /dev/null +++ b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosFlowUtil.java @@ -0,0 +1,51 @@ +package org.smartboot.flow.integration.nacos; + +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.spring.beans.factory.annotation.ConfigServiceBeanBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.core.util.BeanUtils; + +import java.util.Map; +import java.util.Properties; + +/** + * @author qinluo + * @date 2023-08-09 14:09:03 + * @since 1.1.3 + */ +class NacosFlowUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosFlowUtil.class); + + static ConfigService createCfgService(Map properties) { + // 检查从bean上下文中是否能获取到configServiceFactory. + ConfigService cfgService = createWithBeanCtx(properties); + + try { + if (cfgService == null) { + Properties prop = new Properties(); + prop.putAll(properties); + return NacosFactory.createConfigService(prop); + } + } catch (Exception e) { + LOGGER.error("create nacos config service failed, properties = {}", properties, e); + } + + return cfgService; + } + + + private static ConfigService createWithBeanCtx(Map properties) { + + try { + ConfigServiceBeanBuilder beanBuilder = BeanUtils.getBean(ConfigServiceBeanBuilder.BEAN_NAME); + return beanBuilder.build(properties); + } catch (Throwable ignored) { + + } + + return null; + } +} diff --git a/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosWatcher.java b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosWatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..a7d522847768642938deb35f450b0ec12f392f80 --- /dev/null +++ b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosWatcher.java @@ -0,0 +1,85 @@ +package org.smartboot.flow.integration.nacos; + +import com.alibaba.nacos.api.config.listener.AbstractListener; +import com.alibaba.nacos.api.exception.NacosException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.core.util.AssertUtil; +import org.smartboot.flow.core.util.BeanUtils; +import org.smartboot.flow.manager.reload.MemoryXmlSelector; +import org.smartboot.flow.manager.reload.ReloadWatcher; +import org.smartboot.flow.manager.reload.Reloader; +import org.smartboot.flow.manager.reload.XmlParseReloader; + +import javax.annotation.PostConstruct; + +/** + * @author qinluo + * @date 2023-08-09 10:44:55 + * @since 1.1.3 + */ +public class NacosWatcher extends NacosConfiguration implements ReloadWatcher { + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosWatcher.class); + + private Reloader reloader = new XmlParseReloader(); + + private NacosXmlSelector notifier; + + /** + * For reflection. + */ + public NacosWatcher() { + } + + public NacosWatcher(NacosXmlSelector notifier) { + this.notifier = notifier; + } + + private void init() { + if (configService == null) { + configService = NacosFlowUtil.createCfgService(nacosProperties); + AssertUtil.notNull(configService, "nacos config service must not be null!"); + } + + if (reloader == null) { + reloader = BeanUtils.getBean(Reloader.class); + } + + if (reloader == null) { + XmlParseReloader r = new XmlParseReloader(); + r.setAssemble(true); + reloader = r; + } + } + + @PostConstruct + public void start() { + init(); + + try { + configService.addListener(dataId, groupId, new AbstractListener() { + @Override + public void receiveConfigInfo(String configInfo) { + if (notifier != null) { + notifier.notifyContentReceived(); + } + + MemoryXmlSelector.updateContent(engine, configInfo); + reloader.reload(engine); + } + }); + } catch (NacosException e) { + LOGGER.error("add nacos watcher failed, groupId = {}, dataId = {}, engine = {}", groupId, dataId, engine, e); + } + + } + + public Reloader getReloader() { + return reloader; + } + + public void setReloader(Reloader reloader) { + this.reloader = reloader; + } +} diff --git a/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosXmlSelector.java b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosXmlSelector.java new file mode 100644 index 0000000000000000000000000000000000000000..e25329570421f62ee7b45ca3717a39ce7455293c --- /dev/null +++ b/smart-flow-integration/smart-flow-integration-nacos/src/main/java/org/smartboot/flow/integration/nacos/NacosXmlSelector.java @@ -0,0 +1,74 @@ +package org.smartboot.flow.integration.nacos; + +import org.smartboot.flow.core.util.AssertUtil; +import org.smartboot.flow.manager.reload.ReloadWatcher; +import org.smartboot.flow.manager.reload.XmlSelector; + +import javax.annotation.PostConstruct; + +/** + * @author qinluo + * @date 2023-08-09 10:44:55 + * @since 1.1.3 + */ +public class NacosXmlSelector extends NacosConfiguration implements XmlSelector, ReloadWatcher { + + private boolean enableWatcher; + private boolean fetch = true; + private volatile boolean initialized = false; + private final NacosWatcher watcher = new NacosWatcher(this); + private volatile boolean enabledWatcher = false; + + @PostConstruct + public synchronized void init() { + if (initialized) { + return; + } + + if (configService == null) { + configService = NacosFlowUtil.createCfgService(nacosProperties); + AssertUtil.notNull(configService, "nacos config service must not be null!"); + } + + watcher.setConfigService(configService); + watcher.setEngine(engine); + watcher.setGroupId(groupId); + watcher.setNacosProperties(nacosProperties); + watcher.setDataId(dataId); + + initialized = true; + } + + @Override + public String select(String engineName) { + init(); + + String content = null; + + try { + if (fetch) { + content = configService.getConfig(dataId, groupId, 1000); + } + + if (enableWatcher && !enabledWatcher) { + watcher.start(); + enabledWatcher = true; + } + } catch (Exception ignored) { + + } + return content; + } + + public boolean getEnableWatcher() { + return enableWatcher; + } + + public void setEnableWatcher(boolean enableWatcher) { + this.enableWatcher = enableWatcher; + } + + void notifyContentReceived() { + this.fetch = false; + } +} diff --git a/smart-flow-spring-extension/pom.xml b/smart-flow-integration/smart-flow-spring-extension/pom.xml similarity index 90% rename from smart-flow-spring-extension/pom.xml rename to smart-flow-integration/smart-flow-spring-extension/pom.xml index 14ad1b038395ccc208d24039aa64681f2aa8e121..fb1a35e713cf17272a45522ee9621efb61b663d8 100644 --- a/smart-flow-spring-extension/pom.xml +++ b/smart-flow-integration/smart-flow-spring-extension/pom.xml @@ -3,9 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - smart-flow-parent + smart-flow-integration org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -15,6 +15,7 @@ 8 8 5.3.23 + UTF-8 diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionRegister.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionRegister.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionRegister.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionRegister.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java similarity index 98% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java index 1b305152ef82df5ba9d0b68bd38cf8cbf03d7371..f1d9b80fdc2a0fcffdd7cbcde719388156b1b5b1 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/BeanDefinitionVisitor.java @@ -1,7 +1,6 @@ package org.smartboot.flow.spring.extension; import org.smartboot.flow.core.attribute.AttributeHolder; -import org.smartboot.flow.core.attribute.AttributeValueResolver; import org.smartboot.flow.core.attribute.Attributes; import org.smartboot.flow.core.executable.DecorateExecutable; import org.smartboot.flow.core.parser.DefinitionVisitor; @@ -47,6 +46,8 @@ import java.util.stream.Collectors; */ public class BeanDefinitionVisitor implements DefinitionVisitor, BeanFactoryAware { + public static final String NAME = BeanDefinitionVisitor.class.getName(); + private ParserContext context; /** @@ -167,23 +168,15 @@ public class BeanDefinitionVisitor implements DefinitionVisitor, BeanFactoryAwar private void appendAttributes(ComponentDefinition ed, RootBeanDefinition definition) { List attributes = ed.getAttributes(); - AttributeValueResolver resolver = AttributeValueResolver.getInstance(); for (AttributeHolder holder : attributes) { Attributes attribute = holder.getAttribute(); - - try { - Object resolved = resolver.resolve(attribute, holder.getValue()); - holder.setValue(resolved); - } catch (Exception ignored) { - - } - if (attribute == Attributes.NAME || attribute == Attributes.DEGRADE_CALLBACK || !attribute.isVisible()) { continue; } + PropertyValue value = new PropertyValue(attribute.getName(), holder.getValue()); definition.getPropertyValues().addPropertyValue(value); } diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EnableReloadNotify.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EasySmartFlow.java similarity index 92% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EnableReloadNotify.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EasySmartFlow.java index 1b8ea79a729a66379bec6dc21207b5fb9405b712..f2b47a6720448e0860233245cd58a284ef849b63 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EnableReloadNotify.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EasySmartFlow.java @@ -17,5 +17,5 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(SmartFlowRegistrar.class) -public @interface EnableReloadNotify { +public @interface EasySmartFlow { } diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java similarity index 97% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java index 1cc239be58183a9a3190c04ef498fda04f6188d1..a10dbebe5b363f5bbf4a4ea89dcffaa1e53bb567 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/EngineInitializer.java @@ -6,6 +6,7 @@ import org.smartboot.flow.manager.NullReloader; import org.smartboot.flow.manager.reload.Reloader; import org.springframework.beans.factory.config.BeanPostProcessor; +import javax.annotation.PostConstruct; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -27,6 +28,7 @@ public class EngineInitializer implements BeanPostProcessor { */ private Reloader defaultReloader = NullReloader.NULL; + @PostConstruct public void start() { for (Map.Entry entry : engines.entrySet()) { Reloader reloader = entry.getValue(); diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NameAwareCondition.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NameAwareCondition.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NameAwareCondition.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NameAwareCondition.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NamedAbstractExecutable.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NamedAbstractExecutable.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NamedAbstractExecutable.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NamedAbstractExecutable.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java similarity index 85% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java index bbd464e51f7d36ca3ccd8e2ba8bd968d24782fad..0904b2d49c18a931ff830981571b9005992da161 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/NotifierProcessor.java @@ -8,7 +8,6 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.util.ReflectionUtils; import java.util.Arrays; @@ -23,6 +22,7 @@ import java.util.Map; public class NotifierProcessor implements BeanPostProcessor, BeanFactoryAware { private static final Logger LOGGER = LoggerFactory.getLogger(NotifierProcessor.class); + public static final String NAME = SmartFlowBeanFactoryRegistry.class.getName(); private ReflectionNotifier notifier; @@ -53,11 +53,7 @@ public class NotifierProcessor implements BeanPostProcessor, BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - if (beanFactory instanceof DefaultListableBeanFactory) { - ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(true); - notifier = new ReflectionNotifier(beanFactory); - notifier.register(); - } - + notifier = new ReflectionNotifier(beanFactory); + notifier.register(); } } diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ProxyParser.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ProxyParser.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ProxyParser.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ProxyParser.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java similarity index 78% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java index 4af2547386ce2e3b8cb77d02a9c10abdd24a0019..4e452895c5f3bc34b68f1e2965bfc467e31eca65 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReflectionNotifier.java @@ -1,8 +1,9 @@ package org.smartboot.flow.spring.extension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.smartboot.flow.core.FlowEngine; import org.smartboot.flow.core.manager.EngineManager; -import org.smartboot.flow.core.manager.EngineModel; import org.smartboot.flow.core.util.AuxiliaryUtils; import org.smartboot.flow.manager.reload.ReloadListener; import org.springframework.beans.factory.BeanFactory; @@ -21,6 +22,8 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class ReflectionNotifier implements ReloadListener { + private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionNotifier.class); + private final BeanFactory factory; private final List notifiers = new CopyOnWriteArrayList<>(); @@ -41,22 +44,17 @@ public class ReflectionNotifier implements ReloadListener { FlowEngine engineInstance = null; FlowEngine springEngine = null; - FlowEngine managerEngine = null; + FlowEngine managerEngine = EngineManager.getEngine(engineName); try { springEngine = (FlowEngine)factory.getBean(engineName); } catch (Exception ex) { // do-nothing } - EngineModel engineModel = EngineManager.defaultManager().getEngineModel(engineName); - if (engineModel != null) { - managerEngine = engineModel.getSource(); - } - if (springEngine == null ^ managerEngine == null) { engineInstance = AuxiliaryUtils.or(springEngine, managerEngine); } else if (springEngine != null) { - if (springEngine.getStartedAt() > managerEngine.getStartedAt()) { + if (springEngine.getStartedAt() >= managerEngine.getStartedAt()) { engineInstance = springEngine; } else if(springEngine.getStartedAt() < managerEngine.getStartedAt()){ engineInstance = managerEngine; @@ -98,6 +96,8 @@ public class ReflectionNotifier implements ReloadListener { if (FlowEngine.class.isAssignableFrom(f.getType())) { ReflectionUtils.setField(f, bean, engineInstance); + LOGGER.info("reload-notify engine {}({}) to field {}#{}", + engineName, engineInstance.getStartedAt(), f.getDeclaringClass().getSimpleName(), f.getName()); } else if ((Map.class.isAssignableFrom(f.getType()))) { Map engines = (Map)ReflectionUtils.getField(f, bean); if (engines == null) { @@ -107,6 +107,9 @@ public class ReflectionNotifier implements ReloadListener { Object o = engines.get(engineName); if (o instanceof FlowEngine) { engines.put(engineName, engineInstance); + + LOGGER.info("reload-notify engine {}({}) to field {}#{}", + engineName, engineInstance.getStartedAt(), f.getDeclaringClass().getSimpleName(), f.getName()); } } @@ -114,4 +117,14 @@ public class ReflectionNotifier implements ReloadListener { } } + + @Override + public boolean equals(Object obj) { + return obj instanceof ReflectionNotifier; + } + + @Override + public int hashCode() { + return ReflectionNotifier.class.hashCode(); + } } diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReloadNotify.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReloadNotify.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReloadNotify.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/ReloadNotify.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java similarity index 45% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java index 559dfd833e23ad51b4653a554f6fc996a5c8d643..2ab733f24458025e5895e26daea7a4dd70896a19 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowBeanFactoryRegistry.java @@ -1,10 +1,18 @@ package org.smartboot.flow.spring.extension; import org.smartboot.flow.core.parser.ParserContext; +import org.smartboot.flow.core.util.AuxiliaryUtils; +import org.smartboot.flow.manager.reload.XmlParseReloader; import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +import java.util.stream.Stream; /** * @author qinluo @@ -14,14 +22,33 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProce public class SmartFlowBeanFactoryRegistry implements BeanDefinitionRegistryPostProcessor { private BeanDefinitionRegistry registry; + public static final String NAME = SmartFlowBeanFactoryRegistry.class.getName(); @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { this.registry = registry; + SmartFlowRegistrar.registerAll(registry, NAME); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String[] beanNames = beanFactory.getBeanDefinitionNames(); + Stream.of(beanNames).forEach(p -> { + BeanDefinition beanDefinition = beanFactory.getBeanDefinition(p); + Class type = AuxiliaryUtils.asClass(beanDefinition.getBeanClassName()); + if (type != null && XmlParseReloader.class.isAssignableFrom(type)) { + PropertyValue visitor = beanDefinition.getPropertyValues().getPropertyValue("visitor"); + if (visitor == null) { + beanDefinition.getPropertyValues().addPropertyValue("visitor", new RuntimeBeanReference(BeanDefinitionVisitor.NAME)); + } + + PropertyValue creator = beanDefinition.getPropertyValues().getPropertyValue("objectCreator"); + if (creator == null) { + beanDefinition.getPropertyValues().addPropertyValue("objectCreator", new RuntimeBeanReference(SpringObjectCreator.NAME)); + } + } + }); + try { // Touch visit all parsed elements after all bean definition loaded. ParserContext ctx = ProxyParser.getInstance().getContext(); @@ -34,5 +61,9 @@ public class SmartFlowBeanFactoryRegistry implements BeanDefinitionRegistryPostP } finally { ProxyParser.getInstance().reset(); } + + if (beanFactory instanceof DefaultListableBeanFactory) { + ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(true); + } } } diff --git a/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java new file mode 100644 index 0000000000000000000000000000000000000000..58d17240732cb05b9e59c91250a2e5f4569482f1 --- /dev/null +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java @@ -0,0 +1,55 @@ +package org.smartboot.flow.spring.extension; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.manager.reload.XmlParseReloader; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author qinluo + * @date 2023/1/31 22:15 + * @since 1.0.0 + */ +public class SmartFlowRegistrar implements ImportBeanDefinitionRegistrar { + + private static final Logger LOGGER = LoggerFactory.getLogger(SmartFlowRegistrar.class); + + private static final Map> registeredClasses = new HashMap<>(); + + static { + registeredClasses.put(NotifierProcessor.NAME, NotifierProcessor.class); + registeredClasses.put(SmartFlowBeanFactoryRegistry.NAME, SmartFlowBeanFactoryRegistry.class); + registeredClasses.put(BeanDefinitionVisitor.NAME, BeanDefinitionVisitor.class); + registeredClasses.put(SpringObjectCreator.NAME, SpringObjectCreator.class); + registeredClasses.put(SpringBeanContextAdapter.NAME, SpringBeanContextAdapter.class); + registeredClasses.put(XmlParseReloader.class.getName(), XmlParseReloader.class); + } + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + registerAll(registry); + } + + public static void registerAll(BeanDefinitionRegistry registry, String ...excludes) { + List excludeBeans = excludes != null ? Arrays.asList(excludes) : Collections.emptyList(); + + registeredClasses.forEach((k, v) -> { + if (registry.containsBeanDefinition(k) || excludeBeans.contains(k)) { + return; + } + RootBeanDefinition definition = new RootBeanDefinition(); + definition.setBeanClass(v); + registry.registerBeanDefinition(k, definition); + LOGGER.info("register to spring container [{}]", k); + }); + } +} diff --git a/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringBeanContextAdapter.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringBeanContextAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..43526eb6ede599c7031e276646d610c50190a406 --- /dev/null +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringBeanContextAdapter.java @@ -0,0 +1,55 @@ +package org.smartboot.flow.spring.extension; + +import org.smartboot.flow.core.util.BeanContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.Ordered; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author qinluo + * @date 2022-12-21 14:22:23 + * @since 1.1.3 + */ +public class SpringBeanContextAdapter implements BeanContext, ApplicationContextAware, BeanPostProcessor, Ordered { + + public static final String NAME = SpringBeanContextAdapter.class.getName(); + + private ApplicationContext ctx; + + @Override + public T getBean(String name) { + return (T)ctx.getBean(name); + } + + @Override + public T getBean(String name, Class type) { + return ctx.getBean(name, type); + } + + @Override + public List getBean(Class type) { + String[] beanNamesForType = ctx.getBeanNamesForType(type); + List objects = new ArrayList<>(); + for (String name : beanNamesForType) { + objects.add(ctx.getBean(name, type)); + } + + return objects; + } + + @Override + public void setApplicationContext(ApplicationContext ctx) throws BeansException { + this.ctx = ctx; + this.init(); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringIdentifierManager.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringIdentifierManager.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringIdentifierManager.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringIdentifierManager.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringNamespaceHandler.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringNamespaceHandler.java similarity index 100% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringNamespaceHandler.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringNamespaceHandler.java diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java similarity index 93% rename from smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java rename to smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java index 242e1e354a2aeecf01bb3f65a3bb35475c4d36c2..ac0d3e067b0c286195df8a24d57b975824996277 100644 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java +++ b/smart-flow-integration/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SpringObjectCreator.java @@ -13,6 +13,8 @@ import org.springframework.context.ApplicationContextAware; */ public class SpringObjectCreator implements ObjectCreator, ApplicationContextAware { + public static final String NAME = SpringObjectCreator.class.getName(); + private ApplicationContext ctx; @Override diff --git a/smart-flow-spring-extension/src/main/resources/META-INF/spring.handlers b/smart-flow-integration/smart-flow-spring-extension/src/main/resources/META-INF/spring.handlers similarity index 100% rename from smart-flow-spring-extension/src/main/resources/META-INF/spring.handlers rename to smart-flow-integration/smart-flow-spring-extension/src/main/resources/META-INF/spring.handlers diff --git a/smart-flow-spring-extension/src/main/resources/META-INF/spring.schemas b/smart-flow-integration/smart-flow-spring-extension/src/main/resources/META-INF/spring.schemas similarity index 100% rename from smart-flow-spring-extension/src/main/resources/META-INF/spring.schemas rename to smart-flow-integration/smart-flow-spring-extension/src/main/resources/META-INF/spring.schemas diff --git a/smart-flow-springboot-starter/pom.xml b/smart-flow-integration/smart-flow-springboot-starter/pom.xml similarity index 86% rename from smart-flow-springboot-starter/pom.xml rename to smart-flow-integration/smart-flow-springboot-starter/pom.xml index e90b4f57e05151d46a898d3a80be750e3835c392..767f59a7d8a96d65ef996b0aadbfa7c26b41aba1 100644 --- a/smart-flow-springboot-starter/pom.xml +++ b/smart-flow-integration/smart-flow-springboot-starter/pom.xml @@ -3,9 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - smart-flow-parent + smart-flow-integration org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -14,6 +14,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowReloadConfiguration.java b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowDatabaseXmlSelectorConfiguration.java similarity index 45% rename from smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowReloadConfiguration.java rename to smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowDatabaseXmlSelectorConfiguration.java index fad3f1a86e686090e1c8e2d52c4840cde1584bdf..459710e534a42e5f7736d451fe907075b294f224 100644 --- a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowReloadConfiguration.java +++ b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowDatabaseXmlSelectorConfiguration.java @@ -1,17 +1,9 @@ package org.smartboot.flow.springboot.extension; -import org.smartboot.flow.core.parser.ObjectCreator; -import org.smartboot.flow.manager.reload.Reloader; import org.smartboot.flow.manager.reload.SqlXmlSelector; -import org.smartboot.flow.manager.reload.XmlParseReloader; import org.smartboot.flow.manager.reload.XmlSelector; -import org.smartboot.flow.spring.extension.BeanDefinitionVisitor; -import org.smartboot.flow.spring.extension.SpringObjectCreator; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -22,15 +14,9 @@ import org.springframework.context.annotation.Configuration; * @since 2022/12/15 16:32 */ @Configuration -@ConfigurationProperties(prefix = "smart.flow.manage.reload") -@ConditionalOnProperty(name = "smart.flow.manage.reload.enable", havingValue = "true") -public class FlowReloadConfiguration { - - - /** - * Assemble engine after reload. - */ - private boolean assemble; +@ConfigurationProperties(prefix = "smart.flow.selector") +@ConditionalOnProperty(name = "smart.flow.selector.datasource.url") +public class FlowDatabaseXmlSelectorConfiguration { /** * Selector datasource config. @@ -83,26 +69,7 @@ public class FlowReloadConfiguration { } } - - @ConditionalOnProperty(name = "smart.flow.manage.reload.spring-object-creator", havingValue = "true") - @ConditionalOnMissingBean(ObjectCreator.class) - @Bean("springObjectCreator") - public ObjectCreator getSpringObjectCreator(ApplicationContext ctx) { - SpringObjectCreator soc = new SpringObjectCreator(); - soc.setApplicationContext(ctx); - return soc; - } - - @ConditionalOnMissingBean(BeanDefinitionVisitor.class) - @Bean("beanDefVisitor") - public BeanDefinitionVisitor getVisitor(ApplicationContext ctx) { - BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(); - visitor.setBeanFactory(ctx); - return visitor; - } - - @ConditionalOnProperty(name = "smart.flow.manage.reload.datasource.url") - @Bean("xmlSelector") + @Bean("databaseXmlSelector") public XmlSelector getXmlSelector() { SqlXmlSelector selector = new SqlXmlSelector(); @@ -116,40 +83,6 @@ public class FlowReloadConfiguration { return selector; } - @Bean - @ConditionalOnBean(XmlSelector.class) - public Reloader getReloader(ApplicationContext ctx) { - XmlParseReloader reloader = new XmlParseReloader(); - reloader.setAssemble(assemble); - - try { - ObjectCreator creator = ctx.getBean(ObjectCreator.class); - reloader.setObjectCreator(creator); - } catch (Exception ignored) { - - } - - try { - XmlSelector selector = ctx.getBean(XmlSelector.class); - reloader.setXmlSelector(selector); - } catch (Exception ignored) { - - } - - try { - BeanDefinitionVisitor visitor = ctx.getBean(BeanDefinitionVisitor.class); - reloader.setVisitor(visitor); - } catch (Exception ignored) { - - } - - return reloader; - } - - public void setAssemble(boolean assemble) { - this.assemble = assemble; - } - public void setDatasource(DataSource dataSource) { this.datasource = dataSource; } diff --git a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManageConfiguration.java b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManagerConfiguration.java similarity index 32% rename from smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManageConfiguration.java rename to smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManagerConfiguration.java index c0198cd1d6f1d17028f3d19751a6559a613ada9d..b5a1a4e4de7e7280dd3181c49fa1ccbfa07ffb5e 100644 --- a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManageConfiguration.java +++ b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpManagerConfiguration.java @@ -1,79 +1,123 @@ package org.smartboot.flow.springboot.extension; +import org.smartboot.flow.core.util.AuxiliaryUtils; import org.smartboot.flow.manager.change.HttpManager; import org.smartboot.flow.manager.reload.Reloader; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.smartboot.flow.manager.reload.XmlParseReloader; +import org.smartboot.flow.manager.report.HttpReporter; +import org.smartboot.flow.manager.trace.HttpTraceReporter; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.Map; + /** * @author huqiang * @since 2022/12/14 19:15 */ @Configuration -@ConfigurationProperties(prefix = "smart.flow.manage.http") -@ConditionalOnProperty(name = "smart.flow.manage.http.url") -public class FlowHttpManageConfiguration { +@ConfigurationProperties(prefix = "smart.flow.manager") +@ConditionalOnProperty(name = "smart.flow.manager.server") +public class FlowHttpManagerConfiguration { + /* Common Server Configuration start */ /** * Connect timeout in microseconds. */ private long timeout; /** - * Manage request url. + * manager server address. */ - private String url; + private String server; /** * request idle in microseconds. */ - private long idle; + private long idle = 5000L; /** * First delay in microseconds. */ private long delayAtFirst; + private Map headers; + + /* Common Server Configuration end */ + + + /* Management Configuration */ + /** - * Configuration http manager without reloader. + * Management reloader's bean name. */ - @Bean(value = "smart-flow-http-manager", initMethod = "start") - @ConditionalOnMissingBean(Reloader.class) - public HttpManager getHttpManager(){ - HttpManager httpManager = new HttpManager(); - httpManager.setTimeout(timeout); - httpManager.setUrl(url); - httpManager.setIdle(idle); - httpManager.setDelayAtFirst(delayAtFirst); - return httpManager; + private String reloader; + + /* Manager bean definition start */ + + /** + * Configuration httpReporter. + * + * @return httpReporter definition. + */ + @ConditionalOnProperty(value = "smart.flow.manager.statistic.report", havingValue = "true") + @Bean(value = "smart-flow-http-reporter", initMethod = "start") + public HttpReporter getHttpReporter() { + HttpReporter reporter = new HttpReporter(); + reporter.setTimeout(this.timeout); + reporter.setServerAddress(this.server); + reporter.setIdle(this.idle); + reporter.setHeaders(headers); + return reporter; } /** - * Configuration http manager with reloader. + * Configuration http manager。 */ + @ConditionalOnProperty(value = "smart.flow.manager.management.enabled", havingValue = "true") @Bean(value = "smart-flow-http-manager", initMethod = "start") - @ConditionalOnBean(Reloader.class) - public HttpManager getHttpManager(Reloader reloader){ + public HttpManager getHttpManager(ApplicationContext ctx){ HttpManager httpManager = new HttpManager(); httpManager.setTimeout(timeout); - httpManager.setUrl(url); + httpManager.setUrl(server); httpManager.setIdle(idle); httpManager.setDelayAtFirst(delayAtFirst); - httpManager.setReloader(reloader); + httpManager.setHeaders(headers); + + if (AuxiliaryUtils.isBlank(reloader)) { + // not configured, use default reloader. + reloader = XmlParseReloader.class.getName(); + } + + Reloader reloaderBean = ctx.getBean(reloader, Reloader.class); + httpManager.setReloader(reloaderBean); return httpManager; } + /** + * Configuration httpTraceReporter. + */ + @ConditionalOnProperty(value = "smart.flow.manager.trace.http-report", havingValue = "true") + @Bean(value = "httpTraceReporter", initMethod = "init") + public HttpTraceReporter getHttpTraceReporter() { + HttpTraceReporter reporter = new HttpTraceReporter(); + reporter.setTimeout(this.timeout); + reporter.setServerAddress(this.server); + reporter.setHeaders(headers); + return reporter; + } + + /* Manager bean definition end */ public void setTimeout(long timeout) { this.timeout = timeout; } - public void setUrl(String url) { - this.url = url; + public void setServer(String server) { + this.server = server; } public void setIdle(long idle) { @@ -83,4 +127,12 @@ public class FlowHttpManageConfiguration { public void setDelayAtFirst(long delayAtFirst) { this.delayAtFirst = delayAtFirst; } + + public void setReloader(String reloader) { + this.reloader = reloader; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } } diff --git a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java similarity index 45% rename from smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java rename to smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java index 1f31f6584ed4fc5e88eda07d8fed7c59e946952c..bc51bfb4d7e60dcdee7750934624e87fb3145599 100644 --- a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java +++ b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowInitializerConfiguration.java @@ -1,12 +1,15 @@ package org.smartboot.flow.springboot.extension; +import org.smartboot.flow.core.util.AuxiliaryUtils; +import org.smartboot.flow.manager.reload.XmlParseReloader; +import org.smartboot.flow.manager.reload.XmlSelector; import org.smartboot.flow.spring.extension.EngineInitializer; import org.smartboot.flow.manager.reload.Reloader; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -19,22 +22,49 @@ import java.util.Arrays; * @since 2022/12/15 16:32 */ @Configuration -@ConfigurationProperties(prefix = "smart.flow.initialize") -@ConditionalOnProperty(name = "smart.flow.initialize.engines") -@AutoConfigureAfter(FlowReloadConfiguration.class) +@ConfigurationProperties(prefix = "smart.flow.initializer") +@ConditionalOnProperty(name = "smart.flow.initializer.engines") public class FlowInitializerConfiguration { /** * Initializer engines, multiple engine name split with , */ private String engines; + private String xmlSelector; + private String reloader; @Bean(value = "springboot-engine-initializer", initMethod = "start") @ConditionalOnBean(Reloader.class) @ConditionalOnMissingBean(EngineInitializer.class) - public EngineInitializer getInitializer(Reloader reloader) { + public EngineInitializer getInitializer(ApplicationContext ctx) { + boolean withSelector = false; + if (AuxiliaryUtils.isBlank(reloader)) { + // not configured, use default reloader. + reloader = XmlParseReloader.class.getName(); + withSelector = true; + } + + Reloader reloaderBean = ctx.getBean(reloader, Reloader.class); + + if (withSelector) { + XmlSelector selector = null; + + if (AuxiliaryUtils.isNotBlank(xmlSelector)) { + selector = ctx.getBean(xmlSelector, XmlSelector.class); + } + // DatabaseXmlSelector has configured + else if (ctx.containsBean("databaseXmlSelector")) { + selector = ctx.getBean("databaseXmlSelector", XmlSelector.class); + } + + if (selector != null) { + ((XmlParseReloader)reloaderBean).setXmlSelector(selector); + } + } + + EngineInitializer initializer = new EngineInitializer(); - initializer.setReloader(reloader); + initializer.setReloader(reloaderBean); initializer.setEngines(Arrays.asList(engines.split(","))); return initializer; } @@ -43,4 +73,12 @@ public class FlowInitializerConfiguration { public void setEngines(String engines) { this.engines = engines; } + + public void setXmlSelector(String xmlSelector) { + this.xmlSelector = xmlSelector; + } + + public void setReloader(String reloader) { + this.reloader = reloader; + } } diff --git a/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowTraceConfiguration.java b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowTraceConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..27b83b0c3d21fe4e9396c6bb3fcc48b948c39459 --- /dev/null +++ b/smart-flow-integration/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowTraceConfiguration.java @@ -0,0 +1,94 @@ +package org.smartboot.flow.springboot.extension; + +import org.smartboot.flow.core.parser.DefaultObjectCreator; +import org.smartboot.flow.core.util.AuxiliaryUtils; +import org.smartboot.flow.manager.trace.DefaultTraceCollector; +import org.smartboot.flow.manager.trace.LogTraceReporter; +import org.smartboot.flow.manager.trace.TraceReporter; +import org.smartboot.flow.manager.trace.TraceSampleStrategy; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.stream.Stream; + +/** + * @author huqiang + * @since 2022/12/14 19:15 + */ +@Configuration +@ConfigurationProperties(prefix = "smart.flow.manager.trace") +@ConditionalOnProperty(value = "smart.flow.manager.trace.enabled", havingValue = "true") +public class FlowTraceConfiguration { + + /** + * request idle in microseconds. + */ + private long idle = 5000L; + + /* Trace Collector and Reporter */ + + /** + * Trace radio. + */ + private double radio; + + /** + * sampleStrategy bean name. + */ + private String sampleStrategy; + + /** + * sampleStrategy class name. + */ + private String sampleStrategyClass; + + + @ConditionalOnProperty(value = "smart.flow.manager.trace.log-report", havingValue = "true") + @Bean(value = "logTraceReporter") + public LogTraceReporter getLogTraceReporter() { + return new LogTraceReporter(); + } + + @ConditionalOnProperty(value = "smart.flow.manager.trace.enabled", havingValue = "true") + @Bean(value = "defaultTraceCollector", initMethod = "start") + public DefaultTraceCollector getTraceCollector(ApplicationContext ctx){ + DefaultTraceCollector collector = new DefaultTraceCollector(); + collector.setIdle(idle); + collector.setRadio(radio); + + String[] traceReporterNames = ctx.getBeanNamesForType(TraceReporter.class); + Stream.of(traceReporterNames).forEach(p -> collector.addReporter(ctx.getBean(p, TraceReporter.class))); + + if (AuxiliaryUtils.isNotBlank(sampleStrategy)) { + collector.setSampleStrategy(ctx.getBean(sampleStrategy, TraceSampleStrategy.class)); + } + // Create strategy with classname. + else if (AuxiliaryUtils.asClass(sampleStrategyClass) != null) { + TraceSampleStrategy strategy = DefaultObjectCreator.getInstance().create(sampleStrategyClass, TraceSampleStrategy.class, false); + collector.setSampleStrategy(strategy); + } + + return collector; + } + + /* Manager bean definition end */ + + public void setIdle(long idle) { + this.idle = idle; + } + + public void setRadio(double radio) { + this.radio = radio; + } + + public void setSampleStrategy(String sampleStrategy) { + this.sampleStrategy = sampleStrategy; + } + + public void setSampleStrategyClass(String sampleStrategyClass) { + this.sampleStrategyClass = sampleStrategyClass; + } +} diff --git a/smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories b/smart-flow-integration/smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories similarity index 37% rename from smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories rename to smart-flow-integration/smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories index 0fe6437f29294d9aba75644c80d0e2aac6a72eae..3ffcb6d1ecf6bf576bcdb3f9278acc755d055512 100644 --- a/smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories +++ b/smart-flow-integration/smart-flow-springboot-starter/src/main/resources/META-INF/spring.factories @@ -1,5 +1,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - org.smartboot.flow.springboot.extension.FlowHttpManageConfiguration,\ - org.smartboot.flow.springboot.extension.FlowHttpReportConfiguration,\ - org.smartboot.flow.springboot.extension.FlowReloadConfiguration,\ + org.smartboot.flow.springboot.extension.FlowHttpManagerConfiguration,\ + org.smartboot.flow.springboot.extension.FlowDatabaseXmlSelectorConfiguration,\ + org.smartboot.flow.springboot.extension.FlowTraceConfiguration,\ org.smartboot.flow.springboot.extension.FlowInitializerConfiguration \ No newline at end of file diff --git a/smart-flow-manager/pom.xml b/smart-flow-manager/pom.xml index db7aa9c4e811218a50b31a5ce4cc49c3d2e454f6..1247b5d0a48bc692733cfb1ea781ccc9e02e91ad 100644 --- a/smart-flow-manager/pom.xml +++ b/smart-flow-manager/pom.xml @@ -5,7 +5,7 @@ smart-flow-parent org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -14,6 +14,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/MemoryXmlSelector.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/MemoryXmlSelector.java new file mode 100644 index 0000000000000000000000000000000000000000..b509c6431fd52260ca00161480ffecdb5d57b9dc --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/MemoryXmlSelector.java @@ -0,0 +1,35 @@ +package org.smartboot.flow.manager.reload; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author qinluo + * @date 2022-12-21 16:36:25 + * @since 1.1.3 + */ +public class MemoryXmlSelector implements XmlSelector { + + private static final Map contentMap = new ConcurrentHashMap<>(); + static XmlSelector INSTANCE = new MemoryXmlSelector(); + + private MemoryXmlSelector() { + + } + + @Override + public String select(String engineName) { + return contentMap.get(engineName); + } + + /* + Static methods. + */ + public static void updateContent(String engine, String content) { + contentMap.put(engine, content); + } + + public static String remove(String engine) { + return contentMap.remove(engine); + } +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/ReloadWatcher.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/ReloadWatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..3e9a47f5cee701c318c84641b9c9be3ea81922e3 --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/ReloadWatcher.java @@ -0,0 +1,11 @@ +package org.smartboot.flow.manager.reload; + +/** + * ReloadWatcher Mark interface. + * + * @author qinluo + * @date 2023-08-09 18:17:34 + * @since 1.1.3 + */ +public interface ReloadWatcher { +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/XmlParseReloader.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/XmlParseReloader.java index b04a40434d2382df9f6365b8feb5122627b80718..44a75037f4bbe43455a3d01c85804888c2f0592d 100644 --- a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/XmlParseReloader.java +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/reload/XmlParseReloader.java @@ -7,6 +7,7 @@ import org.smartboot.flow.core.parser.DefaultParser; import org.smartboot.flow.core.parser.DefinitionVisitor; import org.smartboot.flow.core.parser.ObjectCreator; import org.smartboot.flow.core.parser.ParserContext; +import org.smartboot.flow.core.util.AssertUtil; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -24,6 +25,7 @@ public class XmlParseReloader extends AbstractReloader { protected boolean assemble; protected DefinitionVisitor visitor; private XmlSelector xmlSelector; + private final XmlSelector memoryXmlSelector = MemoryXmlSelector.INSTANCE; public void setXmlSelector(XmlSelector xmlSelector) { this.xmlSelector = xmlSelector; @@ -43,8 +45,19 @@ public class XmlParseReloader extends AbstractReloader { @Override public void doReload(String engineName) { + XmlSelector selector = xmlSelector; + if (selector == null) { + selector = memoryXmlSelector; + } + + AssertUtil.notNull(selector, "selector must not be null!"); + // select config. - String xml = xmlSelector.select(engineName); + String xml = selector.select(engineName); + if (xml == null || xml.trim().length() == 0) { + xml = memoryXmlSelector.select(engineName); + } + if (xml == null || xml.trim().length() == 0) { throw new FlowException("load config " + engineName + " is empty"); } diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/DefaultTraceCollector.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/DefaultTraceCollector.java new file mode 100644 index 0000000000000000000000000000000000000000..d33eed95bca5606172d1c23a2a59077d647f7fbc --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/DefaultTraceCollector.java @@ -0,0 +1,124 @@ +package org.smartboot.flow.manager.trace; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.core.ExecutionListenerRegistry; +import org.smartboot.flow.core.util.AssertUtil; +import org.smartboot.flow.manager.NamedThreadFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author qinluo + * @date 2023-02-07 + * @since 1.0.7 + */ +public class DefaultTraceCollector implements TraceCollector { + + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTraceCollector.class); + private final ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("export-trace")); + + /** + * Report idle in mills. + */ + protected long idle = 5000L; + private Double radio; + private TraceSampleStrategy sampleStrategy; + private ManagerExecutionListener executionListener; + + private final BlockingQueue traceQueue = new ArrayBlockingQueue<>(20000); + private final List reporters = new ArrayList<>(8); + + public long getIdle() { + return idle; + } + + public void setIdle(long idle) { + AssertUtil.isTrue(idle > 0, "idle must great than zero"); + this.idle = idle; + } + + public void addReporter(TraceReporter reporter) { + reporters.add(reporter); + } + + public void removeReporter(TraceReporter reporter) { + reporters.remove(reporter); + } + + public void removeAll() { + reporters.clear(); + } + + public void setReporters(List reporters) { + this.reporters.addAll(reporters); + } + + public void export() { + try { + this.doExport(); + } catch (Throwable ex){ + LOGGER.error("report trace failed", ex); + } + } + + public void doExport() { + List traces = new ArrayList<>(); + if (traceQueue.drainTo(traces) < 0) { + return; + } + + for (TraceData trace : traces) { + for (TraceReporter reporter : reporters) { + reporter.report(trace); + } + + } + } + + public void start() { + // Register listener. + if (sampleStrategy == null && radio != null && radio > 0 && radio <= 1) { + sampleStrategy = new TraceSampleStrategy(); + sampleStrategy.setRadio(radio); + } + + executionListener = new ManagerExecutionListener(this, sampleStrategy); + ExecutionListenerRegistry.register(executionListener); + executorService.setMaximumPoolSize(1); + executorService.scheduleAtFixedRate(this::export, idle, idle, TimeUnit.MILLISECONDS); + } + + @Override + public void submit(TraceData item) { + //noinspection ResultOfMethodCallIgnored + traceQueue.offer(item); + } + + public Double getRadio() { + return radio; + } + + public void setRadio(Double radio) { + this.radio = radio; + if (sampleStrategy != null && radio != null && radio > 0 && radio <= 1) { + sampleStrategy.setRadio(radio); + } + } + + public TraceSampleStrategy getSampleStrategy() { + return sampleStrategy; + } + + public void setSampleStrategy(TraceSampleStrategy sampleStrategy) { + this.sampleStrategy = sampleStrategy; + if (this.executionListener != null) { + this.executionListener.setSampleStrategy(this.sampleStrategy); + } + } +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/HttpTraceReporter.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/HttpTraceReporter.java new file mode 100644 index 0000000000000000000000000000000000000000..7dad8b2bdf73c9418bb8737f546f2026c88988ab --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/HttpTraceReporter.java @@ -0,0 +1,107 @@ +package org.smartboot.flow.manager.trace; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.core.FlowEngine; +import org.smartboot.flow.core.manager.EngineManager; +import org.smartboot.flow.manager.ManagerConstants; +import org.smartboot.flow.manager.UpdateContentTask; +import org.smartboot.http.client.HttpClient; +import org.smartboot.http.client.HttpPost; +import org.smartboot.http.common.enums.HeaderNameEnum; + +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * @author qinluo + * @date 2023-02-07 + * @since 1.1.3 + */ +public class HttpTraceReporter implements TraceReporter { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpTraceReporter.class); + + /** + * 服务端地址 + */ + private String serverAddress; + + /** + * 超时时间 + */ + private long timeout; + private String host; + private int port; + + private Map headers; + + @Override + public void report(TraceData trace) { + EngineManager defaultManager = EngineManager.defaultManager(); + + HttpClient httpClient = new HttpClient(host, port); + httpClient.configuration().connectTimeout((int) timeout); + HttpPost post = httpClient.post(ManagerConstants.REPORT_TRACE); + + if (headers != null) { + headers.forEach((key, value) -> post.header().add(key, value)); + } + + FlowEngine source = defaultManager.getEngineModel(trace.getEngineName()).getSource(); + TraceReportRequest request = TraceRequestConverter.convert(trace, source); + + String json = JSON.toJSONString(request, SerializerFeature.WriteEnumUsingToString); + byte[] bytes = json.getBytes(StandardCharsets.UTF_8); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("report trace data, engine = {}, data = {}", trace.getEngineName(), JSON.toJSONString(request)); + } + + post.header().add(HeaderNameEnum.CONTENT_TYPE.getName(), "application/json;charset=UTF-8").add(HeaderNameEnum.CONTENT_LENGTH.getName(), String.valueOf(bytes.length)); + + // Use body stream write. + post.body().write(bytes, 0, bytes.length).done() + .onSuccess(httpResponse -> LOGGER.info("send trace success")) + .onFailure(throwable -> LOGGER.error("send trace failed", throwable)); + } + + public void init() { + URL parsedUrl; + try { + parsedUrl = new URL(serverAddress); + } catch (Exception e) { + throw new IllegalStateException("invalid url " + serverAddress, e); + } + this.host = parsedUrl.getHost(); + this.port = parsedUrl.getPort(); + UpdateContentTask.startTask(host, port); + } + + public String getServerAddress() { + return serverAddress; + } + + public void setServerAddress(String serverAddress) { + this.serverAddress = serverAddress; + } + + public long getTimeout() { + return timeout; + } + + public void setTimeout(long timeout) { + this.timeout = timeout; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/LogTraceReporter.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/LogTraceReporter.java new file mode 100644 index 0000000000000000000000000000000000000000..d035e9dd3cab67d2707a21d07c2b168f2f5ef450 --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/LogTraceReporter.java @@ -0,0 +1,27 @@ +package org.smartboot.flow.manager.trace; + +import com.alibaba.fastjson.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.smartboot.flow.core.FlowEngine; +import org.smartboot.flow.core.manager.EngineManager; + +/** + * @author qinluo + * @date 2023-02-07 + * @since 1.1.3 + */ +public class LogTraceReporter implements TraceReporter { + + private static final Logger LOGGER = LoggerFactory.getLogger(LogTraceReporter.class); + + @Override + public void report(TraceData trace) { + EngineManager defaultManager = EngineManager.defaultManager(); + + FlowEngine source = defaultManager.getEngineModel(trace.getEngineName()).getSource(); + TraceReportRequest request = TraceRequestConverter.convert(trace, source); + + LOGGER.info("{}", JSON.toJSONString(request)); + } +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/ManagerExecutionListener.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/ManagerExecutionListener.java index 8da105593227f4daba290f62137547e607078fef..48e12e9d4ac449fa3cfb65e1bee0897f2367c9f0 100644 --- a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/ManagerExecutionListener.java +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/ManagerExecutionListener.java @@ -20,11 +20,11 @@ public class ManagerExecutionListener implements ExecutionListener { * Invoke trace in engine invoking. */ private static final Key TRACES = Key.of("traces"); - private final TraceReporter traceReporter; + private final TraceCollector traceCollector; private TraceSampleStrategy sampleStrategy; - public ManagerExecutionListener(TraceReporter traceReporter, TraceSampleStrategy sampleStrategy) { - this.traceReporter = traceReporter; + public ManagerExecutionListener(TraceCollector traceCollector, TraceSampleStrategy sampleStrategy) { + this.traceCollector = traceCollector; this.sampleStrategy = sampleStrategy; } @@ -135,6 +135,6 @@ public class ManagerExecutionListener implements ExecutionListener { } // 将执行采集到的数据进行上报 - traceReporter.submit(trace); + traceCollector.submit(trace); } } diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceCollector.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceCollector.java new file mode 100644 index 0000000000000000000000000000000000000000..cdf80b5c9bdd27d2853e02f751e095bd95baf8e5 --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceCollector.java @@ -0,0 +1,16 @@ +package org.smartboot.flow.manager.trace; + +/** + * @author qinluo + * @date 2023-02-07 + * @since 1.1.3 + */ +public interface TraceCollector { + + /** + * Submit trace data to TraceCollector. + * + * @param traceData traceData. + */ + void submit(TraceData traceData); +} diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceReporter.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceReporter.java index 97483695bbb5d9892d30c240ab800f7d6bc17011..0bb02d1ef467dbaf308a9599c013d34665bac313 100644 --- a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceReporter.java +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceReporter.java @@ -1,257 +1,16 @@ package org.smartboot.flow.manager.trace; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.serializer.SerializerFeature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.smartboot.flow.core.ExecutionListenerRegistry; -import org.smartboot.flow.core.manager.EngineManager; -import org.smartboot.flow.core.util.AssertUtil; -import org.smartboot.flow.manager.FlatEngine; -import org.smartboot.flow.manager.FlatManager; -import org.smartboot.flow.manager.HostUtils; -import org.smartboot.flow.manager.ManagerConfiguration; -import org.smartboot.flow.manager.ManagerConstants; -import org.smartboot.flow.manager.NamedThreadFactory; -import org.smartboot.flow.manager.UpdateContentTask; -import org.smartboot.http.client.HttpClient; -import org.smartboot.http.client.HttpPost; -import org.smartboot.http.common.enums.HeaderNameEnum; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** * @author qinluo - * @date 2023-02-07 - * @since 1.0.7 + * @date 2023-08-02 09:13:20 + * @since 1.1.3 */ -public class TraceReporter { - - private static final Logger LOGGER = LoggerFactory.getLogger(TraceReporter.class); - private final ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("export-trace")); - - /** - * Report idle in mills. - */ - protected long idle = 5000L; +public interface TraceReporter { /** - * 服务端地址 + * Report trace record. + * + * @param trace trace. */ - private String serverAddress; - - /** - * 超时时间 - */ - private long timeout; - private String host; - private int port; - private Double radio; - private TraceSampleStrategy sampleStrategy; - private ManagerExecutionListener executionListener; - - private Map headers; - private final BlockingQueue traceQueue = new ArrayBlockingQueue<>(20000); - - public long getIdle() { - return idle; - } - - public void setIdle(long idle) { - AssertUtil.isTrue(idle > 0, "idle must great than zero"); - this.idle = idle; - } - - public void export() { - try { - this.doExport(); - } catch (Throwable ex){ - LOGGER.error("report trace failed", ex); - } - } - - public void doExport() { - List traces = new ArrayList<>(); - if (traceQueue.drainTo(traces) < 0) { - return; - } - - EngineManager defaultManager = EngineManager.defaultManager(); - - for (TraceData trace : traces) { - HttpClient httpClient = new HttpClient(host, port); - httpClient.configuration().connectTimeout((int) timeout); - HttpPost post = httpClient.post(ManagerConstants.REPORT_TRACE); - - if (headers != null) { - headers.forEach((key, value) -> post.header().add(key, value)); - } - - TraceReportRequest request = new TraceReportRequest(); - request.setAddress(HostUtils.getHostIp()); - request.setHost(HostUtils.getHostName()); - request.setTimestamp(System.currentTimeMillis()); - FlatEngine flatEngine = FlatManager.getInstance().getFlatEngine(defaultManager.getEngineModel(trace.getEngineName()).getSource()); - request.setMd5(flatEngine.getMd5()); - request.setTraceId(trace.getTraceId()); - request.setEngineName(trace.getEngineName()); - request.setSuccess(trace.getEx() == null); - request.setTraceTime(trace.getTraceTime()); - request.setEndTime(trace.getEndTime()); - if (!request.getSuccess()) { - request.setEx(serialExToString(trace.getEx())); - } - request.setRequest(toJSON(trace.getRequest())); - request.setResult(toJSON(trace.getResult())); - - if (flatEngine.getReportContent()) { - request.setContent(flatEngine.getContent()); - } - - JSONArray ja = new JSONArray(); - - trace.getComponents().forEach((k, v) -> { - JSONObject item = new JSONObject(); - item.put("name", k.getName()); - item.put("type", k.getType()); - item.put("start", v.getStart()); - item.put("escape", v.getEscape()); - item.put("ex", serialExToString(v.getEx())); - item.put("rollbackStart", v.getRollbackStart()); - item.put("rollbackEnd", v.getRollbackEnd()); - - ja.add(item); - }); - - request.setJson(ja); - - String json = JSON.toJSONString(request, SerializerFeature.WriteEnumUsingToString); - byte[] bytes = json.getBytes(StandardCharsets.UTF_8); - - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("report trace data, engine = {}, data = {}", trace.getEngineName(), JSON.toJSONString(request)); - } - - post.header().add(HeaderNameEnum.CONTENT_TYPE.getName(), "application/json;charset=UTF-8").add(HeaderNameEnum.CONTENT_LENGTH.getName(), String.valueOf(bytes.length)); - - // Use body stream write. - post.body().write(bytes, 0, bytes.length).done().onSuccess(httpResponse -> { - LOGGER.info("send trace success"); - }) - .onFailure(throwable -> { - LOGGER.error("send trace failed", throwable); - }); - - } - } - - private String serialExToString(Throwable ex) { - if (ex == null) { - return null; - } - - int maxDepth = ManagerConfiguration.reportMaxStackDepth; - StackTraceElement[] stackTrace = ex.getStackTrace(); - if (stackTrace.length > maxDepth) { - StackTraceElement[] newTrace = new StackTraceElement[maxDepth]; - System.arraycopy(stackTrace, 0, newTrace, 0, newTrace.length); - ex.setStackTrace(newTrace); - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(bos); - ex.printStackTrace(writer); - writer.flush(); - return bos.toString(); - } - - public void start() { - URL parsedUrl; - try { - parsedUrl = new URL(serverAddress); - } catch (Exception e) { - throw new IllegalStateException("invalid url " + serverAddress, e); - } - this.host = parsedUrl.getHost(); - this.port = parsedUrl.getPort(); - - // Register listener. - if (sampleStrategy == null && radio != null && radio > 0 && radio <= 1) { - sampleStrategy = new TraceSampleStrategy(); - sampleStrategy.setRadio(radio); - } - - executionListener = new ManagerExecutionListener(this, sampleStrategy); - ExecutionListenerRegistry.register(executionListener); - UpdateContentTask.startTask(host, port); - executorService.setMaximumPoolSize(1); - executorService.scheduleAtFixedRate(this::export, idle, idle, TimeUnit.MILLISECONDS); - } - - public void submit(TraceData item) { - //noinspection ResultOfMethodCallIgnored - traceQueue.offer(item); - } - - public String getServerAddress() { - return serverAddress; - } - - public void setServerAddress(String serverAddress) { - this.serverAddress = serverAddress; - } - - public long getTimeout() { - return timeout; - } - - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - public Map getHeaders() { - return headers; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public Double getRadio() { - return radio; - } - - public void setRadio(Double radio) { - this.radio = radio; - if (sampleStrategy != null && radio != null && radio > 0 && radio <= 1) { - sampleStrategy.setRadio(radio); - } - } - - public TraceSampleStrategy getSampleStrategy() { - return sampleStrategy; - } - - public void setSampleStrategy(TraceSampleStrategy sampleStrategy) { - this.sampleStrategy = sampleStrategy; - if (this.executionListener != null) { - this.executionListener.setSampleStrategy(this.sampleStrategy); - } - } - - protected String toJSON(Object obj) { - return obj == null ? null : JSON.toJSONString(obj); - } + void report(TraceData trace); } diff --git a/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceRequestConverter.java b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceRequestConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..91309479d3203a625ce779a77d68272004d1a0b6 --- /dev/null +++ b/smart-flow-manager/src/main/java/org/smartboot/flow/manager/trace/TraceRequestConverter.java @@ -0,0 +1,87 @@ +package org.smartboot.flow.manager.trace; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.smartboot.flow.core.FlowEngine; +import org.smartboot.flow.manager.FlatEngine; +import org.smartboot.flow.manager.FlatManager; +import org.smartboot.flow.manager.HostUtils; +import org.smartboot.flow.manager.ManagerConfiguration; + +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; + +/** + * @author qinluo + * @date 2023-08-02 09:05:51 + * @since 1.1.3 + */ +public class TraceRequestConverter { + + public static TraceReportRequest convert(TraceData trace, FlowEngine engine) { + TraceReportRequest request = new TraceReportRequest(); + request.setAddress(HostUtils.getHostIp()); + request.setHost(HostUtils.getHostName()); + request.setTimestamp(System.currentTimeMillis()); + FlatEngine flatEngine = FlatManager.getInstance().getFlatEngine(engine); + request.setMd5(flatEngine.getMd5()); + request.setTraceId(trace.getTraceId()); + request.setEngineName(trace.getEngineName()); + request.setSuccess(trace.getEx() == null); + request.setTraceTime(trace.getTraceTime()); + request.setEndTime(trace.getEndTime()); + if (!request.getSuccess()) { + request.setEx(serialExToString(trace.getEx())); + } + request.setRequest(toJSON(trace.getRequest())); + request.setResult(toJSON(trace.getResult())); + + if (flatEngine.getReportContent()) { + request.setContent(flatEngine.getContent()); + } + + JSONArray ja = new JSONArray(); + + trace.getComponents().forEach((k, v) -> { + JSONObject item = new JSONObject(); + item.put("name", k.getName()); + item.put("type", k.getType()); + item.put("start", v.getStart()); + item.put("escape", v.getEscape()); + item.put("ex", serialExToString(v.getEx())); + item.put("rollbackStart", v.getRollbackStart()); + item.put("rollbackEnd", v.getRollbackEnd()); + + ja.add(item); + }); + + request.setJson(ja); + return request; + } + + private static String serialExToString(Throwable ex) { + if (ex == null) { + return null; + } + + int maxDepth = ManagerConfiguration.reportMaxStackDepth; + StackTraceElement[] stackTrace = ex.getStackTrace(); + if (stackTrace.length > maxDepth) { + StackTraceElement[] newTrace = new StackTraceElement[maxDepth]; + System.arraycopy(stackTrace, 0, newTrace, 0, newTrace.length); + ex.setStackTrace(newTrace); + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintWriter writer = new PrintWriter(bos); + ex.printStackTrace(writer); + writer.flush(); + return bos.toString(); + } + + private static String toJSON(Object obj) { + return obj == null ? null : JSON.toJSONString(obj); + } + +} diff --git a/smart-flow-plugin/pom.xml b/smart-flow-plugin/pom.xml index d6c8537873919b479eca0e101593a6ec301d90d5..b76abb4969efe75476f5cbf898002d3b0d8ae035 100644 --- a/smart-flow-plugin/pom.xml +++ b/smart-flow-plugin/pom.xml @@ -6,7 +6,7 @@ org.smartboot.flow smart-flow-parent - 1.1.2 + 1.1.3 smart-flow-plugin diff --git a/smart-flow-plugin/smart-flow-bootstrap/pom.xml b/smart-flow-plugin/smart-flow-bootstrap/pom.xml index a5625c0bca7637f1791a0d9f289211e54ba7c746..9ffc1b6509a7b00e4709fe45588f231d747c9759 100644 --- a/smart-flow-plugin/smart-flow-bootstrap/pom.xml +++ b/smart-flow-plugin/smart-flow-bootstrap/pom.xml @@ -6,7 +6,7 @@ org.smartboot.flow smart-flow-plugin - 1.1.2 + 1.1.3 smart-flow-bootstrap diff --git a/smart-flow-plugin/smart-flow-enhance-plugin/pom.xml b/smart-flow-plugin/smart-flow-enhance-plugin/pom.xml index 77a3bc2b71130e3d49c4f34387b4f251d28c9fa3..22217006949c6ca8b149a287f82858f448cf169b 100644 --- a/smart-flow-plugin/smart-flow-enhance-plugin/pom.xml +++ b/smart-flow-plugin/smart-flow-enhance-plugin/pom.xml @@ -6,7 +6,7 @@ org.smartboot.flow smart-flow-plugin - 1.1.2 + 1.1.3 smart-flow-enhance-plugin diff --git a/smart-flow-script/pom.xml b/smart-flow-script/pom.xml index c41ee128df81423e5e79a30aa6a59c1b9ed716e5..af5a19dcaccd98d8494bd650a495969cc676c18d 100644 --- a/smart-flow-script/pom.xml +++ b/smart-flow-script/pom.xml @@ -5,7 +5,7 @@ smart-flow-parent org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 pom @@ -21,6 +21,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-script/smart-flow-script-groovy/pom.xml b/smart-flow-script/smart-flow-script-groovy/pom.xml index dcb9a3598ef2f443d5c3ed96f4faedc12833f93b..8febee5d7a28367db7ec31a330e582060594e780 100644 --- a/smart-flow-script/smart-flow-script-groovy/pom.xml +++ b/smart-flow-script/smart-flow-script-groovy/pom.xml @@ -5,7 +5,7 @@ smart-flow-script org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -14,6 +14,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-script/smart-flow-script-ognl/pom.xml b/smart-flow-script/smart-flow-script-ognl/pom.xml index 71f70767e25ae4aa95d607d83c958938bc8621b3..efd7c167d1842163aaea5db2e21fc89f3ff30215 100644 --- a/smart-flow-script/smart-flow-script-ognl/pom.xml +++ b/smart-flow-script/smart-flow-script-ognl/pom.xml @@ -5,7 +5,7 @@ smart-flow-script org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -14,6 +14,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-script/smart-flow-script-qlexpress/pom.xml b/smart-flow-script/smart-flow-script-qlexpress/pom.xml index 3c1184b9d7b60fd40ed42be543c7b96104e1197c..13519f07117359e2ad783e4c3d735ad02230575f 100644 --- a/smart-flow-script/smart-flow-script-qlexpress/pom.xml +++ b/smart-flow-script/smart-flow-script-qlexpress/pom.xml @@ -5,7 +5,7 @@ smart-flow-script org.smartboot.flow - 1.1.2 + 1.1.3 4.0.0 @@ -14,6 +14,7 @@ 8 8 + UTF-8 diff --git a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java b/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java deleted file mode 100644 index abadd1f6603d45929d184a2b36f2e0b7cd42394b..0000000000000000000000000000000000000000 --- a/smart-flow-spring-extension/src/main/java/org/smartboot/flow/spring/extension/SmartFlowRegistrar.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.smartboot.flow.spring.extension; - -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanNameGenerator; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.type.AnnotationMetadata; - -/** - * @author qinluo - * @date 2023/1/31 22:15 - * @since 1.0.0 - */ -public class SmartFlowRegistrar implements ImportBeanDefinitionRegistrar { - - private static final String NOTIFIER_PROCESS = "smart-flow-notifer-processor"; - private static final String REGISTRY_NAME = "smart-flow-registry-processor"; - - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { - registerAll(registry); - } - - public static void registerAll(BeanDefinitionRegistry registry) { - registerNotifier(registry); - registerRegistry(registry); - } - - private static void registerNotifier(BeanDefinitionRegistry registry) { - if (registry.containsBeanDefinition(NOTIFIER_PROCESS)) { - return; - } - RootBeanDefinition definition = new RootBeanDefinition(); - definition.setBeanClass(NotifierProcessor.class); - registry.registerBeanDefinition(NOTIFIER_PROCESS, definition); - } - - private static void registerRegistry(BeanDefinitionRegistry registry) { - if (registry.containsBeanDefinition(REGISTRY_NAME)) { - return; - } - RootBeanDefinition definition = new RootBeanDefinition(); - definition.setBeanClass(SmartFlowBeanFactoryRegistry.class); - registry.registerBeanDefinition(REGISTRY_NAME, definition); - } -} diff --git a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpReportConfiguration.java b/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpReportConfiguration.java deleted file mode 100644 index 4bc582c049b137442598a442a594e21714b41700..0000000000000000000000000000000000000000 --- a/smart-flow-springboot-starter/src/main/java/org/smartboot/flow/springboot/extension/FlowHttpReportConfiguration.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.smartboot.flow.springboot.extension; - -import org.smartboot.flow.manager.report.HttpReporter; -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.Configuration; - -/** - * smart flow httReport auto config - * - * @author huqiang - * @since 2022/12/15 16:32 - */ -@Configuration -@ConfigurationProperties(prefix = "smart.flow.report.http") -@ConditionalOnProperty(name = "smart.flow.report.http.url") -public class FlowHttpReportConfiguration { - - /** - * Connect timeout in microseconds. - */ - private long timeout; - - /** - * Report url. - */ - private String url; - - /** - * Default idle in microseconds. - */ - private long idle = 5000L; - - @Bean(value = "smart-flow-http-reporter", initMethod = "start") - public HttpReporter getHttpReporter() { - HttpReporter reporter = new HttpReporter(); - reporter.setTimeout(this.timeout); - reporter.setServerAddress(this.url); - reporter.setIdle(this.idle); - return reporter; - } - - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - public void setUrl(String url) { - this.url = url; - } - - public void setIdle(long idle) { - this.idle = idle; - } -}