diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java index 80af26990..20efa0ead 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowChainBuilder.java @@ -17,14 +17,23 @@ public class LiteFlowChainBuilder { private Chain chain; + //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载 + //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List + //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList + private final List conditionList; + public static LiteFlowChainBuilder createChain(){ return new LiteFlowChainBuilder(); } public LiteFlowChainBuilder(){ chain = new Chain(); + conditionList = new ArrayList<>(); } + //在parser中chain的build是2段式的,因为涉及到依赖问题,以前是递归parser + //2.6.8之后取消了递归的模式,两段式组装,先把带有chainName的chain对象放进去,第二段再组装chain里面的condition + //所以这里setChainName的时候需要判断下 public LiteFlowChainBuilder setChainName(String chainName){ if (FlowBus.containChain(chainName)){ this.chain = FlowBus.getChain(chainName); @@ -41,6 +50,7 @@ public class LiteFlowChainBuilder { } public void build(){ + this.chain.setConditionList(this.conditionList); FlowBus.addChain(this.chain); } @@ -49,29 +59,29 @@ public class LiteFlowChainBuilder { //对于then来说,相邻的2个then会合并成一个condition //对于when来说,相同组的when会合并成一个condition,不同组的when还是会拆开 if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_PRE)) { - this.chain.getConditionList().add(new PreCondition(condition)); + this.conditionList.add(new PreCondition(condition)); } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_THEN)) { - if (this.chain.getConditionList().size() >= 1 && - CollectionUtil.getLast(this.chain.getConditionList()) instanceof ThenCondition) { - CollectionUtil.getLast(this.chain.getConditionList()).getNodeList().addAll(condition.getNodeList()); + if (this.conditionList.size() >= 1 && + CollectionUtil.getLast(this.conditionList) instanceof ThenCondition) { + CollectionUtil.getLast(this.conditionList).getNodeList().addAll(condition.getNodeList()); } else { - this.chain.getConditionList().add(new ThenCondition(condition)); + this.conditionList.add(new ThenCondition(condition)); } } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_WHEN)) { - if (this.chain.getConditionList().size() > 1 && - CollectionUtil.getLast(this.chain.getConditionList()) instanceof WhenCondition && - CollectionUtil.getLast(this.chain.getConditionList()).getGroup().equals(condition.getGroup())) { - CollectionUtil.getLast(this.chain.getConditionList()).getNodeList().addAll(condition.getNodeList()); + if (this.conditionList.size() > 1 && + CollectionUtil.getLast(this.conditionList) instanceof WhenCondition && + CollectionUtil.getLast(this.conditionList).getGroup().equals(condition.getGroup())) { + CollectionUtil.getLast(this.conditionList).getNodeList().addAll(condition.getNodeList()); } else { - this.chain.getConditionList().add(new WhenCondition(condition)); + this.conditionList.add(new WhenCondition(condition)); } } else if (condition.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)) { - this.chain.getConditionList().add(new FinallyCondition(condition)); + this.conditionList.add(new FinallyCondition(condition)); } //每一次build之后,对conditionList进行排序,pre最前面,finally最后 //这里为什么要排序,因为在声明的时候,哪怕有人不把pre放最前,finally放最后,但最终也要确保是正确的顺序 - CollectionUtil.sort(this.chain.getConditionList(), (o1, o2) -> { + CollectionUtil.sort(this.conditionList, (o1, o2) -> { if (o1.getConditionType().equals(ConditionTypeEnum.TYPE_PRE) || o2.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)){ return -1; } else if (o2.getConditionType().equals(ConditionTypeEnum.TYPE_PRE) || o1.getConditionType().equals(ConditionTypeEnum.TYPE_FINALLY)){ diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java index 7501e2dab..2d45bc2e5 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.builder; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.flow.Node; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.exception.NodeBuildException; @@ -19,10 +20,31 @@ public class LiteFlowNodeBuilder { return new LiteFlowNodeBuilder(); } + public static LiteFlowNodeBuilder createCommonNode(){ + return new LiteFlowNodeBuilder(NodeTypeEnum.COMMON); + } + + public static LiteFlowNodeBuilder createCommonCondNode(){ + return new LiteFlowNodeBuilder(NodeTypeEnum.COMMON); + } + + public static LiteFlowNodeBuilder createScriptNode(){ + return new LiteFlowNodeBuilder(NodeTypeEnum.SCRIPT); + } + + public static LiteFlowNodeBuilder createScriptCondNode(){ + return new LiteFlowNodeBuilder(NodeTypeEnum.COND_SCRIPT); + } + public LiteFlowNodeBuilder() { this.node = new Node(); } + public LiteFlowNodeBuilder(NodeTypeEnum type) { + this.node = new Node(); + this.node.setType(type); + } + public LiteFlowNodeBuilder setId(String nodeId) { this.node.setId(nodeId); return this; @@ -57,6 +79,11 @@ public class LiteFlowNodeBuilder { } public void build() { + //这里也是一个防御性编程 + //如果单独用builder进行构建的话,那么flow.xml不一定存在,不存在则不会进行FlowExecutor的init,也就不会进行DataBus.init + //所以这里多加一步,DataBus.init()事实上只会执行一遍,不会因为之前执行了,重复执行。因为里面有判断 + DataBus.init(); + try { if (this.node.getType().equals(NodeTypeEnum.COMMON)) { FlowBus.addCommonNode(this.node.getId(), this.node.getName(), this.node.getClazz()); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java index 99777f69b..03cbe1a08 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java @@ -64,9 +64,14 @@ public class FlowExecutor { * FlowExecutor的初始化化方式,主要用于parse规则文件 */ public void init() { - if (ObjectUtil.isNull(liteflowConfig) || StrUtil.isBlank(liteflowConfig.getRuleSource())) { + if (ObjectUtil.isNull(liteflowConfig)) { throw new ConfigErrorException("config error, please check liteflow config property"); } + + if (StrUtil.isBlank(liteflowConfig.getRuleSource())){ + return; + } + List sourceRulePathList = Lists.newArrayList(liteflowConfig.getRuleSource().split(",|;")); FlowParser parser = null; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 288c5e412..886638592 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -34,6 +34,7 @@ import com.yomahub.liteflow.script.ScriptExecutorFactory; import com.yomahub.liteflow.script.exception.ScriptSpiException; import com.yomahub.liteflow.util.CopyOnWriteHashMap; import com.yomahub.liteflow.util.SpringAware; +import org.checkerframework.checker.units.qual.C; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.SerializationUtils; @@ -61,14 +62,18 @@ public class FlowBus { return chainMap.get(id); } - public static void addChain(Chain chain) { - if (chainMap.containsKey(chain.getChainName()) && CollectionUtil.isEmpty(chain.getConditionList())){ - chainMap.get(chain.getChainName()).setConditionList(chain.getConditionList()); - }else{ - chainMap.put(chain.getChainName(), chain); + //这一方法主要用于第一阶段chain的预装载 + public static void addChain(String chainName){ + if (!chainMap.containsKey(chainName)){ + chainMap.put(chainName, new Chain(chainName)); } } + //这个方法主要用于第二阶段的替换chain + public static void addChain(Chain chain) { + chainMap.put(chain.getChainName(), chain); + } + public static boolean containChain(String chainId) { return chainMap.containsKey(chainId); } @@ -172,7 +177,6 @@ public class FlowBus { }catch (ScriptSpiException ignored){} } - //目前这种方式刷新不完全平滑 public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { if (type.equals(FlowParserTypeEnum.TYPE_XML)) { new LocalXmlFlowParser().parse(content); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java index f0c09f34f..11e3e751c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/JsonFlowParser.java @@ -78,7 +78,7 @@ public abstract class JsonFlowParser extends FlowParser { //先在元数据里放上chain chainArray.forEach(o -> { JSONObject innerJsonObject = (JSONObject)o; - FlowBus.addChain(new Chain(innerJsonObject.getString("name"))); + FlowBus.addChain(innerJsonObject.getString("name")); }); }); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index fa5bd4def..63986d3a1 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -73,7 +73,7 @@ public abstract class XmlFlowParser extends FlowParser { List chainList = document.getRootElement().elements("chain"); //先在元数据里放上chain - chainList.forEach(e -> FlowBus.addChain(new Chain(e.attributeValue("name")))); + chainList.forEach(e -> FlowBus.addChain(e.attributeValue("name"))); }); for (Document document : documentList) { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/CopyOnWriteHashMap.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/CopyOnWriteHashMap.java index 265cb894b..e24dc4bf6 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/CopyOnWriteHashMap.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/CopyOnWriteHashMap.java @@ -45,6 +45,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -56,27 +58,25 @@ import java.util.concurrent.atomic.AtomicBoolean; * * @author Paul.Sandoz@Oracle.Com * @author pavel.bucek@oracle.com + * @author Bryan.Zhang */ -public class CopyOnWriteHashMap implements Map { - volatile Map view; +public class CopyOnWriteHashMap extends ConcurrentHashMap { - private Map duplicate(Map original) { - Map result = new HashMap(); + volatile ConcurrentHashMap view; + + private ConcurrentHashMap duplicate(ConcurrentHashMap original) { // SUBTLETY: note that original.entrySet() grabs the entire contents of the original Map in a // single call. This means that if the original map is Thread-safe or another CopyOnWriteHashMap, // we can safely iterate over the list of entries. - for (Map.Entry entry : original.entrySet()) { - result.put(entry.getKey(), entry.getValue()); - } - return result; + return new ConcurrentHashMap<>(original); } - public CopyOnWriteHashMap(Map that) { + public CopyOnWriteHashMap(ConcurrentHashMap that) { this.view = duplicate(that); } public CopyOnWriteHashMap() { - this(new HashMap()); + this(new ConcurrentHashMap<>()); } @Override @@ -114,7 +114,7 @@ public class CopyOnWriteHashMap implements Map { } @Override - public Set keySet() { + public KeySetView keySet() { return view.keySet(); } @@ -149,7 +149,7 @@ public class CopyOnWriteHashMap implements Map { @Override public V put(K key, V value) { synchronized (this) { - Map newCore = duplicate(view); + ConcurrentHashMap newCore = duplicate(view); V result = newCore.put(key, value); view = newCore; // volatile write return result; @@ -159,18 +159,17 @@ public class CopyOnWriteHashMap implements Map { @Override public V remove(Object key) { synchronized (this) { - Map newCore = duplicate(view); + ConcurrentHashMap newCore = duplicate(view); V result = newCore.remove(key); view = newCore; // volatile write return result; - } } @Override public void putAll(Map t) { synchronized (this) { - Map newCore = duplicate(view); + ConcurrentHashMap newCore = duplicate(view); newCore.putAll(t); view = newCore; // volatile write } @@ -179,8 +178,7 @@ public class CopyOnWriteHashMap implements Map { @Override public void clear() { synchronized (this) { - Map newCore = new HashMap(); - view = newCore; // volatile write + view = new ConcurrentHashMap<>(); // volatile write } } } \ No newline at end of file diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowExecutorAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowExecutorAutoConfiguration.java index 4219f16da..24ca07970 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowExecutorAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowExecutorAutoConfiguration.java @@ -11,6 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import javax.swing.*; import java.util.concurrent.ExecutorService; /** @@ -25,15 +26,16 @@ import java.util.concurrent.ExecutorService; @Import(SpringAware.class) public class LiteflowExecutorAutoConfiguration { + //这里参数加上这2个为了先行注入 @Bean("whenExecutors") - public ExecutorService executorService(LiteflowConfig liteflowConfig) { + public ExecutorService executorService(SpringAware springAware, LiteflowConfig liteflowConfig) { return ExecutorHelper.loadInstance().buildExecutor(); } //为什么要注释掉这个@Bean? //LiteFlowExecutorPoolShutdown这个类会在spring上下文移除这个bean的时候执行,也就是应用被停止或者kill的时候 //这个类主要用于卸载掉线程池,会等待线程池中的线程执行完,再卸载掉,相当于一个钩子 - //但这段代码在实际中并没有太多用户,就算结束掉应用进程时很多公司也会优雅停机。就显得这段代码很鸡肋 + //但这段代码在实际中并没有太多用处,就算结束掉应用进程时很多公司也会优雅停机。就显得这段代码很鸡肋 //之所以注释掉,是因为在单元测试中,每一个testcase结束时都会调这个方法。 //当异步线程配置超时的时候。由于这个方法会去关闭掉线程池,会导致单元测试在所有一起运行时(单个运行没有问题)会出错 //按理说这个方法会等待线程池里的全部线程执行完再销毁,但是事实上在单元测试中的确会报错。具体原因还没深究,由于这个类比较鸡肋,就干脆不注册了。 diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowMainAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowMainAutoConfiguration.java index 399f79d99..e8fe65d8d 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowMainAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowMainAutoConfiguration.java @@ -35,13 +35,9 @@ public class LiteflowMainAutoConfiguration { @Bean public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig) { - if (StrUtil.isNotBlank(liteflowConfig.getRuleSource())) { - FlowExecutor flowExecutor = new FlowExecutor(); - flowExecutor.setLiteflowConfig(liteflowConfig); - return flowExecutor; - } else { - return null; - } + FlowExecutor flowExecutor = new FlowExecutor(); + flowExecutor.setLiteflowConfig(liteflowConfig); + return flowExecutor; } @Bean diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties index e23f1ae08..d91ff3337 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties @@ -1,6 +1,5 @@ liteflow.enable=true liteflow.print-banner=true -liteflow.rule-source=config/flow.xml liteflow.zk-node=/lite-flow/flow liteflow.slot-size=1024 liteflow.thread-executor-class=com.yomahub.liteflow.thread.LiteFlowDefaultExecutorBuilder diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseSpringbootTest.java index 71e99f774..029d3a5cc 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseSpringbootTest.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/base/BaseSpringbootTest.java @@ -16,7 +16,7 @@ import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; /** - * springboot环境下pre节点和finally节点的测试 + * springboot环境最普通的例子测试 * @author Bryan.Zhang * @since 2.6.4 */ @@ -30,9 +30,8 @@ public class BaseSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; - //测试普通的pre和finally节点 @Test - public void testPreAndFinally1() throws Exception{ + public void testBase() throws Exception{ LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); Assert.assertTrue(response.isSuccess()); } diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest.java new file mode 100644 index 000000000..aaa3a3894 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest.java @@ -0,0 +1,86 @@ +package com.yomahub.liteflow.test.builder; + +import com.yomahub.liteflow.builder.LiteFlowChainBuilder; +import com.yomahub.liteflow.builder.LiteFlowConditionBuilder; +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.entity.data.DefaultSlot; +import com.yomahub.liteflow.entity.data.LiteflowResponse; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +//基于builder模式的单元测试 +//这里只是最基本的builder模式的测试,只是为了验证在springboot模式下的正常性 +//更详细的builder模式测试用例会单独拉testcase去做 +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BuilderSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.builder.cmp"}) +public class BuilderSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + //基于普通组件的builder模式测试 + @Test + public void testBuilder() throws Exception{ + LiteFlowNodeBuilder.createNode().setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.ACmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.BCmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.CCmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("d") + .setName("组件D") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.DCmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("e") + .setName("组件E") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.ECmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("f") + .setName("组件F") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.FCmp") + .build(); + LiteFlowNodeBuilder.createNode().setId("g") + .setName("组件G") + .setType(NodeTypeEnum.COMMON) + .setClazz("com.yomahub.liteflow.test.builder.cmp.GCmp") + .build(); + + + LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition( + LiteFlowConditionBuilder.createThenCondition().setValue("c,d").build() + ).build(); + + LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition( + LiteFlowConditionBuilder.createThenCondition().setValue("a,b").build() + ).setCondition( + LiteFlowConditionBuilder.createWhenCondition().setValue("e(f|g|chain2)").build() + ).build(); + + LiteflowResponse response = flowExecutor.execute2Resp("chain1"); + Assert.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ACmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ACmp.java new file mode 100644 index 000000000..8e52d41c6 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ACmp.java @@ -0,0 +1,19 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +public class ACmp extends NodeComponent { + + @Override + public void process() { + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/BCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/BCmp.java new file mode 100644 index 000000000..42d9fbc7b --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/BCmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +public class BCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("BCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/CCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/CCmp.java new file mode 100644 index 000000000..69ab153e1 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/CCmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +public class CCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("CCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/DCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/DCmp.java new file mode 100644 index 000000000..30b8b5248 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/DCmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +public class DCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("DCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ECmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ECmp.java new file mode 100644 index 000000000..4b11789ac --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/ECmp.java @@ -0,0 +1,20 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeCondComponent; + +public class ECmp extends NodeCondComponent { + + @Override + public String processCond() throws Exception { + System.out.println("ECmp executed!"); + return "chain2"; + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/FCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/FCmp.java new file mode 100644 index 000000000..a26c3223e --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/FCmp.java @@ -0,0 +1,19 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class FCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("FCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/GCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/GCmp.java new file mode 100644 index 000000000..4fd5944bb --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp/GCmp.java @@ -0,0 +1,19 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.builder.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class GCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("GCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/exception/FlowExecutorSpringBootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/exception/FlowExecutorSpringBootTest.java index 8935aa9e7..3cb043358 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/exception/FlowExecutorSpringBootTest.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/exception/FlowExecutorSpringBootTest.java @@ -45,8 +45,7 @@ public class FlowExecutorSpringBootTest extends BaseTest { @Test(expected = ConfigErrorException.class) public void testConfigErrorException() { - LiteflowConfig config = context.getBean(LiteflowConfig.class); - config.setRuleSource(""); + flowExecutor.setLiteflowConfig(null); flowExecutor.init(); } diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/MonitorSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/MonitorSpringbootTest.java new file mode 100644 index 000000000..e07a53ff9 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/MonitorSpringbootTest.java @@ -0,0 +1,41 @@ +package com.yomahub.liteflow.test.monitor; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.entity.data.DefaultSlot; +import com.yomahub.liteflow.entity.data.LiteflowResponse; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +/** + * springboot环境最普通的例子测试 + * @author Bryan.Zhang + * @since 2.6.4 + */ +@RunWith(SpringRunner.class) +@TestPropertySource(value = "classpath:/monitor/application.properties") +@SpringBootTest(classes = MonitorSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.monitor.cmp"}) +public class MonitorSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + @Test + public void testMonitor() throws Exception{ + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assert.assertTrue(response.isSuccess()); + + Thread.sleep(20000); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/ACmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/ACmp.java new file mode 100644 index 000000000..d5f2438af --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/ACmp.java @@ -0,0 +1,28 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.monitor.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +import java.util.Random; + +@Component("a") +public class ACmp extends NodeComponent { + + @Override + public void process() { + try { + Thread.sleep(new Random().nextInt(2000)); + }catch (Exception e){ + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/BCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/BCmp.java new file mode 100644 index 000000000..a5a3f44e0 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/BCmp.java @@ -0,0 +1,28 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.monitor.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +import java.util.Random; + +@Component("b") +public class BCmp extends NodeComponent { + + @Override + public void process() { + try { + Thread.sleep(new Random().nextInt(2000)); + }catch (Exception e){ + e.printStackTrace(); + } + System.out.println("BCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/CCmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/CCmp.java new file mode 100644 index 000000000..6a44bb60a --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/monitor/cmp/CCmp.java @@ -0,0 +1,28 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.monitor.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +import java.util.Random; + +@Component("c") +public class CCmp extends NodeComponent { + + @Override + public void process() { + try { + Thread.sleep(new Random().nextInt(2000)); + }catch (Exception e){ + e.printStackTrace(); + } + System.out.println("CCmp executed!"); + } + +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserJsonSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/JsonParserSpringbootTest.java similarity index 87% rename from liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserJsonSpringbootTest.java rename to liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/JsonParserSpringbootTest.java index 0edbf4f14..0eb4ce18e 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserJsonSpringbootTest.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/JsonParserSpringbootTest.java @@ -22,10 +22,9 @@ import javax.annotation.Resource; */ @RunWith(SpringRunner.class) @TestPropertySource(value = "classpath:/parser/application-json.properties") -@SpringBootTest(classes = LFParserJsonSpringbootTest.class) +@SpringBootTest(classes = JsonParserSpringbootTest.class) @EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.parser.cmp"}) -public class LFParserJsonSpringbootTest extends BaseTest { +public class JsonParserSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/SpringELSupportSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/SpringELSupportSpringbootTest.java new file mode 100644 index 000000000..ec0e2acc7 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/SpringELSupportSpringbootTest.java @@ -0,0 +1,32 @@ +package com.yomahub.liteflow.test.parser; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.entity.data.DefaultSlot; +import com.yomahub.liteflow.entity.data.LiteflowResponse; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@TestPropertySource(value = "classpath:/parser/application-springEL.properties") +@SpringBootTest(classes = SpringELSupportSpringbootTest.class) +@EnableAutoConfiguration +public class SpringELSupportSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + //测试springEL的解析情况 + @Test + public void testSpringELParser() { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assert.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserXmlSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/XmlParserSpringbootTest.java similarity index 87% rename from liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserXmlSpringbootTest.java rename to liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/XmlParserSpringbootTest.java index a6adad661..91e0a44d4 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserXmlSpringbootTest.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/XmlParserSpringbootTest.java @@ -22,10 +22,9 @@ import javax.annotation.Resource; */ @RunWith(SpringRunner.class) @TestPropertySource(value = "classpath:/parser/application-xml.properties") -@SpringBootTest(classes = LFParserXmlSpringbootTest.class) +@SpringBootTest(classes = XmlParserSpringbootTest.class) @EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.parser.cmp"}) -public class LFParserXmlSpringbootTest extends BaseTest { +public class XmlParserSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserYmlSpringbootTest.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/YmlParserSpringbootTest.java similarity index 87% rename from liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserYmlSpringbootTest.java rename to liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/YmlParserSpringbootTest.java index 90d5636bf..3b2305e20 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/LFParserYmlSpringbootTest.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/YmlParserSpringbootTest.java @@ -22,10 +22,9 @@ import javax.annotation.Resource; */ @RunWith(SpringRunner.class) @TestPropertySource(value = "classpath:/parser/application-yml.properties") -@SpringBootTest(classes = LFParserYmlSpringbootTest.class) +@SpringBootTest(classes = YmlParserSpringbootTest.class) @EnableAutoConfiguration -@ComponentScan({"com.yomahub.liteflow.test.parser.cmp"}) -public class LFParserYmlSpringbootTest extends BaseTest { +public class YmlParserSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/cmp/ACmp.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/cmp/ACmp.java index 4aafee9a6..2c6a9ddf4 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/cmp/ACmp.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/parser/cmp/ACmp.java @@ -17,10 +17,6 @@ public class ACmp extends NodeComponent { @Override public void process() { - String str = this.getSlot().getRequestData(); - if(StrUtil.isNotBlank(str) && str.equals("exception")) { - throw new FlowSystemException("chain execute execption"); - } System.out.println("ACmp executed!"); } } diff --git a/liteflow-testcase-springboot/src/test/resources/monitor/application.properties b/liteflow-testcase-springboot/src/test/resources/monitor/application.properties new file mode 100644 index 000000000..ee78cdf43 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/monitor/application.properties @@ -0,0 +1,5 @@ +liteflow.rule-source=monitor/flow.xml +liteflow.monitor.enable-log=true +liteflow.monitor.queue-limit=200 +liteflow.monitor.delay=5000 +liteflow.monitor.period=5000 \ No newline at end of file diff --git a/liteflow-testcase-springboot/src/test/resources/monitor/flow.xml b/liteflow-testcase-springboot/src/test/resources/monitor/flow.xml new file mode 100644 index 000000000..e8ea83f95 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/monitor/flow.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-springboot/src/test/resources/parser/application-springEL.properties b/liteflow-testcase-springboot/src/test/resources/parser/application-springEL.properties new file mode 100644 index 000000000..7db93206b --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/parser/application-springEL.properties @@ -0,0 +1 @@ +liteflow.rule-source=parser/**/*.xml \ No newline at end of file diff --git a/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow1.xml b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow1.xml new file mode 100644 index 000000000..0775c5ec1 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow1.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow2.xml b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow2.xml new file mode 100644 index 000000000..d739f6b53 --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow2.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow3.xml b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow3.xml new file mode 100644 index 000000000..0a898126c --- /dev/null +++ b/liteflow-testcase-springboot/src/test/resources/parser/subFoder1/subFoder2/flow3.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file