From c3ca027f720e5b2f98d108857463c9e6de636505 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Thu, 2 Jan 2025 17:43:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=87=AA=E5=8A=A8=E8=8A=82?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/jpa/SpringFlowableManager.java | 27 ++++++++++++++++++- .../flowable/jpa/entity/JpaFlowableNode.java | 12 ++++++--- .../flowable/core/SimpleAutoAction.java | 25 +++++++++++++++++ .../jpa/SpringFlowableApplication.java | 7 +++++ .../core/manager/FlowableManager.java | 23 +++++++++++----- .../flowable/core/model/FlowableNode.java | 20 +++++++++----- .../core/test/TestFlowableManager.java | 17 ++++++++++++ .../flowable/core/SimpleAutoAction.java | 17 ++++++++++++ .../flowable/core/SimpleFlowableManager.java | 7 +++++ 9 files changed, 138 insertions(+), 17 deletions(-) create mode 100644 adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java create mode 100644 flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java diff --git a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableManager.java b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableManager.java index 6fc8453..79af33a 100644 --- a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableManager.java +++ b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableManager.java @@ -3,15 +3,40 @@ package com.lanyuanxiaoyao.flowable.jpa; import com.lanyuanxiaoyao.flowable.core.manager.FlowableManager; import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository; import java.util.UUID; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; /** * @author lanyuanxiaoyao * @version 20241231 */ +@Slf4j @Service public class SpringFlowableManager extends FlowableManager { - public SpringFlowableManager(FlowableRepository flowableRepository) { + private final ApplicationContext applicationContext; + + public SpringFlowableManager(FlowableRepository flowableRepository, ApplicationContext applicationContext) { super(flowableRepository, () -> UUID.randomUUID().toString()); + this.applicationContext = applicationContext; + } + + @SneakyThrows + @Override + protected T createBean(String classpath) { + Class clazz = Class.forName(classpath); + T targetObject = null; + try { + targetObject = (T) applicationContext.getBean(clazz); + } catch (Exception springException) { + log.warn("{} not found in spring context", springException); + try { + targetObject = (T) clazz.newInstance(); + } catch (Exception javaException) { + throw new IllegalArgumentException(javaException); + } + } + return targetObject; } } diff --git a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/JpaFlowableNode.java b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/JpaFlowableNode.java index d38eb75..50d7319 100644 --- a/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/JpaFlowableNode.java +++ b/adapter/flowable-spring-boot-jpa-starter/src/main/java/com/lanyuanxiaoyao/flowable/jpa/entity/JpaFlowableNode.java @@ -43,14 +43,17 @@ public class JpaFlowableNode { @Column(nullable = false) private String name; private String description; + @Enumerated(EnumType.STRING) @Column(nullable = false) private FlowableNode.Type type; + private String automaticAction; @ElementCollection(fetch = javax.persistence.FetchType.EAGER) @MapKeyColumn(name = "action") @Column(name = "nodeId") - @CollectionTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) - private Map nextNodes; + @CollectionTable(name = "flowable_node_manual_actions", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + private Map manualActions; + @CreatedDate private LocalDateTime createdTime; @LastModifiedDate @@ -61,11 +64,12 @@ public class JpaFlowableNode { this.name = node.getName(); this.description = node.getDescription(); this.type = node.getType(); - this.nextNodes = node.getNextNodes(); + this.automaticAction = node.getAutomaticAction(); + this.manualActions = node.getManualActions(); } public FlowableNode toFlowableNode() { - FlowableNode node = new FlowableNode(nodeId, name, description, type, nextNodes, null, createdTime); + FlowableNode node = new FlowableNode(nodeId, name, description, type, automaticAction, manualActions, null, createdTime); node.setUpdatedTime(updateTime); return node; } diff --git a/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java new file mode 100644 index 0000000..f96e854 --- /dev/null +++ b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java @@ -0,0 +1,25 @@ +package com.lanyuanxiaoyao.flowable.core; + +import com.lanyuanxiaoyao.flowable.core.manager.FlowableManager; +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import java.util.Map; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; + +/** + * @author lanyuanxiaoyao + * @version 20250102 + */ +@Slf4j +public class SimpleAutoAction implements FlowableNode.AutoAction { + @Resource + private FlowableManager flowableManager; + + @Override + public FlowableAction action(FlowableInstance instance, FlowableNode node, Map metadata) { + log.info("Initial with spring: {}", flowableManager.listNodes()); + return FlowableAction.APPROVE; + } +} diff --git a/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableApplication.java b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableApplication.java index 481ee24..dc7e4ef 100644 --- a/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableApplication.java +++ b/adapter/flowable-spring-boot-jpa-starter/src/test/java/com/lanyuanxiaoyao/flowable/jpa/SpringFlowableApplication.java @@ -1,7 +1,9 @@ package com.lanyuanxiaoyao.flowable.jpa; +import com.lanyuanxiaoyao.flowable.core.SimpleAutoAction; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; /** @@ -14,4 +16,9 @@ public class SpringFlowableApplication { public static void main(String[] args) { SpringApplication.run(SpringFlowableApplication.class, args); } + + @Bean + public SimpleAutoAction simpleAutoAction() { + return new SimpleAutoAction(); + } } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java index c84c4d9..74414c3 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/manager/FlowableManager.java @@ -70,7 +70,7 @@ public abstract class FlowableManager { flowableRepository.saveInstance(instance); if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) { - action(instance, node, FlowableAction.APPROVE, "系统审批通过", MapHelper.empty()); + autoAction(instance, node, MapHelper.empty()); } return instance.getInstanceId(); } @@ -103,6 +103,15 @@ public abstract class FlowableManager { action(instanceId, action, comment, MapHelper.empty()); } + private void autoAction(FlowableInstance instance, FlowableNode node, Map metadata) { + String actionClass = node.getAutomaticAction(); + if (StringHelper.isBlank(actionClass)) { + throw new IllegalArgumentException("自动节点执行器为空"); + } + FlowableNode.AutoAction autoAction = createBean(actionClass); + action(instance, node, autoAction.action(instance, node, metadata), "系统自动执行", metadata); + } + private void action(String instanceId, FlowableAction action, String comment, Map metadata) { FlowableInstance instance = flowableRepository.getInstance(instanceId); FlowableNode node = flowableRepository.getNode(instance.getCurrentNodeId()); @@ -117,19 +126,19 @@ public abstract class FlowableManager { saveInstance(instance, FlowableInstance.Status.ERROR, metadata, action, comment); return; } - if (Objects.isNull(node.getNextNodes()) - || !node.getNextNodes().containsKey(action) - || StringHelper.isBlank(node.getNextNodes().get(action))) { + if (Objects.isNull(node.getManualActions()) + || !node.getManualActions().containsKey(action) + || StringHelper.isBlank(node.getManualActions().get(action))) { saveInstance(instance, FlowableInstance.Status.COMPLETED, metadata, action, comment); return; } - String nextNodeId = node.getNextNodes().get(action); + String nextNodeId = node.getManualActions().get(action); FlowableNode nextNode = flowableRepository.getNode(nextNodeId); instance.setCurrentNodeId(nextNode.getNodeId()); saveInstance(instance, FlowableInstance.Status.RUNNING, metadata, action, comment); if (FlowableNode.Type.AUTOMATIC.equals(nextNode.getType())) { - action(instance, node, FlowableAction.APPROVE, "系统审批通过", metadata); + autoAction(instance, node, metadata); } } @@ -150,6 +159,8 @@ public abstract class FlowableManager { } } + protected abstract T createBean(String classpath); + public interface IdGenerator { String createId(); } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableNode.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableNode.java index 8b73543..fa6dfdd 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableNode.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/model/FlowableNode.java @@ -17,23 +17,27 @@ public class FlowableNode { private final String nodeId; private final String name; private final String description; + private final Type type; - private final Map nextNodes; - private final List> listeners; + private final String automaticAction; + private final Map manualActions; + + private final List listeners; private final LocalDateTime createdTime; private LocalDateTime updatedTime = LocalDateTime.now(); - public FlowableNode(String nodeId, String name, String description, Type type, Map nextNodes) { - this(nodeId, name, description, type, nextNodes, ListHelper.empty(), LocalDateTime.now()); + public FlowableNode(String nodeId, String name, String description, Type type, String automaticAction, Map manualActions) { + this(nodeId, name, description, type, automaticAction, manualActions, ListHelper.empty(), LocalDateTime.now()); } - public FlowableNode(String nodeId, String name, String description, Type type, Map nextNodes, List> listeners, LocalDateTime createdTime) { + public FlowableNode(String nodeId, String name, String description, Type type, String automaticAction, Map manualActions, List listeners, LocalDateTime createdTime) { this.nodeId = nodeId; this.name = name; this.description = description; this.type = type; - this.nextNodes = nextNodes; + this.automaticAction = automaticAction; + this.manualActions = manualActions; this.listeners = listeners; this.createdTime = createdTime; } @@ -42,4 +46,8 @@ public class FlowableNode { AUTOMATIC, MANUAL, } + + public interface AutoAction { + FlowableAction action(FlowableInstance instance, FlowableNode node, Map metadata); + } } diff --git a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/test/TestFlowableManager.java b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/test/TestFlowableManager.java index eefa04e..c14a693 100644 --- a/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/test/TestFlowableManager.java +++ b/flowable-core/src/main/java/com/lanyuanxiaoyao/flowable/core/test/TestFlowableManager.java @@ -35,6 +35,7 @@ public abstract class TestFlowableManager { UUID.randomUUID().toString(), UUID.randomUUID().toString(), FlowableNode.Type.MANUAL, + null, nextNodes ); } @@ -120,4 +121,20 @@ public abstract class TestFlowableManager { Assertions.assertThrows(IllegalArgumentException.class, () -> manager.approve(instanceId)); } + + @Test + public void testAutomaticNode() { + FlowableManager manager = flowableManager(); + FlowableNode node = new FlowableNode( + "2733d930-7a4b-491e-b1ca-4d5811435e9f", + "自动节点", + "自动节点", + FlowableNode.Type.AUTOMATIC, + "com.lanyuanxiaoyao.flowable.core.SimpleAutoAction", + null + ); + manager.create(node); + String instanceId = manager.start(node.getNodeId()); + Assertions.assertEquals(FlowableInstance.Status.COMPLETED, manager.getInstance(instanceId).getStatus()); + } } diff --git a/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java b/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java new file mode 100644 index 0000000..900c822 --- /dev/null +++ b/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleAutoAction.java @@ -0,0 +1,17 @@ +package com.lanyuanxiaoyao.flowable.core; + +import com.lanyuanxiaoyao.flowable.core.model.FlowableAction; +import com.lanyuanxiaoyao.flowable.core.model.FlowableInstance; +import com.lanyuanxiaoyao.flowable.core.model.FlowableNode; +import java.util.Map; + +/** + * @author lanyuanxiaoyao + * @version 20250102 + */ +public class SimpleAutoAction implements FlowableNode.AutoAction { + @Override + public FlowableAction action(FlowableInstance instance, FlowableNode node, Map metadata) { + return FlowableAction.APPROVE; + } +} diff --git a/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleFlowableManager.java b/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleFlowableManager.java index 590c430..741697a 100644 --- a/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleFlowableManager.java +++ b/flowable-core/src/test/java/com/lanyuanxiaoyao/flowable/core/SimpleFlowableManager.java @@ -2,6 +2,7 @@ package com.lanyuanxiaoyao.flowable.core; import com.lanyuanxiaoyao.flowable.core.manager.FlowableManager; import java.util.UUID; +import lombok.SneakyThrows; /** * @author lanyuanxiaoyao @@ -11,4 +12,10 @@ public class SimpleFlowableManager extends FlowableManager { public SimpleFlowableManager() { super(new InMemoryFlowableRepository(), () -> UUID.randomUUID().toString()); } + + @SneakyThrows + @Override + protected T createBean(String classpath) { + return (T) Class.forName(classpath).newInstance(); + } }