diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/common/LocalDefaultFlowConstant.java b/liteflow-core/src/main/java/com/yomahub/liteflow/common/LocalDefaultFlowConstant.java new file mode 100644 index 000000000..0e752c5e9 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/common/LocalDefaultFlowConstant.java @@ -0,0 +1,5 @@ +package com.yomahub.liteflow.common; + +public class LocalDefaultFlowConstant { + public static final String DEFAULT="default"; +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Condition.java index cf4a9d39a..f8e576fea 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Condition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Condition.java @@ -7,6 +7,8 @@ */ package com.yomahub.liteflow.entity.flow; +import com.yomahub.liteflow.common.LocalDefaultFlowConstant; + import java.util.List; /** @@ -14,6 +16,10 @@ import java.util.List; * @author Bryan.Zhang */ public class Condition { + // 增加errorResume属性,以区分当when调用链调用失败时是否继续往下执行 默认true继续执行 + private boolean errorResume = true; + // 增加groupId属性,用于不同node进行同组合并 + private String groupId = LocalDefaultFlowConstant.DEFAULT; private List nodeList; @@ -28,4 +34,20 @@ public class Condition { public void setNodeList(List nodeList) { this.nodeList = nodeList; } + + public boolean isErrorResume() { + return errorResume; + } + + public void setErrorResume(boolean errorResume) { + this.errorResume = errorResume; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java index 13a202537..214626b7c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java @@ -14,20 +14,16 @@ import java.util.List; * @author Bryan.Zhang */ public class WhenCondition extends Condition{ - // 增加errorResume属性,以区分当when调用链调用失败时是否继续往下执行 - private boolean errorResume; + public WhenCondition(List nodeList) { super(nodeList); - errorResume = true; + super.setErrorResume(true); } public WhenCondition(List nodeList, boolean errorResume) { super(nodeList); - this.errorResume = errorResume; + super.setErrorResume(errorResume); } - public boolean isErrorResume() { - return errorResume; - } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 3d3109aae..00cd6436a 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -7,12 +7,13 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.common.LocalDefaultFlowConstant; import com.yomahub.liteflow.entity.flow.*; import com.yomahub.liteflow.exception.ExecutableItemNotFoundException; import com.yomahub.liteflow.exception.ParseException; import com.yomahub.liteflow.util.SpringAware; -import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; @@ -90,6 +91,8 @@ public abstract class XmlFlowParser extends FlowParser{ private void parseOneChain(Element e) throws Exception{ String condArrayStr; String[] condArray; + String group; + String errorResume; List chainNodeList; List conditionList; @@ -98,9 +101,17 @@ public abstract class XmlFlowParser extends FlowParser{ for (Iterator it = e.elementIterator(); it.hasNext();) { Element condE = it.next(); condArrayStr = condE.attributeValue("value"); + errorResume = e.attributeValue("errorResume"); + group = e.attributeValue("group"); if (StrUtil.isBlank(condArrayStr)) { continue; } + if (StrUtil.isBlank(group)) { + group = LocalDefaultFlowConstant.DEFAULT; + } + if (StrUtil.isBlank(errorResume)) { + errorResume = Boolean.TRUE.toString(); + } chainNodeList = new ArrayList<>(); condArray = condArrayStr.split(","); RegexEntity regexEntity; @@ -134,14 +145,22 @@ public abstract class XmlFlowParser extends FlowParser{ throw new ExecutableItemNotFoundException(errorMsg); } } + + if (condE.getName().equals("then")) { - conditionList.add(new ThenCondition(chainNodeList)); + if(conditionList.size() > 1 && + CollectionUtil.getLast(conditionList) instanceof ThenCondition ){ + CollectionUtil.getLast(conditionList).getNodeList().addAll(chainNodeList); + }else{ + conditionList.add(new ThenCondition(chainNodeList)); + } } else if (condE.getName().equals("when")) { - Attribute errorResume = condE.attribute("errorResume"); - if (errorResume != null) { - conditionList.add(new WhenCondition(chainNodeList, errorResume.getValue().equals(Boolean.TRUE.toString()))); - } else { - conditionList.add(new WhenCondition(chainNodeList)); + if(conditionList.size() > 1 && + CollectionUtil.getLast(conditionList) instanceof WhenCondition && + CollectionUtil.getLast(conditionList).getGroupId().equals(group)){ + CollectionUtil.getLast(conditionList).getNodeList().addAll(chainNodeList); + }else{ + conditionList.add(new WhenCondition(chainNodeList, errorResume.equals(Boolean.TRUE.toString()))); } } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java index e093869a7..2212f67fa 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java @@ -7,6 +7,9 @@ */ package com.yomahub.liteflow.util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; @@ -16,7 +19,9 @@ import java.util.concurrent.atomic.AtomicLong; * @author Bryan.Zhang */ public class ExecutorHelper { - + + private static final Logger LOG = LoggerFactory.getLogger(ExecutorHelper.class); + private ExecutorHelper() { } @@ -44,7 +49,7 @@ public class ExecutorHelper { if (!pool.awaitTermination(timeout, TimeUnit.SECONDS)) { pool.shutdownNow(); if (!pool.awaitTermination(timeout, TimeUnit.SECONDS)) { - System.err.println("Pool did not terminate."); + LOG.error("Pool did not terminate."); } } } catch (InterruptedException ie) { diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowComponentScannerAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowComponentScannerAutoConfiguration.java index a415dbf8c..efeb21516 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowComponentScannerAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowComponentScannerAutoConfiguration.java @@ -3,14 +3,12 @@ package com.yomahub.liteflow.springboot; import com.yomahub.liteflow.spring.ComponentScaner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * 组件扫描器自动装配类 * @author Bryan.Zhang */ @Configuration -@EnableAspectJAutoProxy(exposeProxy = true) public class LiteflowComponentScannerAutoConfiguration { @Bean diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestGroupIdFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestGroupIdFlow.java new file mode 100644 index 000000000..df390d9b5 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestGroupIdFlow.java @@ -0,0 +1,49 @@ +package com.yomahub.flowtest.concurrent; + +import com.yomahub.liteflow.core.FlowExecutor; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseAssertRandom; +import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseInit; + +/** + * 测试流程的顺序执行、并发执行等 + * @author justin.xu + */ +@ActiveProfiles("test") +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestGroupIdFlow { + + @Resource + private FlowExecutor flowExecutor; + + private String init(List steps) { + + String requestId = UUID.randomUUID().toString(); + + caseInit(requestId, steps.stream().map(ConcurrentCase.Routers::new).collect(Collectors.toList())); + + return requestId; + } + + @Test + public void whenConditionGroupTest() throws Exception { + //由于errorResume,即使p5执行失败抛出异常, p7, p8也将会执行 + String requestId = init(Arrays.asList("s1", "s2", "s3", "s4", "s5", "s6", "p3", "p4", "p6", "p7", "p8")); + + flowExecutor.execute("test-groupId", requestId); + + caseAssertRandom(requestId); + } +} diff --git a/liteflow-test-springboot/src/test/resources/config/flow-test.xml b/liteflow-test-springboot/src/test/resources/config/flow-test.xml index 7bdc30870..575a6da5b 100644 --- a/liteflow-test-springboot/src/test/resources/config/flow-test.xml +++ b/liteflow-test-springboot/src/test/resources/config/flow-test.xml @@ -24,4 +24,10 @@ + + + + + +