diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java index cd2c584f..65f577b2 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java @@ -1,31 +1,42 @@ package com.yomahub.liteflow.builder.el.operator; +import com.ql.util.express.Operator; import com.ql.util.express.exception.QLException; -import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; -import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; +import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.flow.element.Executable; import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * EL规则中的WHEN的操作符 - * * @author Bryan.Zhang * @since 2.8.0 */ -public class WhenOperator extends BaseOperator { +public class WhenOperator extends Operator { - @Override - public Object buildCondition(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeGtZero(objects); + private final Logger LOG = LoggerFactory.getLogger(this.getClass()); - WhenCondition whenCondition = new WhenCondition(); - for (Object obj : objects) { - if (obj instanceof Executable) { - whenCondition.addExecutable((Executable) obj); - } else { - throw new QLException("parameter error"); - } - } - return whenCondition; - } + @Override + public WhenCondition executeInner(Object[] objects) throws Exception { + try { + if (objects.length == 0) { + throw new QLException("parameter is empty"); + } + + WhenCondition whenCondition = new WhenCondition(); + for (Object obj : objects) { + if (obj instanceof Executable) { + whenCondition.addExecutable((Executable) obj); + } else { + throw new QLException("parameter must be executable item"); + } + } + return whenCondition; + }catch (QLException e){ + throw e; + }catch (Exception e){ + throw new ELParseException("errors occurred in EL parsing"); + } + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java index c126950b..90f65b97 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java @@ -163,29 +163,32 @@ public class FlowExecutor { } //隐式流程的调用方法 + @Deprecated public void invoke(String chainId, Object param, Integer slotIndex) throws Exception { - LiteflowResponse response = this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_SYNC); + LiteflowResponse response = this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_SYNC); + if (!response.isSuccess()){ + throw response.getCause(); + } + } + + @Deprecated + public void invokeInAsync(String chainId, Object param, Integer slotIndex) throws Exception { + LiteflowResponse response = this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_ASYNC); if (!response.isSuccess()){ throw response.getCause(); } } public LiteflowResponse invoke2Resp(String chainId, Object param, Integer slotIndex) { - return this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_SYNC); - } - - public void invokeInAsync(String chainId, Object param, Integer slotIndex) throws Exception { - LiteflowResponse response = this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_ASYNC); - if (!response.isSuccess()){ - throw response.getCause(); - } + return this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_SYNC); } public LiteflowResponse invoke2RespInAsync(String chainId, Object param, Integer slotIndex) { - return this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_ASYNC); + return this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_ASYNC); } //单独调用某一个node + @Deprecated public void invoke(String nodeId, Integer slotIndex) throws Exception { Node node = FlowBus.getNode(nodeId); node.execute(slotIndex); @@ -203,26 +206,27 @@ public class FlowExecutor { //调用一个流程并返回LiteflowResponse,允许多上下文的传入 public LiteflowResponse execute2Resp(String chainId, Object param, Class... contextBeanClazzArray) { - return this.execute2Resp(chainId, param, contextBeanClazzArray, null, null, InnerChainTypeEnum.NONE); + return this.execute2Resp(chainId, param, contextBeanClazzArray, null); + } + + public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) { + return this.execute2Resp(chainId, param, null, contextBeanArray); } //调用一个流程并返回Future,允许多上下文的传入 public Future execute2Future(String chainId, Object param, Class... contextBeanClazzArray) { return ExecutorHelper.loadInstance().buildMainExecutor(liteflowConfig.getMainExecutorClass()).submit(() - -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazzArray,null, null, InnerChainTypeEnum.NONE)); + -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazzArray,null)); } - public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) { - return this.execute2Resp(chainId, param, null, contextBeanArray, null, InnerChainTypeEnum.NONE); - } - public Future execute2Future(String chainId, Object param, Object... contextBeanArray) { return ExecutorHelper.loadInstance().buildMainExecutor(liteflowConfig.getMainExecutorClass()).submit(() - -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, null, contextBeanArray, null, InnerChainTypeEnum.NONE)); + -> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, null, contextBeanArray)); } //调用一个流程,返回默认的上下文,适用于简单的调用 + @Deprecated public DefaultContext execute(String chainId, Object param) throws Exception{ LiteflowResponse response = this.execute2Resp(chainId, param, DefaultContext.class); if (!response.isSuccess()){ @@ -235,10 +239,16 @@ public class FlowExecutor { private LiteflowResponse execute2Resp(String chainId, Object param, Class[] contextBeanClazzArray, - Object[] contextBeanArray, + Object[] contextBeanArray) { + Slot slot = doExecute(chainId, param, contextBeanClazzArray, contextBeanArray, null, InnerChainTypeEnum.NONE); + return LiteflowResponse.newMainResponse(slot); + } + + private LiteflowResponse invoke2Resp(String chainId, + Object param, Integer slotIndex, InnerChainTypeEnum innerChainType) { - Slot slot = doExecute(chainId, param, contextBeanClazzArray, contextBeanArray, slotIndex, innerChainType); - return new LiteflowResponse(slot); + Slot slot = doExecute(chainId, param, null, null, slotIndex, innerChainType); + return LiteflowResponse.newInnerResponse(chainId, slot); } private Slot doExecute(String chainId, @@ -251,7 +261,9 @@ public class FlowExecutor { init(); } + //如果不是隐式流程,那么需要分配Slot if (innerChainType.equals(InnerChainTypeEnum.NONE) && ObjectUtil.isNull(slotIndex)) { + //这里可以根据class分配,也可以根据bean去分配 if (ArrayUtil.isNotEmpty(contextBeanClazzArray)){ slotIndex = DataBus.offerSlotByClass(ListUtil.toList(contextBeanClazzArray)); }else{ @@ -266,11 +278,20 @@ public class FlowExecutor { throw new NoAvailableSlotException("there is no available slot"); } + Slot slot = DataBus.getSlot(slotIndex); if (ObjectUtil.isNull(slot)) { throw new NoAvailableSlotException(StrUtil.format("the slot[{}] is not exist", slotIndex)); } + //如果是隐式流程,事先把subException给置空,然后把隐式流程的chainId放入slot元数据中 + //我知道这在多线程调用隐式流程中会有问题。但是考虑到这种场景的不会多,也有其他的转换方式。 + //所以暂且这么做,以后再优化 + if (!innerChainType.equals(InnerChainTypeEnum.NONE)){ + slot.removeSubException(chainId); + slot.addSubChain(chainId); + } + if (StrUtil.isBlank(slot.getRequestId())) { slot.generateRequestId(); if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) { @@ -318,7 +339,14 @@ public class FlowExecutor { LOG.error(e.getMessage()); } } - slot.setException(e); + + //如果是正常流程需要把异常设置到slot的exception属性里 + //如果是隐式流程,则需要设置到隐式流程的exception属性里 + if (innerChainType.equals(InnerChainTypeEnum.NONE)) { + slot.setException(e); + }else{ + slot.setSubException(chainId, e); + } } finally { if (innerChainType.equals(InnerChainTypeEnum.NONE)) { slot.printStep(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java index e7b444be..e9d36be3 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java @@ -113,6 +113,9 @@ public abstract class NodeComponent{ } throw e; } finally { + //后置处理 + self.afterProcess(this.getNodeId(), slot); + stopWatch.stop(); final long timeSpent = stopWatch.getTotalTimeMillis(); LOG.debug("[{}]:component[{}] finished in {} milliseconds",slot.getRequestId(),this.getDisplayName(),timeSpent); @@ -120,9 +123,6 @@ public abstract class NodeComponent{ //往CmpStep中放入时间消耗信息 cmpStep.setTimeSpent(timeSpent); - //后置处理 - self.afterProcess(this.getNodeId(), slot); - // 性能统计 if (ObjectUtil.isNotNull(monitorBus)) { CompStatistics statistics = new CompStatistics(this.getClass().getSimpleName(), timeSpent); @@ -156,7 +156,7 @@ public abstract class NodeComponent{ return true; } - //出错是否继续执行(这个只适用于串行流程,并行节点不起作用) + //出错是否继续执行(这个只适用于并行流程,串行流程不起作用) public boolean isContinueOnError() { return false; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java index 99c0af05..1c90a198 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java @@ -28,20 +28,30 @@ public class LiteflowResponse implements Serializable { private Slot slot; public LiteflowResponse() { - this(null); } - public LiteflowResponse(Slot slot) { - if (slot != null && slot.getException() != null) { - this.success = false; - this.cause = slot.getException(); - this.message = this.cause.getMessage(); - this.code = this.cause instanceof LiteFlowException ? ((LiteFlowException)this.cause).getCode() : null; + + public static LiteflowResponse newMainResponse(Slot slot){ + return newResponse(slot, slot.getException()); + } + + public static LiteflowResponse newInnerResponse(String chainId, Slot slot){ + return newResponse(slot, slot.getSubException(chainId)); + } + + private static LiteflowResponse newResponse(Slot slot, Exception e){ + LiteflowResponse response = new LiteflowResponse(); + if (slot != null && e != null) { + response.setSuccess(false); + response.setCause(e); + response.setMessage(response.getCause().getMessage()); + response.setCode(response.getCause() instanceof LiteFlowException ? ((LiteFlowException)response.getCause()).getCode() : null); } else { - this.success = true; + response.setSuccess(true); } - this.slot = slot; + response.setSlot(slot); + return response; } - + public boolean isSuccess() { return success; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java index 949e0e1f..e7c4e0c1 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java @@ -89,7 +89,11 @@ public class Chain implements Executable { throw e; }catch (Exception e){ //这里事先取到exception set到slot里,为了方便finally取到exception - slot.setException(e); + if (slot.isSubChain(chainName)){ + slot.setSubException(chainName, e); + }else{ + slot.setException(e); + } throw e; }finally { //执行后置 diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java index 51a17f54..e45cb377 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java @@ -11,7 +11,7 @@ import com.yomahub.liteflow.enums.ConditionTypeEnum; import com.yomahub.liteflow.flow.element.Executable; /** - * 前置Condition + * 后置Condition * @author Bryan.Zhang * @since 2.6.4 */ diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java index 80bd00c9..c63c3e80 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java @@ -7,6 +7,7 @@ */ package com.yomahub.liteflow.slot; +import cn.hutool.core.collection.ConcurrentHashSet; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import com.yomahub.liteflow.exception.NoSuchContextBeanException; @@ -20,6 +21,7 @@ import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.Queue; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; @@ -54,8 +56,12 @@ public class Slot{ private static final String EXCEPTION = "_exception"; + private static final String SUB_EXCEPTION_PREFIX = "_sub_exception_"; + private static final String PRIVATE_DELIVERY_PREFIX = "_private_d_"; + private static final String SUB_CHAIN = "_sub_chain"; + private final Deque executeSteps = new ConcurrentLinkedDeque<>(); private String executeStepsStr; @@ -261,6 +267,18 @@ public class Slot{ putMetaDataMap(EXCEPTION, e); } + public Exception getSubException(String chainId) { + return (Exception) this.metaDataMap.get(SUB_EXCEPTION_PREFIX + chainId); + } + + public void setSubException(String chainId, Exception e) { + putMetaDataMap(SUB_EXCEPTION_PREFIX + chainId, e); + } + + public void removeSubException(String chainId){ + metaDataMap.remove(SUB_EXCEPTION_PREFIX + chainId); + } + public List getContextBeanList(){ return this.contextBeanList; } @@ -277,4 +295,19 @@ public class Slot{ Class firstContextBeanClazz = (Class) this.getContextBeanList().get(0).getClass(); return this.getContextBean(firstContextBeanClazz); } + + public void addSubChain(String chainId){ + Set subChainSet = (Set) metaDataMap.getOrDefault(SUB_CHAIN, new ConcurrentHashSet<>()); + subChainSet.add(chainId); + metaDataMap.putIfAbsent(SUB_CHAIN, subChainSet); + } + + public boolean isSubChain(String chainId){ + if (metaDataMap.containsKey(SUB_CHAIN)){ + Set subChainSet = (Set) metaDataMap.get(SUB_CHAIN); + return subChainSet.contains(chainId); + }else{ + return false; + } + } } diff --git a/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java b/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java index 569a25cc..c7196f4b 100644 --- a/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java +++ b/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java @@ -11,6 +11,7 @@ import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.spi.PathContentParser; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.util.ResourceUtils; import java.util.ArrayList; @@ -33,7 +34,7 @@ public class SpringPathContentParser implements PathContentParser { if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){ locationPattern = ResourceUtils.FILE_URL_PREFIX + path; } else { - if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { + if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) && !path.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) { locationPattern = ResourceUtils.CLASSPATH_URL_PREFIX + path; }else{ locationPattern = path; diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclSpringbootTest1.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclSpringbootTest1.java index 7327e123..fae36327 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclSpringbootTest1.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderELDeclSpringbootTest1.java @@ -1,20 +1,17 @@ package com.yomahub.liteflow.test.builder; -import com.yomahub.liteflow.builder.LiteFlowChainBuilder; -import com.yomahub.liteflow.builder.LiteFlowConditionBuilder; -import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.builder.entity.ExecutableEntity; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.test.builder.cmp1.*; +import com.yomahub.liteflow.test.base.BaseELDeclSpringbootTest; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; @@ -25,6 +22,7 @@ import javax.annotation.Resource; @RunWith(SpringRunner.class) @SpringBootTest(classes = BuilderELDeclSpringbootTest1.class) @EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.builder.cmp1"}) public class BuilderELDeclSpringbootTest1 extends BaseTest { @Resource @@ -33,43 +31,6 @@ public class BuilderELDeclSpringbootTest1 extends BaseTest { //基于普通组件的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(); @@ -80,133 +41,22 @@ public class BuilderELDeclSpringbootTest1 extends BaseTest { LiteflowResponse response = flowExecutor.execute2Resp("chain1"); Assert.assertTrue(response.isSuccess()); - Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr()); + Assert.assertEquals("a==>b==>e==>c==>d", response.getExecuteStepStrWithoutTime()); } - //基于普通组件的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(); - - - LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition( - LiteFlowConditionBuilder.createThenCondition().setValue("c,d").build() - ).build(); - - LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition( - LiteFlowConditionBuilder - .createThenCondition() - .setValue("a,b").build() - ).setCondition( - LiteFlowConditionBuilder.createWhenCondition() - .setValue("e(f|g|chain2)").build() - ).build(); - - LiteflowResponse response = flowExecutor.execute2Resp("chain1"); - Assert.assertTrue(response.isSuccess()); - Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr()); - } - - //基于普通组件的builder模式测试 @Test public void testBuilderForConditionNode() 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(); - - - LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition( - LiteFlowConditionBuilder.createThenCondition() - .setExecutable(new ExecutableEntity().setId("c")) - .setExecutable(new ExecutableEntity().setId("d")) - .build() + LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL( + "THEN(c, d)" ).build(); - LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition( - LiteFlowConditionBuilder - .createThenCondition() - .setExecutable(new ExecutableEntity().setId("a").setTag("hello")) - .setExecutable(new ExecutableEntity().setId("b")) - .build() - ).setCondition( - LiteFlowConditionBuilder.createWhenCondition() - .setExecutable( - new ExecutableEntity().setId("e") - .addNodeCondComponent(new ExecutableEntity().setId("f").setTag("FHello")) - .addNodeCondComponent(new ExecutableEntity().setId("g")) - .addNodeCondComponent(new ExecutableEntity().setId("chain2") - )).build() + LiteFlowChainELBuilder.createChain().setChainName("chain1").setEL( + "THEN(a.tag('hello'), b, WHEN(SWITCH(e).to(f.tag('FHello'), g, chain2)))" ).build(); LiteflowResponse response = flowExecutor.execute2Resp("chain1"); Assert.assertTrue(response.isSuccess()); - Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr()); + Assert.assertEquals("a==>b==>e==>c==>d", response.getExecuteStepStr()); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java index a9ffd1f0..4091980f 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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("a") @LiteflowCmpDefine public class ACmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java index e13b0434..bc7a35d0 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/BCmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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("b") @LiteflowCmpDefine public class BCmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java index 6fbbc10e..69612de4 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/CCmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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("c") @LiteflowCmpDefine public class CCmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java index 27fb0fd4..dc5f720c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/DCmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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") @LiteflowCmpDefine public class DCmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java index 0e4627ec..56ad44af 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ECmp.java @@ -7,11 +7,13 @@ */ package com.yomahub.liteflow.test.builder.cmp1; +import com.yomahub.liteflow.annotation.LiteflowComponent; import com.yomahub.liteflow.annotation.LiteflowSwitchCmpDefine; import com.yomahub.liteflow.annotation.LiteflowMethod; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.enums.LiteFlowMethodEnum; +@LiteflowComponent("e") @LiteflowSwitchCmpDefine public class ECmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java index a300c50f..559b8c37 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/FCmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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("f") @LiteflowCmpDefine public class FCmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java index 4035e89c..94114ecb 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/builder/cmp1/GCmp.java @@ -8,10 +8,12 @@ package com.yomahub.liteflow.test.builder.cmp1; import com.yomahub.liteflow.annotation.LiteflowCmpDefine; +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("g") @LiteflowCmpDefine public class GCmp{ diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index a6fda5aa..0d670c77 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -2,6 +2,6 @@ - + WHEN(a,b,c); \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml index a6fda5aa..0d670c77 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml @@ -2,6 +2,6 @@ - + WHEN(a,b,c); \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java index ac42a4e5..c089041a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java @@ -63,4 +63,11 @@ public class ImplicitSubFlowELSpringbootTest extends BaseTest { //requestData的取值正确 Assert.assertEquals(10, set.size()); } + + @Test + public void testImplicitSubFlow3() { + LiteflowResponse response = flowExecutor.execute2Resp("chain_r", "it's a request"); + Assert.assertTrue(response.isSuccess()); + + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java index b44d66e1..39d75247 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java @@ -19,13 +19,7 @@ public class PCmp extends NodeComponent { int slotIndex = this.getSlotIndex(); for (int i = 0; i < 10; i++) { int finalI = i; - new Thread(() -> { - try { - flowExecutor.invokeInAsync("c2", "it's implicit subflow " + finalI, slotIndex); - } catch (Exception e) { - throw new RuntimeException(e); - } - }).start(); + new Thread(() -> flowExecutor.invoke2RespInAsync("c2", "it's implicit subflow " + finalI, slotIndex)).start(); } Thread.sleep(1000); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/R.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/R.java new file mode 100644 index 00000000..804bba47 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/R.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.subflow.cmp2; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("r") +public class R extends NodeComponent { + @Override + public void process() throws Exception { + this.invoke2Resp("chain_s",""); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/S.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/S.java new file mode 100644 index 00000000..fbaf1dc9 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/S.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.subflow.cmp2; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("s") +public class S extends NodeComponent { + @Override + public void process() throws Exception { + throw new RuntimeException("test"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml index 91498014..3974e211 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml @@ -15,4 +15,12 @@ THEN(q); + + + THEN(r); + + + + THEN(s); + \ No newline at end of file