소스 검색

Merge branch 'bug_I4LUQ5' into v2.6.6

bryan31 3 년 전
부모
커밋
406da614d4
15개의 변경된 파일318개의 추가작업 그리고 27개의 파일을 삭제
  1. 15 15
      liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java
  2. 23 12
      liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java
  3. 31 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/NullParamException.java
  4. 41 0
      liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/NullParamTest.java
  5. 22 0
      liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/ACmp.java
  6. 23 0
      liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/BCmp.java
  7. 22 0
      liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/CCmp.java
  8. 1 0
      liteflow-testcase-springboot/src/test/resources/nullParam/application.properties
  9. 7 0
      liteflow-testcase-springboot/src/test/resources/nullParam/flow.xml
  10. 35 0
      liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/NullParamTest.java
  11. 22 0
      liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/ACmp.java
  12. 23 0
      liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/BCmp.java
  13. 22 0
      liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/CCmp.java
  14. 23 0
      liteflow-testcase-springnative/src/test/resources/nullParam/application-local.xml
  15. 8 0
      liteflow-testcase-springnative/src/test/resources/nullParam/flow.xml

+ 15 - 15
liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java

@@ -8,7 +8,6 @@
  */
 package com.yomahub.liteflow.core;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReUtil;
@@ -31,8 +30,6 @@ import com.yomahub.liteflow.flow.FlowBus;
 import com.yomahub.liteflow.parser.LocalXmlFlowParser;
 import com.yomahub.liteflow.parser.XmlFlowParser;
 import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser;
-
-import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -263,21 +260,16 @@ public class FlowExecutor {
         init();
     }
 
-    /**
-     * callback by implicit subflow
-     *
-     * @param chainId
-     * @param param
-     * @param slotClazz
-     * @param slotIndex
-     * @param <T>
-     * @throws Exception
-     */
+    //隐式流程的调用方法
     public <T extends Slot> void invoke(String chainId, Object param, Class<T> slotClazz,
                                         Integer slotIndex) throws Exception {
         this.execute(chainId, param, slotClazz, slotIndex, true);
     }
 
+    public DefaultSlot execute(String chainId) throws Exception {
+        return this.execute(chainId, null, DefaultSlot.class, null, false);
+    }
+
     public DefaultSlot execute(String chainId, Object param) throws Exception {
         return this.execute(chainId, param, DefaultSlot.class, null, false);
     }
@@ -296,6 +288,10 @@ public class FlowExecutor {
         }
     }
 
+    public LiteflowResponse<DefaultSlot> execute2Resp(String chainId) {
+        return this.execute2Resp(chainId, null, DefaultSlot.class);
+    }
+
     public LiteflowResponse<DefaultSlot> execute2Resp(String chainId, Object param) {
         return this.execute2Resp(chainId, param, DefaultSlot.class);
     }
@@ -349,10 +345,14 @@ public class FlowExecutor {
         }
 
         if (!isInnerChain) {
-            slot.setRequestData(param);
+            if (ObjectUtil.isNotNull(param)){
+                slot.setRequestData(param);
+            }
             slot.setChainName(chainId);
         } else {
-            slot.setChainReqData(chainId, param);
+            if (ObjectUtil.isNotNull(param)){
+                slot.setChainReqData(chainId, param);
+            }
         }
 
         Chain chain = null;

+ 23 - 12
liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java

@@ -7,6 +7,9 @@
  */
 package com.yomahub.liteflow.entity.data;
 
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.exception.NullParamException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.Iterator;
@@ -27,7 +30,7 @@ public abstract class AbsSlot implements Slot {
 
 	private static final String RESPONSE = "_response";
 
-	private static final String CHAINNAME = "_chain_name";
+	private static final String CHAIN_NAME = "_chain_name";
 
 	private static final String COND_NODE_PREFIX = "_cond_";
 
@@ -47,6 +50,14 @@ public abstract class AbsSlot implements Slot {
 
 	protected ConcurrentHashMap<String, Object> dataMap = new ConcurrentHashMap<String, Object>();
 
+	private <T> void putDataMap(String key, T t) {
+		if (ObjectUtil.isNull(t)) {
+			//data slot is a ConcurrentHashMap, so null value will trigger NullPointerException
+			throw new NullParamException("data slot can't accept null param");
+		}
+		dataMap.put(key, t);
+	}
+
 	public <T> T getInput(String nodeId){
 		return (T)dataMap.get(NODE_INPUT_PREFIX + nodeId);
 	}
@@ -56,11 +67,11 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setInput(String nodeId,T t){
-		dataMap.put(NODE_INPUT_PREFIX + nodeId, t);
+		putDataMap(NODE_INPUT_PREFIX + nodeId, t);
 	}
 
 	public <T> void setOutput(String nodeId,T t){
-		dataMap.put(NODE_OUTPUT_PREFIX + nodeId, t);
+		putDataMap(NODE_OUTPUT_PREFIX + nodeId, t);
 	}
 
 	public <T> T getRequestData(){
@@ -68,7 +79,7 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setRequestData(T t){
-		dataMap.put(REQUEST, t);
+		putDataMap(REQUEST, t);
 	}
 
 	public <T> T getResponseData(){
@@ -76,7 +87,7 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setResponseData(T t){
-		dataMap.put(RESPONSE, t);
+		putDataMap(RESPONSE, t);
 	}
 
 	public <T> T getChainReqData(String chainId) {
@@ -84,7 +95,7 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setChainReqData(String chainId, T t) {
-		dataMap.put(CHAIN_REQ_PREFIX + chainId, t);
+		putDataMap(CHAIN_REQ_PREFIX + chainId, t);
 	}
 
 	public boolean hasData(String key){
@@ -96,7 +107,7 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setData(String key, T t){
-		dataMap.put(key, t);
+		putDataMap(key, t);
 	}
 
 	public <T> void setPrivateDeliveryData(String nodeId, T t){
@@ -124,7 +135,7 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public <T> void setCondResult(String key, T t){
-		dataMap.put(COND_NODE_PREFIX + key, t);
+		putDataMap(COND_NODE_PREFIX + key, t);
 	}
 
 	public <T> T getCondResult(String key){
@@ -132,11 +143,11 @@ public abstract class AbsSlot implements Slot {
 	}
 
 	public void setChainName(String chainName) {
-		dataMap.put(CHAINNAME, chainName);
+		putDataMap(CHAIN_NAME, chainName);
 	}
 
 	public String getChainName() {
-		return (String)dataMap.get(CHAINNAME);
+		return (String)dataMap.get(CHAIN_NAME);
 	}
 
 	public void addStep(CmpStep step){
@@ -159,7 +170,7 @@ public abstract class AbsSlot implements Slot {
 
 	@Override
 	public void generateRequestId() {
-		dataMap.put(REQUEST_ID, new Long(System.nanoTime()).toString());
+		dataMap.put(REQUEST_ID, IdUtil.nanoId());
 	}
 
 	@Override
@@ -178,6 +189,6 @@ public abstract class AbsSlot implements Slot {
 
 	@Override
 	public void setException(Exception e) {
-		this.dataMap.put(EXCEPTION, e);
+		putDataMap(EXCEPTION, e);
 	}
 }

+ 31 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/NullParamException.java

@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.exception;
+
+import java.io.Serializable;
+
+/**
+ * null param exception
+ * when param is null, dataMap (ConcurrentHashMap) cann't accept a null value
+ *
+ * @Author LeoLee
+ * @Date 2021/12/10 16:47
+ * @Version 1.0
+ */
+public class NullParamException extends RuntimeException implements Serializable {
+
+    private static final long serialVersionUID = -864259139568071245L;
+
+    private String message;
+
+    public NullParamException(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 41 - 0
liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/NullParamTest.java

@@ -0,0 +1,41 @@
+package com.yomahub.liteflow.test.nullParam;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.entity.data.DefaultSlot;
+import com.yomahub.liteflow.entity.data.LiteflowResponse;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+/**
+ * 单元测试:传递null param导致NPE的优化代码
+ *
+ * @author LeoLee
+ * @since 2.6.6
+ */
+@RunWith(SpringRunner.class)
+@TestPropertySource(value = "classpath:/nullParam/application.properties")
+@SpringBootTest(classes = NullParamTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.nullParam.cmp"})
+public class NullParamTest {
+
+    @Autowired
+    private FlowExecutor flowExecutor;
+
+    /**
+     * 支持无参的flow执行,以及param 为null时的异常抛出
+     */
+    @Test
+    public void testNullParam() throws Exception {
+        LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
+        Assert.assertTrue(response.isSuccess());
+    }
+
+}

+ 22 - 0
liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/ACmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a")
+public class ACmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("ACmp executed!");
+		System.out.println("get request data:" + this.getSlot().getRequestData());
+		this.getSlot().setInput("BCmp", "param for BCmp");
+	}
+}

+ 23 - 0
liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/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.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("b")
+public class BCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("BCmp executed!");
+		System.out.println("BCmp param:" + this.getSlot().getInput("BCmp"));
+		this.getSlot().setOutput("CCmp", "param for CCmp");
+	}
+
+}

+ 22 - 0
liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/CCmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("c")
+public class CCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("CCmp executed!");
+		System.out.println("CCmp param:" + this.getSlot().getOutput("CCmp"));
+	}
+
+}

+ 1 - 0
liteflow-testcase-springboot/src/test/resources/nullParam/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=nullParam/flow.xml

+ 7 - 0
liteflow-testcase-springboot/src/test/resources/nullParam/flow.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <chain name="chain1">
+        <then value="a,b"/>
+        <when value="c"/>
+    </chain>
+</flow>

+ 35 - 0
liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/NullParamTest.java

@@ -0,0 +1,35 @@
+package com.yomahub.liteflow.test.nullParam;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.entity.data.DefaultSlot;
+import com.yomahub.liteflow.entity.data.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+
+/**
+ * 单元测试:传递null param导致NPE的优化代码
+ * @author LeoLee
+ * @since 2.6.6
+ **/
+@RunWith(SpringRunner.class)
+@ContextConfiguration("classpath:/nullParam/application-local.xml")
+public class NullParamTest extends BaseTest {
+
+    @Resource
+    private FlowExecutor flowExecutor;
+
+    /**
+     * 支持无参的flow执行,以及param 为null时的异常抛出
+     */
+    @Test
+    public void testNullParam() throws Exception {
+        LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
+        Assert.assertTrue(response.isSuccess());
+    }
+}

+ 22 - 0
liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/ACmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a")
+public class ACmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("ACmp executed!");
+		System.out.println("get request data:" + this.getSlot().getRequestData());
+		this.getSlot().setInput("BCmp", "param for BCmp");
+	}
+}

+ 23 - 0
liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/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.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("b")
+public class BCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("BCmp executed!");
+		System.out.println("BCmp param:" + this.getSlot().getInput("BCmp"));
+		this.getSlot().setOutput("CCmp", "param for CCmp");
+	}
+
+}

+ 22 - 0
liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/nullParam/cmp/CCmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.nullParam.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("c")
+public class CCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("CCmp executed!");
+		System.out.println("CCmp param:" + this.getSlot().getOutput("CCmp"));
+	}
+
+}

+ 23 - 0
liteflow-testcase-springnative/src/test/resources/nullParam/application-local.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
+       http://www.springframework.org/schema/context
+       http://www.springframework.org/schema/context/spring-context-4.0.xsd">
+
+    <context:component-scan base-package="com.yomahub.liteflow.test.nullParam.cmp" />
+
+    <bean id="springAware" class="com.yomahub.liteflow.util.SpringAware"/>
+
+    <bean class="com.yomahub.liteflow.spring.ComponentScanner"/>
+
+    <bean id="liteflowConfig" class="com.yomahub.liteflow.property.LiteflowConfig">
+        <property name="ruleSource" value="nullParam/flow.xml"/>
+    </bean>
+
+    <bean id="flowExecutor" class="com.yomahub.liteflow.core.FlowExecutor">
+        <property name="liteflowConfig" ref="liteflowConfig"/>
+    </bean>
+</beans>

+ 8 - 0
liteflow-testcase-springnative/src/test/resources/nullParam/flow.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <chain name="chain1">
+        <!--同步执行-->
+        <then value="a,b"/>
+        <when value="c"/>
+    </chain>
+</flow>