فهرست منبع

添加新的单测模块 liteflow-testcase-el-declare-multi-solon

noear 8 ماه پیش
والد
کامیت
647523f395
100فایلهای تغییر یافته به همراه4768 افزوده شده و 0 حذف شده
  1. 52 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/pom.xml
  2. 22 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/BaseTest.java
  3. 98 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java
  4. 34 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/cmp/CmpMultiDefine.java
  5. 55 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainJsonELDeclMultiSpringBootTest.java
  6. 57 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainXmlELDeclMultiSpringbootTest.java
  7. 56 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainYmlELDeclMultiSpringBootTest.java
  8. 51 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/cmp/CmpConfig.java
  9. 49 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/CustomAOPELDeclMultiSpringbootTest.java
  10. 71 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/GlobalAOPELDeclMultiSpringbootTest.java
  11. 34 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/aspect/CmpAspect.java
  12. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/aspect/CustomAspect.java
  13. 26 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/cmp1/Cmp1Config.java
  14. 26 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/cmp2/Cmp2Config.java
  15. 131 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELDeclMultiSpringbootTest.java
  16. 147 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/CmpConfig.java
  17. 5 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/exception/TestException.java
  18. 37 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/BaseELDeclMultiSpringbootTest.java
  19. 58 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/cmp/CmpConfig.java
  20. 13 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/cmp/TestDomain.java
  21. 175 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclMultiSpringbootTest1.java
  22. 30 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclMultiSpringbootTest2.java
  23. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java
  24. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java
  25. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java
  26. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java
  27. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java
  28. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java
  29. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java
  30. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/HCmp.java
  31. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/ICmp.java
  32. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/JCmp.java
  33. 12 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/domain/TestDomain.java
  34. 56 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpRetry/LiteflowRetryELDeclMultiSpringbootTest.java
  35. 62 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpRetry/cmp/CmpConfig.java
  36. 66 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpStep/CmpStepELDeclSpringbootTest.java
  37. 45 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpStep/cmp/CmpConfig.java
  38. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/comments/LiteflowNodeELDeclMultiSpringbootTest.java
  39. 26 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/comments/cmp/CmpConfig.java
  40. 42 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/ComplexELDeclMultiSpringbootTest1.java
  41. 42 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/ComplexELDeclMultiSpringbootTest2.java
  42. 82 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp1/CmpConfig1.java
  43. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp1/ICmp.java
  44. 82 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp2/CmpConfig2.java
  45. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp2/ICmp.java
  46. 90 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/FlowExecutorELDeclMultiSpringbootTest.java
  47. 111 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/cmp1/CmpConfig1.java
  48. 28 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/cmp2/FCondCmp.java
  49. 31 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customMethodName/CustomMethodNameELDeclMultiSpringbootTest.java
  50. 54 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customMethodName/cmp/CmpConfig.java
  51. 37 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/CustomNodesELDeclMultiSpringbootTest.java
  52. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/ACmp.java
  53. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/BCmp.java
  54. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/CCmp.java
  55. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/DCmp.java
  56. 29 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/ECmp.java
  57. 21 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/FCmp.java
  58. 12 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/domain/DemoDomain.java
  59. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor1.java
  60. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor2.java
  61. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor3.java
  62. 67 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomWhenThreadPoolELDeclMultiSpringbootTest.java
  63. 53 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/cmp/CmpConfig.java
  64. 57 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/event/EventELDeclMultiSpringbootTest.java
  65. 82 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/event/cmp/CmpConfig.java
  66. 14 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/CustomStatefulException.java
  67. 63 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/Exception1ELDeclMultiSpringBootTest.java
  68. 72 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/Exception2ELDeclMultiSpringBootTest.java
  69. 81 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/cmp/CmpConfig.java
  70. 34 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/execute2Future/Executor2FutureELDeclMultiSpringbootTest.java
  71. 32 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/execute2Future/cmp/CmpConfig.java
  72. 31 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/extend/CmpExtendELDeclMultiSpringbootTest.java
  73. 32 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/extend/cmp/CmpConfig.java
  74. 53 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/getChainName/GetChainNameELDeclMultiSpringbootTest.java
  75. 79 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/getChainName/cmp/CmpConfig.java
  76. 81 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/ifelse/IfElseELDeclMultiSpringbootTest.java
  77. 38 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/ifelse/cmp/CmpConfig.java
  78. 50 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/iterator/IteratorELDeclMultiSpringbootTest.java
  79. 43 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/iterator/cmp/CmpConfig.java
  80. 20 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/LazyELDeclMultiSpringbootTest.java
  81. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/ACmp.java
  82. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/BCmp.java
  83. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/CCmp.java
  84. 32 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/LiteflowComponentELDeclMultiSpringbootTest.java
  85. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/ACmp.java
  86. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/BCmp.java
  87. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/CCmp.java
  88. 23 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/DCmp.java
  89. 89 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/loop/LoopELDeclMultiSpringbootTest.java
  90. 82 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/loop/cmp/CmpConfig.java
  91. 171 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclMultiSpringbootTest.java
  92. 98 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CmpConfig.java
  93. 171 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitSeconds/MaxWaitSecondsELDeclMultiSpringbootTest.java
  94. 98 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitSeconds/cmp/CmpConfig.java
  95. 43 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/monitor/MonitorELDeclMultiSpringbootTest.java
  96. 47 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/monitor/cmp/CmpConfig.java
  97. 25 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/CheckContext.java
  98. 48 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/MultiContextELDeclMultiSpringbootTest.java
  99. 37 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/OrderContext.java
  100. 45 0
      liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/cmp/CmpConfig.java

+ 52 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/pom.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         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">
+    <parent>
+        <artifactId>liteflow-testcase-el</artifactId>
+        <groupId>com.yomahub</groupId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>liteflow-testcase-el-declare-multi-solon</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-solon-plugin</artifactId>
+            <version>${revision}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.noear</groupId>
+            <artifactId>solon-test</artifactId>
+            <version>${solon.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.101tec</groupId>
+            <artifactId>zkclient</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-framework</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-recipes</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 22 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/BaseTest.java

@@ -0,0 +1,22 @@
+package com.yomahub.liteflow.test;
+
+import com.yomahub.liteflow.core.FlowInitHook;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.spi.holder.SpiFactoryInitializing;
+import com.yomahub.liteflow.thread.ExecutorHelper;
+import org.junit.jupiter.api.AfterAll;
+
+public class BaseTest {
+
+	@AfterAll
+	public static void cleanScanCache() {
+		//ComponentScanner.cleanCache();
+		FlowBus.cleanCache();
+		ExecutorHelper.loadInstance().clearExecutorServiceMap();
+		SpiFactoryInitializing.clean();
+		LiteflowConfigGetter.clean();
+		FlowInitHook.cleanHook();
+	}
+
+}

+ 98 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java

@@ -0,0 +1,98 @@
+package com.yomahub.liteflow.test.absoluteConfigPath;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIf;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境下异步线程超时日志打印测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@SolonTest(classes = AbsoluteConfigPathELDeclMultiSpringbootTest.class)
+public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
+
+	private static String rootDir;
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testAbsoluteConfig() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir));
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	public void testAbsolutePathMatch() throws Exception {
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir));
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	@Test
+	@EnabledIf("isWindows")
+	public void testAbsPath() throws Exception{
+		Assertions.assertTrue(() -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource(StrUtil.format("{}\\sub\\**\\*.xml",rootDir));
+			flowExecutor.reloadRule();
+			return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
+		});
+	}
+
+	public static boolean isWindows() {
+		try {
+			String osName = System.getProperty("os.name");
+			if (osName.isEmpty()) return false;
+			else {
+				return osName.contains("Windows");
+			}
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	@BeforeAll
+	public static void createFiles() {
+		rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
+
+		String path1 = StrUtil.format("{}/sub/a", rootDir);
+		String path2 = StrUtil.format("{}/sub/b", rootDir);
+
+		FileUtil.mkdir(path1);
+		FileUtil.mkdir(path2);
+
+		String content1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain1\">WHEN(a, b, c);</chain></flow>";
+		String content2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><flow><chain name=\"chain2\">THEN(c, chain1);</chain></flow>";
+
+		FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8);
+		FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8);
+	}
+
+	@AfterAll
+	public static void removeFiles() {
+		FileUtil.del(StrUtil.format("{}/sub", rootDir));
+	}
+
+}

+ 34 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/cmp/CmpMultiDefine.java

@@ -0,0 +1,34 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.absoluteConfigPath.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+@LiteflowComponent
+public class CmpMultiDefine {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a", nodeType = NodeTypeEnum.COMMON)
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 55 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainJsonELDeclMultiSpringBootTest.java

@@ -0,0 +1,55 @@
+package com.yomahub.liteflow.test.abstractChain;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 测试显示调用子流程(json) 单元测试
+ *
+ * @author justin.xu
+ */
+@Import(profiles = "classpath:/abstractChain/application-json.properties")
+@SolonTest(classes = AbstractChainJsonELDeclMultiSpringBootTest.class)
+public class AbstractChainJsonELDeclMultiSpringBootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 是否按照流程定义配置执行
+	@Test
+	public void test1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implA", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implB", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implC", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>a==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	@Test
+	public void test4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implD", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>j==>k==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+}

+ 57 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainXmlELDeclMultiSpringbootTest.java

@@ -0,0 +1,57 @@
+package com.yomahub.liteflow.test.abstractChain;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境EL常规的例子测试
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles = "classpath:/abstractChain/application.properties")
+@SolonTest(classes = AbstractChainXmlELDeclMultiSpringbootTest.class)
+public class AbstractChainXmlELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+
+
+	// XML文件基本继承测试
+	@Test
+	public void test1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implA", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implB", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implC", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>a==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	@Test
+	public void test4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implD", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>j==>k==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+}

+ 56 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/AbstractChainYmlELDeclMultiSpringBootTest.java

@@ -0,0 +1,56 @@
+package com.yomahub.liteflow.test.abstractChain;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 测试显示调用子流程(yml) 单元测试
+ *
+ * @author justin.xu
+ */
+@Import(profiles =  "classpath:/abstractChain/application-yml.properties")
+@SolonTest(classes = AbstractChainYmlELDeclMultiSpringBootTest.class)
+public class AbstractChainYmlELDeclMultiSpringBootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 是否按照流程定义配置执行
+	// XML文件基本继承测试
+	@Test
+	public void test1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implA", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implB", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+	//测试嵌套继承的baseChain是否重复解析
+	@Test
+	public void test3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implC", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>a==>b==>f==>a==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	@Test
+	public void test4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("implD", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>a==>b==>j==>k==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
+	}
+
+}

+ 51 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/abstractChain/cmp/CmpConfig.java

@@ -0,0 +1,51 @@
+package com.yomahub.liteflow.test.abstractChain.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+    public void processA(NodeComponent bindCmp) {
+        System.out.println("ACmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+    public void processB(NodeComponent bindCmp) {
+        System.out.println("BCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "c", nodeType = NodeTypeEnum.BOOLEAN)
+    public boolean processIfC(NodeComponent bindCmp) throws Exception{
+        return true;
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+    public void processD(NodeComponent bindCmp) {
+        System.out.println("DCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+    public void processE(NodeComponent bindCmp) {
+        System.out.println("ECmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "f", nodeType = NodeTypeEnum.SWITCH)
+    public String processF(NodeComponent bindCmp) {
+        return "j";
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "j")
+    public void processJ(NodeComponent bindCmp) {
+        System.out.println("JCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "k")
+    public void processK(NodeComponent bindCmp) {
+        System.out.println("KCmp executed!");
+    }
+}

+ 49 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/CustomAOPELDeclMultiSpringbootTest.java

@@ -0,0 +1,49 @@
+package com.yomahub.liteflow.test.aop;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.aop.aspect.CustomAspect;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 切面场景单元测试 在声明式组件场景中,自定义aspect的aop不生效的,因为生成的代理类并不是原类,也不是原类的子类,而是NodeComponent的子类
+ * 所以切不到,暂且没有想出办法来解决,这个测试类暂时不用
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles =  "classpath:/aop/application.properties", classes = CustomAspect.class)
+@SolonTest(classes = CustomAOPELDeclMultiSpringbootTest.class)
+public class CustomAOPELDeclMultiSpringbootTest extends BaseTest {
+
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	//测试自定义AOP,串行场景
+	@Test
+	public void testCustomAopS() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("before_after", context.getData("a"));
+		Assertions.assertEquals("before_after", context.getData("b"));
+		Assertions.assertEquals("before_after", context.getData("c"));
+	}
+
+	//测试自定义AOP,并行场景
+	@Test
+	public void testCustomAopP() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "it's a request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("before_after", context.getData("a"));
+		Assertions.assertEquals("before_after", context.getData("b"));
+		Assertions.assertEquals("before_after", context.getData("c"));
+	}
+}

+ 71 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/GlobalAOPELDeclMultiSpringbootTest.java

@@ -0,0 +1,71 @@
+package com.yomahub.liteflow.test.aop;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.aop.aspect.CmpAspect;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 切面场景单元测试
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles =  "classpath:/aop/application.properties", classes = CmpAspect.class)
+@SolonTest(classes = GlobalAOPELDeclMultiSpringbootTest.class)
+public class GlobalAOPELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 测试全局AOP,串行场景
+	@Test
+	public void testGlobalAopS() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("before_after", context.getData("a"));
+		Assertions.assertEquals("before_after", context.getData("b"));
+		Assertions.assertEquals("before_after", context.getData("c"));
+		Assertions.assertEquals("before_after", context.getData("d"));
+		Assertions.assertEquals("before_after", context.getData("e"));
+	}
+
+	// 测试全局AOP,并行场景
+	@Test
+	public void testGlobalAopP() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "it's a request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("before_after", context.getData("a"));
+		Assertions.assertEquals("before_after", context.getData("b"));
+		Assertions.assertEquals("before_after", context.getData("c"));
+		Assertions.assertEquals("before_after", context.getData("d"));
+		Assertions.assertEquals("before_after", context.getData("e"));
+	}
+
+	@Test
+	public void testGlobalAopException() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals("before_after", context.getData("a"));
+		Assertions.assertEquals("before_after", context.getData("b"));
+		Assertions.assertEquals("before_after", context.getData("c"));
+		Assertions.assertEquals("before_after", context.getData("f"));
+		Assertions.assertEquals("test error", context.getData("f_error"));
+	}
+
+	@AfterAll
+	public static void cleanScanCache() {
+		BaseTest.cleanScanCache();
+		//ComponentScanner.cmpAroundAspect = null;
+	}
+
+}

+ 34 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/aspect/CmpAspect.java

@@ -0,0 +1,34 @@
+package com.yomahub.liteflow.test.aop.aspect;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.aop.ICmpAroundAspect;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.slot.Slot;
+
+public class CmpAspect implements ICmpAroundAspect {
+
+	@Override
+	public void beforeProcess(NodeComponent cmp) {
+		DefaultContext context = cmp.getFirstContextBean();
+		context.setData(cmp.getNodeId(), "before");
+	}
+
+	@Override
+	public void afterProcess(NodeComponent cmp) {
+		DefaultContext context = cmp.getFirstContextBean();
+		context.setData(cmp.getNodeId(), StrUtil.format("{}_{}", context.getData(cmp.getNodeId()), "after"));
+	}
+
+	@Override
+	public void onSuccess(NodeComponent cmp) {
+
+	}
+
+	@Override
+	public void onError(NodeComponent cmp, Exception e) {
+		DefaultContext context = cmp.getFirstContextBean();
+		context.setData(cmp.getNodeId()+"_error", e.getMessage());
+	}
+
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/aspect/CustomAspect.java

@@ -0,0 +1,28 @@
+package com.yomahub.liteflow.test.aop.aspect;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.slot.DefaultContext;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+
+@Aspect
+public class CustomAspect {
+
+	@Pointcut("execution(* com.yomahub.liteflow.test.aop.cmp1.*.process*(..))")
+	public void cut() {
+	}
+
+	@Around("cut()")
+	public Object around(ProceedingJoinPoint jp) throws Throwable {
+		NodeComponent cmp = (NodeComponent)jp.getArgs()[0];
+		DefaultContext context = cmp.getFirstContextBean();
+		context.setData(cmp.getNodeId(), "before");
+		Object returnObj = jp.proceed();
+		context.setData(cmp.getNodeId(), StrUtil.format("{}_{}", context.getData(cmp.getNodeId()), "after"));
+		return returnObj;
+	}
+
+}

+ 26 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/cmp1/Cmp1Config.java

@@ -0,0 +1,26 @@
+package com.yomahub.liteflow.test.aop.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class Cmp1Config {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("Acomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("Bcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("Ccomp executed!");
+	}
+
+}

+ 26 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/aop/cmp2/Cmp2Config.java

@@ -0,0 +1,26 @@
+package com.yomahub.liteflow.test.aop.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class Cmp2Config {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		System.out.println("Dcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		System.out.println("Ecomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) {
+		throw new RuntimeException("test error");
+	}
+
+}

+ 131 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELDeclMultiSpringbootTest.java

@@ -0,0 +1,131 @@
+package com.yomahub.liteflow.test.asyncNode;
+
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.asyncNode.exception.TestException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 测试隐式调用子流程 单元测试
+ *
+ * @author ssss
+ */
+@Import(profiles =  "classpath:/asyncNode/application.properties")
+@SolonTest(classes = AsyncNodeELDeclMultiSpringbootTest.class)
+public class AsyncNodeELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	/*****
+	 * 标准chain 嵌套选择 嵌套子chain进行执行 验证了when情况下 多个node是并行执行 验证了默认参数情况下 when可以加载执行
+	 **/
+	@Test
+	public void testAsyncFlow1() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a base request");
+		Assertions.assertTrue(response.isSuccess());
+		System.out.println(response.getExecuteStepStr());
+	}
+
+	// 这个和test1有点类似,只不过进一步验证了步骤
+	@Test
+	public void testAsyncFlow2() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "it's a base request");
+		Assertions.assertTrue(
+				ListUtil
+					.toList("b==>j==>g==>f==>h", "b==>j==>g==>h==>f", "b==>j==>h==>g==>f", "b==>j==>h==>f==>g",
+							"b==>j==>f==>h==>g", "b==>j==>f==>g==>h")
+					.contains(response.getExecuteStepStr()));
+	}
+
+	// 测试errorResume,默认的errorResume为false,这里测试默认的
+	@Test
+	public void testAsyncFlow3_1() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3-1", "it's a base request");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals(response.getSlot().getException().getClass(), TestException.class);
+	}
+
+	// 测试errorResume,默认的errorResume为false,这里设置为true
+	@Test
+	public void testAsyncFlow3_2() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3-2", "it's a base request");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	// 相同group的并行组,会合并,并且errorResume根据第一个when来,这里第一个when配置了不抛错
+	@Test
+	public void testAsyncFlow4() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "it's a base request");
+		DefaultContext context = response.getFirstContextBean();
+		// 因为不记录错误,所以最终结果是true
+		Assertions.assertTrue(response.isSuccess());
+		// 因为是并行组,所以即便抛错了,其他组件也会执行,i在流程里配置了2遍,i抛错,但是也执行了2遍,这里验证下
+		Integer count = context.getData("count");
+		Assertions.assertEquals(2, count);
+		// 因为配置了不抛错,所以response里的cause应该为null
+		Assertions.assertNull(response.getCause());
+	}
+
+	// 相同group的并行组,会合并,并且errorResume根据第一个when来,这里第一个when配置了会抛错
+	@Test
+	public void testAsyncFlow5() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", "it's a base request");
+		DefaultContext context = response.getFirstContextBean();
+		// 整个并行组是报错的,所以最终结果是false
+		Assertions.assertFalse(response.isSuccess());
+		// 因为是并行组,所以即便抛错了,其他组件也会执行,i在流程里配置了2遍,i抛错,但是也执行了2遍,这里验证下
+		Integer count = context.getData("count");
+		Assertions.assertEquals(2, count);
+		// 因为第一个when配置了会报错,所以response里的cause里应该会有TestException
+		Assertions.assertEquals(TestException.class, response.getCause().getClass());
+	}
+
+	// 不同group的并行组,不会合并,第一个when的errorResume是false,会抛错,那第二个when就不会执行
+	@Test
+	public void testAsyncFlow6() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", "it's a base request");
+		DefaultContext context = response.getFirstContextBean();
+		// 第一个when会抛错,所以最终结果是false
+		Assertions.assertFalse(response.isSuccess());
+		// 因为是不同组并行组,第一组的when里的i就抛错了,所以i就执行了1遍
+		Integer count = context.getData("count");
+		Assertions.assertEquals(1, count);
+		// 第一个when会报错,所以最终response的cause里应该会有TestException
+		Assertions.assertEquals(TestException.class, response.getCause().getClass());
+	}
+
+	// 不同group的并行组,不会合并,第一个when的errorResume是true,不会报错,那第二个when还会继续执行,但是第二个when的errorResume是false,所以第二个when会报错
+	@Test
+	public void testAsyncFlow7() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain7", "it's a base request");
+		DefaultContext context = response.getFirstContextBean();
+		// 第二个when会抛错,所以最终结果是false
+		Assertions.assertFalse(response.isSuccess());
+		// 传递了slotIndex,则set的size==2
+		Integer count = context.getData("count");
+		Assertions.assertEquals(2, count);
+		// 第一个when会报错,所以最终response的cause里应该会有TestException
+		Assertions.assertEquals(TestException.class, response.getCause().getClass());
+	}
+
+	// 测试任意异步一个执行完即继续的场景
+	// d g h并行,配置了any=true,其中d耗时1秒,g耗时0.5秒,其他都不设耗时
+	// 最终执行效果应该是h先返回,然后执行abc,最后gd
+	// 这里要注意的是,由于step是先加入,所以step的打印顺序并不是这样的。但是实际执行是正确的
+	@Test
+	public void testAsyncFlow8() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain8", "it's a base request");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(context.getData("check").toString().startsWith("habc"));
+	}
+
+}

+ 147 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/CmpConfig.java

@@ -0,0 +1,147 @@
+package com.yomahub.liteflow.test.asyncNode.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.asyncNode.exception.TestException;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+		}
+		System.out.println("Acomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+		}
+		System.out.println("Bcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+		}
+		System.out.println("Ccomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) throws Exception {
+		Thread.sleep(1000);
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+		}
+		System.out.println("Dcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "e", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchE(NodeComponent bindCmp) throws Exception {
+		System.out.println("Ecomp executed!");
+		return "g";
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) throws Exception {
+		System.out.println("Fcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "g")
+	public void processG(NodeComponent bindCmp) throws Exception {
+		Thread.sleep(500);
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+		}
+		System.out.println("Gcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "h")
+	public void processH(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (NodeComponent.class) {
+			if (context.hasData("check")) {
+				String str = context.getData("check");
+				str += bindCmp.getNodeId();
+				context.setData("check", str);
+			}
+			else {
+				context.setData("check", bindCmp.getNodeId());
+			}
+
+		}
+
+		System.out.println("Hcomp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "i")
+	public void processI(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		synchronized (this) {
+			if (context.hasData("count")) {
+				Integer count = context.getData("count");
+				context.setData("count", ++count);
+			}
+			else {
+				context.setData("count", 1);
+			}
+		}
+		System.out.println("Icomp executed! throw Exception!");
+		throw new TestException();
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "j", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchJ(NodeComponent bindCmp) throws Exception {
+		System.out.println("Jcomp executed!");
+		return "chain3";
+	}
+
+}

+ 5 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/asyncNode/exception/TestException.java

@@ -0,0 +1,5 @@
+package com.yomahub.liteflow.test.asyncNode.exception;
+
+public class TestException extends Exception {
+
+}

+ 37 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/BaseELDeclMultiSpringbootTest.java

@@ -0,0 +1,37 @@
+package com.yomahub.liteflow.test.base;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles = "classpath:/base/application.properties")
+@SolonTest(classes = BaseELDeclMultiSpringbootTest.class)
+public class BaseELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testBase1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	@Test
+	public void testBase2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertFalse(response.isSuccess());
+	}
+
+}

+ 58 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/cmp/CmpConfig.java

@@ -0,0 +1,58 @@
+package com.yomahub.liteflow.test.base.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import org.noear.solon.annotation.Inject;
+
+import javax.annotation.Resource;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a", nodeName = "A组件")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+	@Inject
+	private TestDomain testDomain;
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		testDomain.sayHi();
+		System.out.println("CCmp executed!");
+	}
+
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		System.out.println("ECmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.BEFORE_PROCESS, nodeId = "e")
+	public void beforeProcessE(NodeComponent bindCmp) {
+		int a = 1/0;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_ERROR, nodeId = "e")
+	public void onErrorE(NodeComponent bindCmp, Exception e) {
+		if (e != null){
+			e.printStackTrace();
+		}else{
+			System.out.println("no error");
+		}
+	}
+}

+ 13 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/base/cmp/TestDomain.java

@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.test.base.cmp;
+
+
+import org.noear.solon.annotation.Component;
+
+@Component
+public class TestDomain {
+
+	public void sayHi() {
+		System.out.println("hello");
+	}
+
+}

+ 175 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclMultiSpringbootTest1.java

@@ -0,0 +1,175 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
+import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.builder.cmp1.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+//基于builder模式的单元测试
+//这里只是最基本的builder模式的测试,只是为了验证在springboot模式下的正常性
+//更详细的builder模式测试用例会单独拉testcase去做
+@SolonTest(classes = BuilderELDeclMultiSpringbootTest1.class)
+public class BuilderELDeclMultiSpringbootTest1 extends BaseTest {
+
+	@Inject
+	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.cmp1.ACmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("b")
+			.setName("组件B")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.BCmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("c")
+			.setName("组件C")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.CCmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("d")
+			.setName("组件D")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.DCmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("e")
+			.setName("组件E")
+			.setType(NodeTypeEnum.SWITCH)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.ECmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("f")
+			.setName("组件F")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.FCmp")
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("g")
+			.setName("组件G")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz("com.yomahub.liteflow.test.builder.cmp1.GCmp")
+			.build();
+
+		LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL("THEN(c, d)").build();
+
+		LiteFlowChainELBuilder.createChain()
+			.setChainName("chain1")
+			.setEL("THEN(a, b, WHEN(SWITCH(e).to(f, g, chain2)))")
+			.build();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
+	}
+
+	// 基于普通组件的builder模式测试
+	@Test
+	public void testBuilderForClassAndCode() throws Exception {
+		LiteFlowNodeBuilder.createNode()
+			.setId("a")
+			.setName("组件A")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(ACmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("b")
+			.setName("组件B")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(BCmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("c")
+			.setName("组件C")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(CCmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("d")
+			.setName("组件D")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(DCmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("e")
+			.setName("组件E")
+			.setType(NodeTypeEnum.SWITCH)
+			.setClazz(ECmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("f")
+			.setName("组件F")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(FCmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("g")
+			.setName("组件G")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(GCmp.class)
+			.build();
+
+		LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL("THEN(c, d)").build();
+
+		LiteFlowChainELBuilder.createChain()
+			.setChainName("chain1")
+			.setEL("THEN(a, b, WHEN(SWITCH(e).to(f, g, chain2)))")
+			.build();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
+	}
+
+	@Test
+	public void testBuilderForSameNodeMultiTimes() throws Exception {
+		LiteFlowNodeBuilder.createNode()
+			.setId("a1")
+			.setName("组件A1")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(ACmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("a2")
+			.setName("组件A2")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(ACmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("c1")
+			.setName("组件C1")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(CCmp.class)
+			.build();
+		LiteFlowNodeBuilder.createNode()
+			.setId("c2")
+			.setName("组件C2")
+			.setType(NodeTypeEnum.COMMON)
+			.setClazz(CCmp.class)
+			.build();
+
+		LiteFlowChainELBuilder.createChain().setChainName("chain1").setEL("THEN(a1,c2,a2,c1)").build();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a1[组件A1]==>c2[组件C2]==>a2[组件A2]==>c1[组件C1]", response.getExecuteStepStr());
+	}
+
+}

+ 30 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclMultiSpringbootTest2.java

@@ -0,0 +1,30 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+//基于builder模式的单元测试
+//这里测试的是通过spring去扫描,但是通过代码去构建chain的用例
+@SolonTest(classes = BuilderELDeclMultiSpringbootTest2.class)
+public class BuilderELDeclMultiSpringbootTest2 extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 通过spring去扫描组件,通过代码去构建chain
+	@Test
+	public void testBuilder() throws Exception {
+		LiteFlowChainELBuilder.createChain().setChainId("chain1").setEL("THEN(h, i, j)").build();
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("h==>i==>j", response.getExecuteStepStr());
+	}
+
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java

@@ -0,0 +1,28 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.test.builder.domain.TestDomain;
+import org.noear.solon.annotation.Inject;
+
+import javax.annotation.Resource;
+
+public class ACmp {
+
+	@Inject
+	private TestDomain testDomain;
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		testDomain.sayHi();
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class BCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class CCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class DCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("DCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+public class ECmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitch(NodeComponent bindCmp) throws Exception {
+		System.out.println("ECmp executed!");
+		return "chain2";
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class FCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("FCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class GCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("GCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/HCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent("h")
+public class HCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("HCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/ICmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent("i")
+public class ICmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("ICmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/cmp2/JCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.builder.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent("j")
+public class JCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("JCmp executed!");
+	}
+
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/builder/domain/TestDomain.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.builder.domain;
+
+import org.noear.solon.annotation.Component;
+
+@Component
+public class TestDomain {
+
+	public void sayHi() {
+		System.out.println("hello");
+	}
+
+}

+ 56 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpRetry/LiteflowRetryELDeclMultiSpringbootTest.java

@@ -0,0 +1,56 @@
+package com.yomahub.liteflow.test.cmpRetry;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 测试springboot下的节点执行器
+ *
+ * @author Bryan.Zhang
+ * @since 2.5.10
+ */
+@Import(profiles ="classpath:/cmpRetry/application.properties")
+@SolonTest(classes = LiteflowRetryELDeclMultiSpringbootTest.class)
+public class LiteflowRetryELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 全局重试配置测试
+	@Test
+	public void testRetry1() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b==>b==>b", response.getExecuteStepStr());
+	}
+
+	// 单个组件重试配置测试
+	@Test
+	public void testRetry2() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals("c==>c==>c==>c==>c==>c", response.getExecuteStepStr());
+	}
+
+	// 单个组件指定异常,但抛出的并不是指定异常的场景测试
+	@Test
+	public void testRetry3() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		Assertions.assertFalse(response.isSuccess());
+	}
+
+	// 单个组件指定异常重试,抛出的是指定异常或者
+	@Test
+	public void testRetry4() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals("e==>e==>e==>e==>e==>e", response.getExecuteStepStr());
+	}
+
+}

+ 62 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpRetry/cmp/CmpConfig.java

@@ -0,0 +1,62 @@
+package com.yomahub.liteflow.test.cmpRetry.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.annotation.LiteflowRetry;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	private int flag = 0;
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+		if (flag < 2) {
+			flag++;
+			throw new RuntimeException("demo exception");
+		}
+	}
+
+	@LiteflowRetry(5)
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+		throw new RuntimeException("demo exception");
+	}
+
+	@LiteflowRetry(retry = 5, forExceptions = { NullPointerException.class })
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		System.out.println("DCmp executed!");
+		throw new RuntimeException("demo exception");
+	}
+
+	@LiteflowRetry(retry = 5, forExceptions = { NullPointerException.class })
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		System.out.println("ECmp executed!");
+		throw new NullPointerException("demo null exception");
+	}
+
+	@LiteflowRetry(retry = 5, forExceptions = { NullPointerException.class })
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) {
+		System.out.println("ECmp executed!");
+		throw new NullPointerException("demo null exception");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.AFTER_PROCESS, nodeId = "f")
+	public void after(NodeComponent bindCmp) {
+		System.out.println("ECmp executed!");
+		throw new NullPointerException("demo null exception");
+	}
+
+}

+ 66 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpStep/CmpStepELDeclSpringbootTest.java

@@ -0,0 +1,66 @@
+package com.yomahub.liteflow.test.cmpStep;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.flow.entity.CmpStep;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import java.util.*;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/cmpStep/application.properties")
+@SolonTest(classes = CmpStepELDeclSpringbootTest.class)
+public class CmpStepELDeclSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testStep() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertTrue(response.getExecuteSteps().get("a").get(0).isSuccess());
+		Assertions.assertTrue(response.getExecuteSteps().get("b").get(0).isSuccess());
+		Assertions.assertFalse(response.getExecuteSteps().get("c").get(0).isSuccess());
+		Assertions.assertFalse(response.getExecuteSteps().get("d").get(0).isSuccess());
+		Assertions.assertTrue(response.getExecuteSteps().get("c").get(0).getTimeSpent() >= 2000);
+		Assertions.assertEquals(RuntimeException.class, response.getExecuteSteps().get("c").get(0).getException().getClass());
+		Assertions.assertEquals(RuntimeException.class, response.getExecuteSteps().get("d").get(0).getException().getClass());
+	}
+
+	@Test
+	public void testStep2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	@Test
+	public void testStep3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Map<String, List<CmpStep>> stepMap = response.getExecuteSteps();
+		Assertions.assertEquals(2, stepMap.size());
+		Queue<CmpStep> queue = response.getExecuteStepQueue();
+		Assertions.assertEquals(5, queue.size());
+
+		Set<String> tagSet = new HashSet<>();
+		response.getExecuteStepQueue()
+			.stream()
+			.filter(cmpStep -> cmpStep.getNodeId().equals("a"))
+			.forEach(cmpStep -> tagSet.add(cmpStep.getTag()));
+
+		Assertions.assertEquals(3, tagSet.size());
+
+	}
+
+}

+ 45 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/cmpStep/cmp/CmpConfig.java

@@ -0,0 +1,45 @@
+package com.yomahub.liteflow.test.cmpStep.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) throws Exception {
+		Thread.sleep(5000L);
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) throws Exception {
+		System.out.println("CCmp executed!");
+		Thread.sleep(2000);
+		throw new RuntimeException("test error c");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+		throw new RuntimeException("test error d");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		System.out.println("ECmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_ACCESS, nodeId = "e")
+	public boolean isAccessE(NodeComponent bindCmp) {
+		return false;
+	}
+
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/comments/LiteflowNodeELDeclMultiSpringbootTest.java

@@ -0,0 +1,28 @@
+package com.yomahub.liteflow.test.comments;
+
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+@Import(profiles ="classpath:/comments/application.properties")
+@SolonTest(classes = LiteflowNodeELDeclMultiSpringbootTest.class)
+public class LiteflowNodeELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 测试注释
+	@Test
+	public void testAsyncFlow1() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a base request");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(ListUtil.toList("a==>b==>c==>b", "a==>b==>b==>c").contains(response.getExecuteStepStr()));
+	}
+
+}

+ 26 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/comments/cmp/CmpConfig.java

@@ -0,0 +1,26 @@
+package com.yomahub.liteflow.test.comments.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 42 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/ComplexELDeclMultiSpringbootTest1.java

@@ -0,0 +1,42 @@
+package com.yomahub.liteflow.test.complex;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境EL复杂例子测试1
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles ="classpath:/complex/application1.properties")
+@SolonTest(classes = ComplexELDeclMultiSpringbootTest1.class)
+public class ComplexELDeclMultiSpringbootTest1 extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 测试复杂例子,优化前
+	// 案例来自于文档中 EL规则写法/复杂编排例子/复杂例子一
+	// 因为所有的组件都是空执行,你可以在组件里加上Thread.sleep来模拟业务耗时,再来看这个打出结果
+	@Test
+	public void testComplex1_1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1_1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	// 测试复杂例子,优化后
+	// 案例来自于文档中 EL规则写法/复杂编排例子/复杂例子一
+	// 因为所有的组件都是空执行,你可以在组件里加上Thread.sleep来模拟业务耗时,再来看这个打出结果
+	@Test
+	public void testComplex1_2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1_2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 42 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/ComplexELDeclMultiSpringbootTest2.java

@@ -0,0 +1,42 @@
+package com.yomahub.liteflow.test.complex;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境EL复杂例子测试1
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles ="classpath:/complex/application2.properties")
+@SolonTest(classes = ComplexELDeclMultiSpringbootTest2.class)
+public class ComplexELDeclMultiSpringbootTest2 extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 测试复杂例子,优化前
+	// 案例来自于文档中 EL规则写法/复杂编排例子/复杂例子二
+	// 因为所有的组件都是空执行,你可以在组件里加上Thread.sleep来模拟业务耗时,再来看这个打出结果
+	@Test
+	public void testComplex2_1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2_1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	// 测试复杂例子,优化后
+	// 案例来自于文档中 EL规则写法/复杂编排例子/复杂例子二
+	// 因为所有的组件都是空执行,你可以在组件里加上Thread.sleep来模拟业务耗时,再来看这个打出结果
+	@Test
+	public void testComplex2_2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2_2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 82 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp1/CmpConfig1.java

@@ -0,0 +1,82 @@
+package com.yomahub.liteflow.test.complex.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+@LiteflowComponent
+public class CmpConfig1 {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "A")
+	public void processA(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "B")
+	public void processB(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "C")
+	public void processC(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "D")
+	public void processD(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "E")
+	public void processE(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "F")
+	public void processF(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "G", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchG(NodeComponent bindCmp) throws Exception {
+		return "t1";
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "H")
+	public void processH(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "J")
+	public void processJ(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "K")
+	public void processK(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "L")
+	public void processL(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "M")
+	public void processM(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "N")
+	public void processN(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "Z")
+	public void processZ(NodeComponent bindCmp) {
+
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp1/ICmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.complex.cmp1;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.noear.solon.annotation.Component;
+
+@Component("I")
+public class ICmp extends NodeComponent {
+
+	@Override
+	public void process() {
+
+	}
+
+}

+ 82 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp2/CmpConfig2.java

@@ -0,0 +1,82 @@
+package com.yomahub.liteflow.test.complex.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+@LiteflowComponent
+public class CmpConfig2 {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "A")
+	public void processA(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.SWITCH, nodeId = "B")
+	public String processSwitchB(NodeComponent bindCmp) {
+		return "t3";
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "C")
+	public void processC(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "D")
+	public void processD(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "E")
+	public void processE(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "F")
+	public void processF(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.SWITCH, nodeId = "G")
+	public String processSwitchG(NodeComponent bindCmp) throws Exception {
+		return "t2";
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "H")
+	public void processH(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "J")
+	public void processJ(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "K")
+	public void processK(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "L")
+	public void processL(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "M")
+	public void processM(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "N")
+	public void processN(NodeComponent bindCmp) {
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "Z")
+	public void processZ(NodeComponent bindCmp) {
+
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/complex/cmp2/ICmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.complex.cmp2;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.noear.solon.annotation.Component;
+
+@Component("I")
+public class ICmp extends NodeComponent {
+
+	@Override
+	public void process() {
+
+	}
+
+}

+ 90 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/FlowExecutorELDeclMultiSpringbootTest.java

@@ -0,0 +1,90 @@
+package com.yomahub.liteflow.test.component;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 组件功能点测试 单元测试
+ *
+ * @author donguo.tao
+ */
+@Import(profiles ="classpath:/component/application.properties")
+@SolonTest(classes = FlowExecutorELDeclMultiSpringbootTest.class)
+public class FlowExecutorELDeclMultiSpringbootTest extends BaseTest {
+
+	private static final Logger LOG = LoggerFactory.getLogger(FlowExecutorELDeclMultiSpringbootTest.class);
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// isAccess方法的功能测试
+	@Test
+	public void testIsAccess() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", 101);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertNotNull(response.getSlot().getResponseData());
+	}
+
+	// 组件抛错的功能点测试
+	@Test
+	public void testComponentException() throws Exception {
+		Assertions.assertThrows(ArithmeticException.class, () -> {
+			LiteflowResponse response = flowExecutor.execute2Resp("chain2", 0);
+			Assertions.assertFalse(response.isSuccess());
+			Assertions.assertEquals("/ by zero", response.getMessage());
+
+			if(response.getCause() != null) {
+				throw response.getCause();
+			}
+			//ReflectionUtils.rethrowException(response.getCause());
+		});
+	}
+
+	// isContinueOnError方法的功能点测试
+	@Test
+	public void testIsContinueOnError() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", 0);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertNull(response.getCause());
+	}
+
+	// isEnd方法的功能点测试
+	@Test
+	public void testIsEnd() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", 10);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("d", response.getExecuteStepStr());
+	}
+
+	// setIsEnd方法的功能点测试
+	@Test
+	public void testSetIsEnd1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", 10);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("e", response.getExecuteStepStr());
+	}
+
+	// 条件组件的功能点测试
+	@Test
+	public void testNodeCondComponent() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", 0);
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	// 测试setIsEnd如果为true,continueError也为true,那不应该continue了
+	@Test
+	public void testSetIsEnd2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain7", 10);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("g", response.getExecuteStepStr());
+	}
+
+}

+ 111 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/cmp1/CmpConfig1.java

@@ -0,0 +1,111 @@
+package com.yomahub.liteflow.test.component.cmp1;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Objects;
+
+@LiteflowComponent
+public class CmpConfig1 {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("AComp executed!");
+		bindCmp.getSlot().setResponseData("AComp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_ACCESS, nodeId = "a")
+	public boolean isAccessA(NodeComponent bindCmp) {
+		Integer requestData = bindCmp.getRequestData();
+		if (Objects.nonNull(requestData) && requestData > 100) {
+			return true;
+		}
+		System.out.println("AComp isAccess false.");
+		return false;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BComp executed!");
+		Integer requestData = bindCmp.getRequestData();
+		Integer divisor = 130;
+		Integer result = divisor / requestData;
+		bindCmp.getSlot().setResponseData(result);
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_ACCESS, nodeId = "b")
+	public boolean isAccessB(NodeComponent bindCmp) {
+		Integer requestData = bindCmp.getRequestData();
+		if (Objects.nonNull(requestData)) {
+			return true;
+		}
+		return false;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CComp executed!");
+		Integer requestData = bindCmp.getRequestData();
+		Integer divisor = 130;
+		Integer result = divisor / requestData;
+		bindCmp.getSlot().setResponseData(result);
+		System.out.println("responseData=" + Integer.parseInt(bindCmp.getSlot().getResponseData()));
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_CONTINUE_ON_ERROR, nodeId = "c")
+	public boolean isContinueOnErrorC(NodeComponent bindCmp) {
+		Integer requestData = bindCmp.getRequestData();
+		if (Objects.nonNull(requestData)) {
+			return true;
+		}
+		return false;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) throws Exception {
+		System.out.println("DComp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_END, nodeId = "d")
+	public boolean isEndD(NodeComponent bindCmp) {
+		// 组件的process执行完之后才会执行isEnd
+		Object requestData = bindCmp.getSlot().getResponseData();
+		if (Objects.isNull(requestData)) {
+			System.out.println("DComp flow isEnd, because of responseData is null.");
+			return true;
+		}
+		return false;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) throws Exception {
+		System.out.println("EComp executed!");
+		Object responseData = bindCmp.getSlot().getResponseData();
+		if (Objects.isNull(responseData)) {
+			System.out.println("EComp responseData flow must be set end .");
+			// 执行到某个条件时,手动结束流程。
+			bindCmp.setIsEnd(true);
+		}
+		System.out.println("EComp responseData responseData=" + JsonUtil.toJsonString(responseData));
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "g")
+	public void processF(NodeComponent bindCmp) {
+		System.out.println("GCmp executed!");
+		bindCmp.setIsEnd(true);
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_CONTINUE_ON_ERROR, nodeId = "g")
+	public boolean isContinueOnError(NodeComponent bindCmp) {
+		return true;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "h")
+	public void processH(NodeComponent bindCmp) {
+		System.out.println("HCmp executed!");
+	}
+
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/component/cmp2/FCondCmp.java

@@ -0,0 +1,28 @@
+package com.yomahub.liteflow.test.component.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+import java.util.Objects;
+
+@LiteflowComponent
+public class FCondCmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "f", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchF(NodeComponent bindCmp) {
+		Integer requestData = bindCmp.getRequestData();
+		if (Objects.isNull(requestData)) {
+			return "d";
+		}
+		else if (requestData == 0) {
+			return "c";
+		}
+		else {
+			return "b";
+		}
+	}
+
+}

+ 31 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customMethodName/CustomMethodNameELDeclMultiSpringbootTest.java

@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.test.customMethodName;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 声明式组件自定义方法的测试用例
+ *
+ * @author Bryan.Zhang
+ * @since 2.7.2
+ */
+@Import(profiles ="classpath:/customMethodName/application.properties")
+@SolonTest(classes = CustomMethodNameELDeclMultiSpringbootTest.class)
+public class CustomMethodNameELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testCustomMethodName() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 54 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customMethodName/cmp/CmpConfig.java

@@ -0,0 +1,54 @@
+package com.yomahub.liteflow.test.customMethodName.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.slot.Slot;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processAcmp(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_ACCESS, nodeId = "a")
+	public boolean isAcmpAccess(NodeComponent bindCmp) {
+		return true;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.BEFORE_PROCESS, nodeId = "a")
+	public void beforeAcmp(NodeComponent bindCmp) {
+		System.out.println("before A");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.AFTER_PROCESS, nodeId = "a")
+	public void afterAcmp(NodeComponent bindCmp) {
+		System.out.println("after A");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_SUCCESS, nodeId = "a")
+	public void onAcmpSuccess(NodeComponent bindCmp) {
+		System.out.println("Acmp success");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_ERROR, nodeId = "a")
+	public void onAcmpError(NodeComponent bindCmp) {
+		System.out.println("Acmp error");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.IS_END, nodeId = "a")
+	public boolean isAcmpEnd(NodeComponent bindCmp) {
+		System.out.println("Acmp end config");
+		return false;
+	}
+
+	///////////////////////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processBcmp(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 37 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/CustomNodesELDeclMultiSpringbootTest.java

@@ -0,0 +1,37 @@
+package com.yomahub.liteflow.test.customNodes;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * springboot环境下自定义声明节点的测试 不通过spring扫描的方式,通过在配置文件里定义nodes的方式
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/customNodes/application.properties")
+@SolonTest(classes = CustomNodesELDeclMultiSpringbootTest.class)
+public class CustomNodesELDeclMultiSpringbootTest extends BaseTest {
+
+	private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testCustomNodes() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/ACmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class ACmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/BCmp.java

@@ -0,0 +1,29 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.test.customNodes.domain.DemoDomain;
+import org.noear.solon.annotation.Inject;
+
+import javax.annotation.Resource;
+
+public class BCmp {
+
+	@Inject
+	private DemoDomain demoDomain;
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		demoDomain.sayHi();
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/CCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class CCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/DCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class DCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("DCmp executed!");
+	}
+
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/ECmp.java

@@ -0,0 +1,29 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.test.customNodes.domain.DemoDomain;
+import org.noear.solon.annotation.Inject;
+
+import javax.annotation.Resource;
+
+public class ECmp {
+
+	@Inject
+	private DemoDomain demoDomain;
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		demoDomain.sayHi();
+		System.out.println("ECmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/cmp/FCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.customNodes.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+public class FCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("FCmp executed!");
+	}
+
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customNodes/domain/DemoDomain.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.customNodes.domain;
+
+import org.noear.solon.annotation.Component;
+
+@Component
+public class DemoDomain {
+
+	public void sayHi() {
+		System.out.println("hi");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor1.java

@@ -0,0 +1,23 @@
+package com.yomahub.liteflow.test.customWhenThreadPool;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.thread.ExecutorBuilder;
+
+import java.util.concurrent.ExecutorService;
+
+public class CustomThreadExecutor1 implements ExecutorBuilder {
+
+	@Override
+	public ExecutorService buildExecutor() {
+		LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
+		// 只有在非spring的场景下liteflowConfig才会为null
+		if (ObjectUtil.isNull(liteflowConfig)) {
+			liteflowConfig = new LiteflowConfig();
+		}
+		return buildDefaultExecutor(liteflowConfig.getWhenMaxWorkers(), liteflowConfig.getWhenMaxWorkers(),
+				liteflowConfig.getWhenQueueLimit(), "customer-when-1-thead-");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor2.java

@@ -0,0 +1,23 @@
+package com.yomahub.liteflow.test.customWhenThreadPool;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.thread.ExecutorBuilder;
+
+import java.util.concurrent.ExecutorService;
+
+public class CustomThreadExecutor2 implements ExecutorBuilder {
+
+	@Override
+	public ExecutorService buildExecutor() {
+		LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
+		// 只有在非spring的场景下liteflowConfig才会为null
+		if (ObjectUtil.isNull(liteflowConfig)) {
+			liteflowConfig = new LiteflowConfig();
+		}
+		return buildDefaultExecutor(liteflowConfig.getWhenMaxWorkers(), liteflowConfig.getWhenMaxWorkers(),
+				liteflowConfig.getWhenQueueLimit(), "customer-when-2-thead-");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomThreadExecutor3.java

@@ -0,0 +1,23 @@
+package com.yomahub.liteflow.test.customWhenThreadPool;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.thread.ExecutorBuilder;
+
+import java.util.concurrent.ExecutorService;
+
+public class CustomThreadExecutor3 implements ExecutorBuilder {
+
+	@Override
+	public ExecutorService buildExecutor() {
+		LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
+		// 只有在非spring的场景下liteflowConfig才会为null
+		if (ObjectUtil.isNull(liteflowConfig)) {
+			liteflowConfig = new LiteflowConfig();
+		}
+		return buildDefaultExecutor(liteflowConfig.getWhenMaxWorkers(), liteflowConfig.getWhenMaxWorkers(),
+				liteflowConfig.getWhenQueueLimit(), "customer-when-3-thead-");
+	}
+
+}

+ 67 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/CustomWhenThreadPoolELDeclMultiSpringbootTest.java

@@ -0,0 +1,67 @@
+package com.yomahub.liteflow.test.customWhenThreadPool;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * springboot环境下异步线程超时日志打印测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/customWhenThreadPool/application.properties")
+@SolonTest(classes = CustomWhenThreadPoolELDeclMultiSpringbootTest.class)
+public class CustomWhenThreadPoolELDeclMultiSpringbootTest extends BaseTest {
+
+	private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	/**
+	 * 测试全局线程池配置
+	 */
+	@Test
+	public void testGlobalThreadPool() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertTrue(context.getData("threadName").toString().startsWith("when-thread-1"));
+	}
+
+	/**
+	 * 测试全局和when上自定义线程池-优先以when上为准
+	 */
+	@Test
+	public void testGlobalAndCustomWhenThreadPool() {
+		LiteflowResponse response1 = flowExecutor.execute2Resp("chain1", "arg");
+		DefaultContext context = response1.getFirstContextBean();
+		Assertions.assertTrue(response1.isSuccess());
+		Assertions.assertTrue(context.getData("threadName").toString().startsWith("customer-when-1-thead"));
+	}
+
+	/**
+	 * when配置的线程池可以共用
+	 */
+	@Test
+	public void testCustomWhenThreadPool() {
+		// 使用when - thread1
+		testGlobalAndCustomWhenThreadPool();
+		// chain配置同一个thead1
+		LiteflowResponse response2 = flowExecutor.execute2Resp("chain2", "arg");
+		DefaultContext context = response2.getFirstContextBean();
+		Assertions.assertTrue(response2.isSuccess());
+		Assertions.assertTrue(context.getData("threadName").toString().startsWith("customer-when-1-thead"));
+
+	}
+
+}

+ 53 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/customWhenThreadPool/cmp/CmpConfig.java

@@ -0,0 +1,53 @@
+package com.yomahub.liteflow.test.customWhenThreadPool.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("threadName", Thread.currentThread().getName());
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("threadName", Thread.currentThread().getName());
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("threadName", Thread.currentThread().getName());
+		System.out.println("DCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("threadName", Thread.currentThread().getName());
+		System.out.println("ECmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("threadName", Thread.currentThread().getName());
+		System.out.println("FCmp executed!");
+	}
+
+}

+ 57 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/event/EventELDeclMultiSpringbootTest.java

@@ -0,0 +1,57 @@
+package com.yomahub.liteflow.test.event;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/event/application.properties")
+@SolonTest(classes = EventELDeclMultiSpringbootTest.class)
+public class EventELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 测试组件成功事件
+	@Test
+	public void testEvent1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("abc", context.getData("test"));
+	}
+
+	// 测试组件失败事件
+	@Test
+	public void testEvent2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals(NullPointerException.class, response.getCause().getClass());
+		Assertions.assertEquals("ab", context.getData("test"));
+		Assertions.assertEquals("error:d", context.getData("error"));
+	}
+
+	// 测试组件失败事件本身抛出异常
+	@Test
+	public void testEvent3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals(NullPointerException.class, response.getCause().getClass());
+		Assertions.assertEquals("a", context.getData("test"));
+		Assertions.assertEquals("error:e", context.getData("error"));
+	}
+
+}

+ 82 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/event/cmp/CmpConfig.java

@@ -0,0 +1,82 @@
+package com.yomahub.liteflow.test.event.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("test", "");
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_SUCCESS, nodeId = "a")
+	public void onSuccessA(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String str = context.getData("test");
+		str += bindCmp.getNodeId();
+		context.setData("test", str);
+	}
+
+	////////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_SUCCESS, nodeId = "b")
+	public void onSuccessB(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String str = context.getData("test");
+		str += bindCmp.getNodeId();
+		context.setData("test", str);
+	}
+
+	///////////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_SUCCESS, nodeId = "c")
+	public void onSuccessC(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String str = context.getData("test");
+		str += bindCmp.getNodeId();
+		context.setData("test", str);
+	}
+
+	///////////////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) throws Exception {
+		System.out.println("CCmp executed!");
+		throw new NullPointerException();
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_ERROR, nodeId = "d")
+	public void onErrorD(NodeComponent bindCmp, Exception e) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("error", "error:" + bindCmp.getNodeId());
+	}
+
+	///////////////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) throws Exception {
+		System.out.println("CCmp executed!");
+		throw new NullPointerException();
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.ON_ERROR, nodeId = "e")
+	public void onErrorE(NodeComponent bindCmp,Exception e) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData("error", "error:" + bindCmp.getNodeId());
+		throw new IllegalAccessException("错误事件回调本身抛出异常");
+	}
+
+}

+ 14 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/CustomStatefulException.java

@@ -0,0 +1,14 @@
+package com.yomahub.liteflow.test.exception;
+
+import com.yomahub.liteflow.exception.LiteFlowException;
+
+/**
+ * 用户自定义带状态码的异常
+ */
+public class CustomStatefulException extends LiteFlowException {
+
+	public CustomStatefulException(String code, String message) {
+		super(code, message);
+	}
+
+}

+ 63 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/Exception1ELDeclMultiSpringBootTest.java

@@ -0,0 +1,63 @@
+package com.yomahub.liteflow.test.exception;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.exception.ChainDuplicateException;
+import com.yomahub.liteflow.exception.ConfigErrorException;
+import com.yomahub.liteflow.exception.FlowExecutorNotInitException;
+import com.yomahub.liteflow.property.LiteflowConfig;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 流程执行异常 单元测试
+ *
+ * @author zendwang
+ */
+@SolonTest(classes = Exception1ELDeclMultiSpringBootTest.class)
+public class Exception1ELDeclMultiSpringBootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	/**
+	 * 验证 chain 节点重复的异常
+	 */
+	@Test
+	public void testChainDuplicateException() {
+		Assertions.assertThrows(ChainDuplicateException.class, () -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("exception/flow-exception.el.xml");
+			flowExecutor.reloadRule();
+		});
+	}
+
+	@Test
+	public void testConfigErrorException() {
+		Assertions.assertThrows(ConfigErrorException.class, () -> {
+			flowExecutor.setLiteflowConfig(null);
+			flowExecutor.reloadRule();
+		});
+	}
+
+	@Test
+	public void testFlowExecutorNotInitException() {
+		Assertions.assertThrows(FlowExecutorNotInitException.class, () -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("error/flow.txt");
+			flowExecutor.reloadRule();
+		});
+	}
+
+	@Test
+	public void testNoConditionInChainException() throws Exception {
+		Assertions.assertThrows(FlowExecutorNotInitException.class, () -> {
+			LiteflowConfig config = LiteflowConfigGetter.get();
+			config.setRuleSource("exception/flow-blank.el.xml");
+			flowExecutor.reloadRule();
+		});
+	}
+}

+ 72 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/Exception2ELDeclMultiSpringBootTest.java

@@ -0,0 +1,72 @@
+package com.yomahub.liteflow.test.exception;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.exception.ChainNotFoundException;
+import com.yomahub.liteflow.exception.LiteFlowException;
+import com.yomahub.liteflow.exception.NoSwitchTargetNodeException;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 流程执行异常 单元测试
+ *
+ * @author zendwang
+ */
+@Import(profiles ="classpath:/exception/application.properties")
+@SolonTest(classes = Exception2ELDeclMultiSpringBootTest.class)
+public class Exception2ELDeclMultiSpringBootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testChainNotFoundException() throws Exception {
+		Assertions.assertThrows(ChainNotFoundException.class, () -> flowExecutor.execute("chain0", "it's a request"));
+
+	}
+
+	@Test
+	public void testComponentCustomException() throws Exception {
+		Assertions.assertThrows(RuntimeException.class, () -> flowExecutor.execute("chain1", "exception"));
+	}
+
+	@Test
+	public void testGetSlotFromResponseWhenException() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "test");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertNotNull(response.getCause());
+		Assertions.assertNotNull(response.getSlot());
+	}
+
+	@Test
+	public void testNoTargetFindException() throws Exception {
+		Assertions.assertThrows(NoSwitchTargetNodeException.class, () -> {
+			LiteflowResponse response = flowExecutor.execute2Resp("chain5", "test");
+			Assertions.assertFalse(response.isSuccess());
+			throw response.getCause();
+		});
+	}
+
+	@Test
+	public void testInvokeCustomStatefulException() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", "custom-stateful-exception");
+		Assertions.assertFalse(response.isSuccess());
+		Assertions.assertEquals("300", response.getCode());
+		Assertions.assertNotNull(response.getCause());
+		Assertions.assertTrue(response.getCause() instanceof LiteFlowException);
+		Assertions.assertNotNull(response.getSlot());
+	}
+
+	@Test
+	public void testNotInvokeCustomStatefulException() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", "test");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertNull(response.getCode());
+	}
+
+}

+ 81 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/exception/cmp/CmpConfig.java

@@ -0,0 +1,81 @@
+package com.yomahub.liteflow.test.exception.cmp;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.test.exception.CustomStatefulException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	private static final Logger LOG = LoggerFactory.getLogger(CmpConfig.class);
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		String str = bindCmp.getRequestData();
+		if (StrUtil.isNotBlank(str) && str.equals("exception")) {
+			throw new RuntimeException("chain execute execption");
+		}
+		LOG.info("Acomp executed!");
+	}
+
+	//////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) throws InterruptedException {
+		String str = bindCmp.getRequestData();
+		if (StrUtil.isNotBlank(str) && str.equals("when")) {
+			try {
+				LOG.info("Bcomp sleep begin");
+				Thread.sleep(3000);
+				LOG.info("Bcomp sleep end");
+			}
+			catch (InterruptedException e) {
+				throw e;
+			}
+		}
+		LOG.info("Bcomp executed!");
+	}
+
+	//////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		LOG.info("Ccomp executed!");
+	}
+
+	//////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		if (1 == 1) {
+			int a = 1 / 0;
+		}
+		LOG.info("Dcomp executed!");
+	}
+
+	////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "e", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchE(NodeComponent bindCmp) throws Exception {
+		return "a";
+	}
+
+	//////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) {
+		String str = bindCmp.getRequestData();
+		if (StrUtil.isNotBlank(str) && str.equals("custom-stateful-exception")) {
+			throw new CustomStatefulException("300", "chain execute custom stateful execption");
+		}
+		LOG.info("Fcomp executed!");
+	}
+
+	////////
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "g")
+	public void processG(NodeComponent bindCmp) {
+		LOG.info("Gcomp executed!");
+	}
+
+}

+ 34 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/execute2Future/Executor2FutureELDeclMultiSpringbootTest.java

@@ -0,0 +1,34 @@
+package com.yomahub.liteflow.test.execute2Future;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import java.util.concurrent.Future;
+
+/**
+ * springboot环境执行返回future的例子
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.13
+ */
+@Import(profiles ="classpath:/execute2Future/application.properties")
+@SolonTest(classes = Executor2FutureELDeclMultiSpringbootTest.class)
+public class Executor2FutureELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testFuture() throws Exception {
+		Future<LiteflowResponse> future = flowExecutor.execute2Future("chain1", "arg", DefaultContext.class);
+		LiteflowResponse response = future.get();
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/execute2Future/cmp/CmpConfig.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.execute2Future.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 31 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/extend/CmpExtendELDeclMultiSpringbootTest.java

@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.test.extend;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境测试声明式组件继承其他类的场景
+ *
+ * @author Bryan.Zhang
+ * @since 2.7.1
+ */
+@Import(profiles = "classpath:/extend/application.properties")
+@SolonTest(classes = CmpExtendELDeclMultiSpringbootTest.class)
+public class CmpExtendELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testExtend() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+}

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/extend/cmp/CmpConfig.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.extend.cmp;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+		System.out.println(this.sayHi("jack"));
+	}
+
+	protected String sayHi(String name) {
+		return StrUtil.format("hi,{}", name);
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 53 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/getChainName/GetChainNameELDeclMultiSpringbootTest.java

@@ -0,0 +1,53 @@
+package com.yomahub.liteflow.test.getChainName;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境获取ChainName的测试
+ *
+ * @author Bryan.Zhang
+ */
+@Import(profiles ="classpath:/getChainName/application.properties")
+@SolonTest(classes = GetChainNameELDeclMultiSpringbootTest.class)
+public class GetChainNameELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testGetChainName1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("sub1", context.getData("a"));
+		Assertions.assertEquals("sub2", context.getData("b"));
+		Assertions.assertEquals("sub3", context.getData("c"));
+		Assertions.assertEquals("sub4", context.getData("d"));
+	}
+
+	@Test
+	public void testGetChainName2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("chain2", context.getData("g"));
+		Assertions.assertEquals("sub1", context.getData("a"));
+		Assertions.assertEquals("sub2", context.getData("b"));
+		Assertions.assertEquals("sub3", context.getData("c"));
+		Assertions.assertEquals("sub4", context.getData("d"));
+		Assertions.assertEquals("sub5", context.getData("f"));
+		Assertions.assertEquals("sub5_chain2", context.getData("e"));
+		Assertions.assertEquals("sub6", context.getData("h"));
+		Assertions.assertEquals("sub6", context.getData("j"));
+		Assertions.assertNull(context.getData("k"));
+	}
+
+}

+ 79 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/getChainName/cmp/CmpConfig.java

@@ -0,0 +1,79 @@
+package com.yomahub.liteflow.test.getChainName.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		if (context.hasData(bindCmp.getNodeId())) {
+			context.setData(bindCmp.getNodeId(), context.getData(bindCmp.getNodeId()) + "_" + bindCmp.getCurrChainId());
+		}
+		else {
+			context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+		}
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "f")
+	public void processF(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "g")
+	public void processG(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "h", nodeType = NodeTypeEnum.SWITCH)
+	public String processSwitchH(NodeComponent bindCmp) throws Exception {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+		return "j";
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "j")
+	public void processJ(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "k")
+	public void process(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		context.setData(bindCmp.getNodeId(), bindCmp.getCurrChainId());
+	}
+
+}

+ 81 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/ifelse/IfElseELDeclMultiSpringbootTest.java

@@ -0,0 +1,81 @@
+package com.yomahub.liteflow.test.ifelse;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/ifelse/application.properties")
+@SolonTest(classes = IfElseELDeclMultiSpringbootTest.class)
+public class IfElseELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// IF只有2个参数
+	@Test
+	public void testIf1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>a==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	// IF只有3个参数
+	@Test
+	public void testIf2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>c==>d", response.getExecuteStepStrWithoutTime());
+	}
+
+	// IF有3个参数,进行嵌套
+	@Test
+	public void testIf3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>x1==>c==>c==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	// IF有2个参数,加上ELSE
+	@Test
+	public void testIf4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>c==>d", response.getExecuteStepStrWithoutTime());
+	}
+
+	// IF有2个参数,ELSE里再嵌套一个IF
+	@Test
+	public void testIf5() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>x1==>c==>c==>b", response.getExecuteStepStrWithoutTime());
+	}
+
+	// 标准的IF ELIF ELSE
+	@Test
+	public void testIf6() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>x1==>c==>c", response.getExecuteStepStrWithoutTime());
+	}
+
+	// IF ELIF... ELSE 的形式
+	@Test
+	public void testIf7() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain7", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x1==>x1==>x1==>x1==>d==>b==>a", response.getExecuteStepStrWithoutTime());
+	}
+
+}

+ 38 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/ifelse/cmp/CmpConfig.java

@@ -0,0 +1,38 @@
+package com.yomahub.liteflow.test.ifelse.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		System.out.println("DCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "x1", nodeType = NodeTypeEnum.BOOLEAN)
+	public boolean processIfX1(NodeComponent bindCmp) throws Exception {
+		return Boolean.parseBoolean(bindCmp.getTag());
+	}
+
+}

+ 50 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/iterator/IteratorELDeclMultiSpringbootTest.java

@@ -0,0 +1,50 @@
+package com.yomahub.liteflow.test.iterator;
+
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import java.util.List;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/iterator/application.properties")
+@SolonTest(classes = IteratorELDeclMultiSpringbootTest.class)
+public class IteratorELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// 最简单的情况
+	@Test
+	public void testIt1() throws Exception {
+		List<String> list = ListUtil.toList("1", "2", "3");
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
+		Assertions.assertTrue(response.isSuccess());
+		DefaultContext context = response.getFirstContextBean();
+		String str = context.getData("test");
+		Assertions.assertEquals("123", str);
+	}
+
+	// 迭代器带break
+	@Test
+	public void testIt2() throws Exception {
+		List<String> list = ListUtil.toList("1", "2", "3");
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
+		Assertions.assertTrue(response.isSuccess());
+		DefaultContext context = response.getFirstContextBean();
+		String str = context.getData("test");
+		Assertions.assertEquals("12", str);
+	}
+
+}

+ 43 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/iterator/cmp/CmpConfig.java

@@ -0,0 +1,43 @@
+package com.yomahub.liteflow.test.iterator.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.base.cmp.TestDomain;
+
+import javax.annotation.Resource;
+import java.util.Iterator;
+import java.util.List;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		String key = "test";
+		DefaultContext context = bindCmp.getFirstContextBean();
+		if (!context.hasData(key)) {
+			context.setData(key, bindCmp.getCurrLoopObj());
+		}
+		else {
+			String str = context.getData(key);
+			str += bindCmp.getCurrLoopObj();
+			context.setData(key, str);
+		}
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "b", nodeType = NodeTypeEnum.BOOLEAN)
+	public boolean processB(NodeComponent bindCmp) {
+		return bindCmp.getLoopIndex() == 1;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeId = "it", nodeType = NodeTypeEnum.ITERATOR)
+	public Iterator<?> processIT(NodeComponent bindCmp) {
+		List<String> list = bindCmp.getRequestData();
+		return list.iterator();
+	}
+
+}

+ 20 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/LazyELDeclMultiSpringbootTest.java

@@ -0,0 +1,20 @@
+package com.yomahub.liteflow.test.lazy;
+
+import com.yomahub.liteflow.test.BaseTest;
+
+//spring的延迟加载在el表达形式模式下不起作用
+/*
+@Import(profiles ="classpath:/lazy/application.properties")
+@SolonTest(classes = LazyELDeclSpringbootTest.class)
+*/
+public class LazyELDeclMultiSpringbootTest extends BaseTest {
+
+	/*
+	 * @Inject private FlowExecutor flowExecutor;
+	 *
+	 * @Test public void testLazy() throws Exception{ LiteflowResponse response =
+	 * flowExecutor.execute2Resp("chain1", "arg");
+	 * Assertions.assertTrue(response.isSuccess()); }
+	 */
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/ACmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lazy.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import org.noear.solon.annotation.Component;
+
+@Component("a")
+public class ACmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/BCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lazy.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import org.noear.solon.annotation.Component;
+
+@Component("b")
+public class BCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lazy/cmp/CCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lazy.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import org.noear.solon.annotation.Component;
+
+@Component("c")
+public class CCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/LiteflowComponentELDeclMultiSpringbootTest.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.lfCmpAnno;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * 测试@LiteflowComponent标注
+ *
+ * @author Bryan.Zhang
+ * @since 2.5.10
+ */
+@Import(profiles ="classpath:/lfCmpAnno/application.properties")
+@SolonTest(classes = LiteflowComponentELDeclMultiSpringbootTest.class)
+public class LiteflowComponentELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testConfig() {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("a[A组件]==>b[B组件]==>c[C组件]==>b[B组件]==>a[A组件]==>d", response.getExecuteStepStr());
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/ACmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lfCmpAnno.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent(id = "a", name = "A组件")
+public class ACmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/BCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lfCmpAnno.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent(id = "b", name = "B组件")
+public class BCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/CCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lfCmpAnno.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent(id = "c", name = "C组件")
+public class CCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/lfCmpAnno/cmp/DCmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.lfCmpAnno.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+@LiteflowComponent("d")
+public class DCmp {
+
+	@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+	public void process(NodeComponent bindCmp) {
+		System.out.println("DCmp executed!");
+	}
+
+}

+ 89 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/loop/LoopELDeclMultiSpringbootTest.java

@@ -0,0 +1,89 @@
+package com.yomahub.liteflow.test.loop;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/loop/application.properties")
+@SolonTest(classes = LoopELDeclMultiSpringbootTest.class)
+public class LoopELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	// FOR循环数字直接在el中定义
+	@Test
+	public void testLoop1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("LOOP_2==>a==>b==>c==>a==>b==>c", response.getExecuteStepStr());
+	}
+
+	// FPR循环由For组件定义
+	@Test
+	public void testLoop2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("x==>a==>b==>c==>a==>b==>c==>a==>b==>c", response.getExecuteStepStr());
+	}
+
+	// FOR循环中加入BREAK组件
+	@Test
+	public void testLoop3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		Assertions.assertTrue(response.isSuccess());
+	}
+
+	// WHILE循环
+	@Test
+	public void testLoop4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("z==>a==>d==>z==>a==>d==>z==>a==>d==>z==>a==>d==>z==>a==>d==>z",
+				response.getExecuteStepStr());
+	}
+
+	// WHILE循环加入BREAK
+	@Test
+	public void testLoop5() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg");
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("z==>a==>d==>y==>z==>a==>d==>y==>z==>a==>d==>y==>z==>a==>d==>y",
+				response.getExecuteStepStr());
+	}
+
+	// 测试FOR循环中的index
+	@Test
+	public void testLoop6() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain6", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("01234", context.getData("loop_e1"));
+		Assertions.assertEquals("01234", context.getData("loop_e2"));
+		Assertions.assertEquals("01234", context.getData("loop_e3"));
+	}
+
+	// 测试WHILE循环中的index
+	@Test
+	public void testLoop7() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain7", "arg");
+		DefaultContext context = response.getFirstContextBean();
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("01234", context.getData("loop_e1"));
+		Assertions.assertEquals("01234", context.getData("loop_e2"));
+		Assertions.assertEquals("01234", context.getData("loop_e3"));
+	}
+
+}

+ 82 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/loop/cmp/CmpConfig.java

@@ -0,0 +1,82 @@
+package com.yomahub.liteflow.test.loop.cmp;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String key = "test";
+		if (context.hasData(key)) {
+			int count = context.getData(key);
+			context.setData(key, ++count);
+		}
+		else {
+			context.setData(key, 1);
+		}
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "e")
+	public void processE(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String key = StrUtil.format("{}_{}", "loop", bindCmp.getTag());
+		if (context.hasData(key)) {
+			String loopStr = context.getData(key);
+			String loopStrReturn = StrUtil.format("{}{}", loopStr, bindCmp.getLoopIndex());
+			context.setData(key, loopStrReturn);
+		}
+		else {
+			context.setData(key, bindCmp.getLoopIndex().toString());
+		}
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_FOR, nodeId = "x", nodeType = NodeTypeEnum.FOR)
+	public int processX(NodeComponent bindCmp) {
+		return 3;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "y", nodeType = NodeTypeEnum.BOOLEAN)
+	public boolean processY(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		int count = context.getData("test");
+		return count > 3;
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "z", nodeType = NodeTypeEnum.BOOLEAN)
+	public boolean processZ(NodeComponent bindCmp) {
+		DefaultContext context = bindCmp.getFirstContextBean();
+		String key = "test";
+		if (context.hasData(key)) {
+			int count = context.getData("test");
+			return count < 5;
+		}
+		else {
+			return true;
+		}
+	}
+
+}

+ 171 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclMultiSpringbootTest.java

@@ -0,0 +1,171 @@
+package com.yomahub.liteflow.test.maxWaitMilliseconds;
+
+import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.exception.WhenTimeoutException;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import java.util.concurrent.TimeoutException;
+
+import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.CmpConfig.CONTENT_KEY;
+
+/**
+ * Spring Boot 环境下超时控制测试 - maxWaitMilliseconds
+ *
+ * @author Kugaaa
+ * @since 2.11.1
+ */
+@Import(profiles ="classpath:/maxWaitMilliseconds/application.properties")
+@SolonTest(classes = MaxWaitMillisecondsELDeclMultiSpringbootTest.class)
+public class MaxWaitMillisecondsELDeclMultiSpringbootTest extends BaseTest {
+    @Inject
+    private FlowExecutor flowExecutor;
+
+    // 测试 THEN 的超时情况
+    @Test
+    public void testThen1() {
+        assertTimeout("then1");
+    }
+
+    // 测试 THEN 的非超时情况
+    @Test
+    public void testThen2() {
+        assertNotTimeout("then2");
+    }
+
+    // 测试 When 的超时情况
+    @Test
+    public void testWhen1() {
+        assertWhenTimeout("when1");
+    }
+
+    // 测试 WHEN 的非超时情况
+    @Test
+    public void testWhen2() {
+        assertNotTimeout("when2");
+    }
+
+    // 测试 FOR 的超时情况
+    @Test
+    public void testFor1() {
+        assertTimeout("for1");
+    }
+
+    // 测试 FOR 的非超时情况
+    @Test
+    public void testFor2() {
+        assertNotTimeout("for2");
+    }
+
+    // 测试 WHILE 的超时情况
+    @Test
+    public void testWhile1() {
+        assertTimeout("while1");
+    }
+
+    // 测试 WHILE 的非超时情况
+    @Test
+    public void testWhile2() {
+        assertNotTimeout("while2");
+    }
+
+    // 测试 ITERATOR 的超时情况
+    @Test
+    public void testIterator1() {
+        assertTimeout("iterator1");
+    }
+
+    // 测试 ITERATOR 的非超时情况
+    @Test
+    public void testIterator2() {
+        assertNotTimeout("iterator2");
+    }
+
+    // 测试 SWITCH 的超时情况
+    @Test
+    public void testSwitch1() {
+        assertTimeout("switch1");
+    }
+
+    // 测试 SWITCH 的非超时情况
+    @Test
+    public void testSwitch2() {
+        assertNotTimeout("switch2");
+    }
+
+    // 测试 IF 的超时情况
+    @Test
+    public void testIf1() {
+        assertTimeout("if1");
+    }
+
+    // 测试 SWITCH 的非超时情况
+    @Test
+    public void testIf2() {
+        assertNotTimeout("if2");
+    }
+
+    // 测试单个组件的超时情况
+    @Test
+    public void testComponent1() {
+        assertTimeout("component1");
+    }
+
+    // 测试单个组件的非超时情况
+    @Test
+    public void testComponent2() {
+        assertNotTimeout("component2");
+    }
+
+    // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行
+    @Test
+    public void testFinally1() {
+        LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
+        // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY
+        DefaultContext contextBean = response.getFirstContextBean();
+        Assertions.assertTrue(contextBean.hasData(CONTENT_KEY));
+    }
+
+    // 测试 maxWaitMilliseconds 关键字不能作用于 Finally
+    @Test
+    public void testFinally2() {
+        Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))"));
+    }
+
+    // 测试 chain 的超时情况
+    @Test
+    public void testChain1() {
+        assertTimeout("chain1");
+    }
+
+    // 测试 chain 的非超时情况
+    @Test
+    public void testChain2() {
+        assertNotTimeout("chain2");
+    }
+
+    private void assertTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
+    }
+
+    private void assertWhenTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass());
+    }
+
+    private void assertNotTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertTrue(response.isSuccess());
+    }
+}

+ 98 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CmpConfig.java

@@ -0,0 +1,98 @@
+package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp;
+
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+@LiteflowComponent
+public class CmpConfig {
+
+    public static final String CONTENT_KEY = "testKey";
+
+    private int count = 0;
+
+    // 执行过的 chain
+    Set<String> executedChain = new HashSet<>();
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+    public void processA(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(100);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("ACmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+    public void processB(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(200);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("BCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+    public void process(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(500);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("CCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+    public void processD(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(500);
+            DefaultContext contextBean = bindCmp.getFirstContextBean();
+            contextBean.setData(CONTENT_KEY, "value");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("DCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "f", nodeType = NodeTypeEnum.BOOLEAN)
+    public boolean processIf(NodeComponent bindCmp) throws Exception {
+        return true;
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "s", nodeType = NodeTypeEnum.SWITCH)
+    public String processSwitch(NodeComponent bindCmp) throws Exception {
+        return "b";
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "w", nodeType = NodeTypeEnum.BOOLEAN)
+    public boolean processWhile(NodeComponent bindCmp) throws Exception {
+        // 判断是否切换了 chain
+        if (!executedChain.contains(bindCmp.getCurrChainId())) {
+            count = 0;
+            executedChain.add(bindCmp.getCurrChainId());
+        }
+        count++;
+        return count <= 2;
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeId = "x", nodeType = NodeTypeEnum.ITERATOR)
+    public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
+        List<String> list = ListUtil.toList("one", "two");
+        return list.iterator();
+    }
+}

+ 171 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitSeconds/MaxWaitSecondsELDeclMultiSpringbootTest.java

@@ -0,0 +1,171 @@
+package com.yomahub.liteflow.test.maxWaitSeconds;
+
+import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.exception.WhenTimeoutException;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+import java.util.concurrent.TimeoutException;
+
+import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.CmpConfig.CONTENT_KEY;
+
+/**
+ * Spring Boot 环境下超时控制测试
+ *
+ * @author DaleLee
+ * @since 2.11.0
+ */
+@Import(profiles ="classpath:/maxWaitSeconds/application.properties")
+@SolonTest(classes = MaxWaitSecondsELDeclMultiSpringbootTest.class)
+public class MaxWaitSecondsELDeclMultiSpringbootTest extends BaseTest {
+    @Inject
+    private FlowExecutor flowExecutor;
+
+    // 测试 THEN 的超时情况
+    @Test
+    public void testThen1() {
+        assertTimeout("then1");
+    }
+
+    // 测试 THEN 的非超时情况
+    @Test
+    public void testThen2() {
+        assertNotTimeout("then2");
+    }
+
+    // 测试 When 的超时情况
+    @Test
+    public void testWhen1() {
+        assertWhenTimeout("when1");
+    }
+
+    // 测试 WHEN 的非超时情况
+    @Test
+    public void testWhen2() {
+        assertNotTimeout("when2");
+    }
+
+    // 测试 FOR 的超时情况
+    @Test
+    public void testFor1() {
+        assertTimeout("for1");
+    }
+
+    // 测试 FOR 的非超时情况
+    @Test
+    public void testFor2() {
+        assertNotTimeout("for2");
+    }
+
+    // 测试 WHILE 的超时情况
+    @Test
+    public void testWhile1() {
+        assertTimeout("while1");
+    }
+
+    // 测试 WHILE 的非超时情况
+    @Test
+    public void testWhile2() {
+        assertNotTimeout("while2");
+    }
+
+    // 测试 ITERATOR 的超时情况
+    @Test
+    public void testIterator1() {
+        assertTimeout("iterator1");
+    }
+
+    // 测试 ITERATOR 的非超时情况
+    @Test
+    public void testIterator2() {
+        assertNotTimeout("iterator2");
+    }
+
+    // 测试 SWITCH 的超时情况
+    @Test
+    public void testSwitch1() {
+        assertTimeout("switch1");
+    }
+
+    // 测试 SWITCH 的非超时情况
+    @Test
+    public void testSwitch2() {
+        assertNotTimeout("switch2");
+    }
+
+    // 测试 IF 的超时情况
+    @Test
+    public void testIf1() {
+        assertTimeout("if1");
+    }
+
+    // 测试 SWITCH 的非超时情况
+    @Test
+    public void testIf2() {
+        assertNotTimeout("if2");
+    }
+
+    // 测试单个组件的超时情况
+    @Test
+    public void testComponent1() {
+        assertTimeout("component1");
+    }
+
+    // 测试单个组件的非超时情况
+    @Test
+    public void testComponent2() {
+        assertNotTimeout("component2");
+    }
+
+    // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行
+    @Test
+    public void testFinally1() {
+        LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
+        // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY
+        DefaultContext contextBean = response.getFirstContextBean();
+        Assertions.assertTrue(contextBean.hasData(CONTENT_KEY));
+    }
+
+    // 测试 maxWaitSeconds 关键字不能作用于 Finally
+    @Test
+    public void testFinally2() {
+        Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitSeconds(10))"));
+    }
+
+    // 测试 chain 的超时情况
+    @Test
+    public void testChain1() {
+        assertTimeout("chain1");
+    }
+
+    // 测试 chain 的非超时情况
+    @Test
+    public void testChain2() {
+        assertNotTimeout("chain2");
+    }
+
+    private void assertTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(TimeoutException.class, response.getCause().getClass());
+    }
+
+    private void assertWhenTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertFalse(response.isSuccess());
+        Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass());
+    }
+
+    private void assertNotTimeout(String chainId) {
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        Assertions.assertTrue(response.isSuccess());
+    }
+}

+ 98 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/maxWaitSeconds/cmp/CmpConfig.java

@@ -0,0 +1,98 @@
+package com.yomahub.liteflow.test.maxWaitSeconds.cmp;
+
+import cn.hutool.core.collection.ListUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+@LiteflowComponent
+public class CmpConfig {
+
+    public static final String CONTENT_KEY = "testKey";
+
+    private int count = 0;
+
+    // 执行过的 chain
+    Set<String> executedChain = new HashSet<>();
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+    public void processA(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(1000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("ACmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+    public void processB(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(2000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("BCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+    public void process(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(5000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("CCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+    public void processD(NodeComponent bindCmp) {
+        try {
+            Thread.sleep(500);
+            DefaultContext contextBean = bindCmp.getFirstContextBean();
+            contextBean.setData(CONTENT_KEY, "value");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("DCmp executed!");
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "f", nodeType = NodeTypeEnum.BOOLEAN)
+    public boolean processIf(NodeComponent bindCmp) throws Exception {
+        return true;
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "s", nodeType = NodeTypeEnum.SWITCH)
+    public String processSwitch(NodeComponent bindCmp) throws Exception {
+        return "b";
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BOOLEAN, nodeId = "w", nodeType = NodeTypeEnum.BOOLEAN)
+    public boolean processWhile(NodeComponent bindCmp) throws Exception {
+        // 判断是否切换了 chain
+        if (!executedChain.contains(bindCmp.getCurrChainId())) {
+            count = 0;
+            executedChain.add(bindCmp.getCurrChainId());
+        }
+        count++;
+        return count <= 2;
+    }
+
+    @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeId = "x", nodeType = NodeTypeEnum.ITERATOR)
+    public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
+        List<String> list = ListUtil.toList("one", "two");
+        return list.iterator();
+    }
+}

+ 43 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/monitor/MonitorELDeclMultiSpringbootTest.java

@@ -0,0 +1,43 @@
+package com.yomahub.liteflow.test.monitor;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.monitor.MonitorBus;
+import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/monitor/application.properties")
+@SolonTest(classes = MonitorELDeclMultiSpringbootTest.class)
+public class MonitorELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testMonitor() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assertions.assertTrue(response.isSuccess());
+
+		Thread.sleep(10000);
+	}
+
+	@AfterAll
+	public static void clean() {
+		BaseTest.cleanScanCache();
+		MonitorBus monitorBus = ContextAwareHolder.loadContextAware().getBean(MonitorBus.class);
+		monitorBus.closeScheduler();
+	}
+
+}

+ 47 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/monitor/cmp/CmpConfig.java

@@ -0,0 +1,47 @@
+package com.yomahub.liteflow.test.monitor.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+
+import java.util.Random;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		try {
+			Thread.sleep(new Random().nextInt(2000));
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		System.out.println("ACmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		try {
+			Thread.sleep(new Random().nextInt(2000));
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void process(NodeComponent bindCmp) {
+		try {
+			Thread.sleep(new Random().nextInt(2000));
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 25 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/CheckContext.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.test.multiContext;
+
+public class CheckContext {
+
+	private String sign;
+
+	private int randomId;
+
+	public String getSign() {
+		return sign;
+	}
+
+	public void setSign(String sign) {
+		this.sign = sign;
+	}
+
+	public int getRandomId() {
+		return randomId;
+	}
+
+	public void setRandomId(int randomId) {
+		this.randomId = randomId;
+	}
+
+}

+ 48 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/MultiContextELDeclMultiSpringbootTest.java

@@ -0,0 +1,48 @@
+package com.yomahub.liteflow.test.multiContext;
+
+import cn.hutool.core.date.DateUtil;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.exception.NoSuchContextBeanException;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.noear.solon.annotation.Import;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.test.SolonTest;
+
+/**
+ * springboot环境最普通的例子测试
+ *
+ * @author Bryan.Zhang
+ * @since 2.6.4
+ */
+@Import(profiles ="classpath:/multiContext/application.properties")
+@SolonTest(classes = MultiContextELDeclMultiSpringbootTest.class)
+public class MultiContextELDeclMultiSpringbootTest extends BaseTest {
+
+	@Inject
+	private FlowExecutor flowExecutor;
+
+	@Test
+	public void testMultiContext1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", OrderContext.class, CheckContext.class);
+		OrderContext orderContext = response.getContextBean(OrderContext.class);
+		CheckContext checkContext = response.getContextBean(CheckContext.class);
+		Assertions.assertTrue(response.isSuccess());
+		Assertions.assertEquals("987XYZ", checkContext.getSign());
+		Assertions.assertEquals(95, checkContext.getRandomId());
+		Assertions.assertEquals("SO12345", orderContext.getOrderNo());
+		Assertions.assertEquals(2, orderContext.getOrderType());
+		Assertions.assertEquals(DateUtil.parseDate("2022-06-15"), orderContext.getCreateTime());
+	}
+
+	@Test
+	public void testMultiContext2() throws Exception {
+		Assertions.assertThrows(NoSuchContextBeanException.class, () -> {
+			LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", OrderContext.class, CheckContext.class);
+			DefaultContext context = response.getContextBean(DefaultContext.class);
+		});
+	}
+}

+ 37 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/OrderContext.java

@@ -0,0 +1,37 @@
+package com.yomahub.liteflow.test.multiContext;
+
+import java.util.Date;
+
+public class OrderContext {
+
+	private String orderNo;
+
+	private int orderType;
+
+	private Date createTime;
+
+	public String getOrderNo() {
+		return orderNo;
+	}
+
+	public void setOrderNo(String orderNo) {
+		this.orderNo = orderNo;
+	}
+
+	public int getOrderType() {
+		return orderType;
+	}
+
+	public void setOrderType(int orderType) {
+		this.orderType = orderType;
+	}
+
+	public Date getCreateTime() {
+		return createTime;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+}

+ 45 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-multi-solon/src/test/java/com/yomahub/liteflow/test/multiContext/cmp/CmpConfig.java

@@ -0,0 +1,45 @@
+package com.yomahub.liteflow.test.multiContext.cmp;
+
+import cn.hutool.core.date.DateUtil;
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.test.multiContext.CheckContext;
+import com.yomahub.liteflow.test.multiContext.OrderContext;
+
+@LiteflowComponent
+public class CmpConfig {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
+	public void processA(NodeComponent bindCmp) {
+		CheckContext checkContext = bindCmp.getContextBean(CheckContext.class);
+		checkContext.setSign("987XYZ");
+		checkContext.setRandomId(95);
+		System.out.println("ACmp executed!");
+
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b")
+	public void processB(NodeComponent bindCmp) {
+		// getContextBean无参方法是获取到第一个上下文
+		OrderContext orderContext = bindCmp.getFirstContextBean();
+		orderContext.setOrderNo("SO12345");
+		System.out.println("BCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c")
+	public void processC(NodeComponent bindCmp) {
+		OrderContext orderContext = bindCmp.getContextBean(OrderContext.class);
+		orderContext.setOrderType(2);
+		System.out.println("CCmp executed!");
+	}
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d")
+	public void processD(NodeComponent bindCmp) {
+		OrderContext orderContext = bindCmp.getContextBean(OrderContext.class);
+		orderContext.setCreateTime(DateUtil.parseDate("2022-06-15"));
+		System.out.println("CCmp executed!");
+	}
+
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است