新增自动节点
This commit is contained in:
@@ -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> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<FlowableAction, String> nextNodes;
|
||||
@CollectionTable(name = "flowable_node_manual_actions", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
private Map<FlowableAction, String> 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;
|
||||
}
|
||||
|
||||
@@ -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<String, Object> metadata) {
|
||||
log.info("Initial with spring: {}", flowableManager.listNodes());
|
||||
return FlowableAction.APPROVE;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, Object> 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<String, Object> 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> T createBean(String classpath);
|
||||
|
||||
public interface IdGenerator {
|
||||
String createId();
|
||||
}
|
||||
|
||||
@@ -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<FlowableAction, String> nextNodes;
|
||||
private final List<Class<? extends FlowableListener>> listeners;
|
||||
private final String automaticAction;
|
||||
private final Map<FlowableAction, String> manualActions;
|
||||
|
||||
private final List<String> listeners;
|
||||
private final LocalDateTime createdTime;
|
||||
|
||||
private LocalDateTime updatedTime = LocalDateTime.now();
|
||||
|
||||
public FlowableNode(String nodeId, String name, String description, Type type, Map<FlowableAction, String> nextNodes) {
|
||||
this(nodeId, name, description, type, nextNodes, ListHelper.empty(), LocalDateTime.now());
|
||||
public FlowableNode(String nodeId, String name, String description, Type type, String automaticAction, Map<FlowableAction, String> manualActions) {
|
||||
this(nodeId, name, description, type, automaticAction, manualActions, ListHelper.empty(), LocalDateTime.now());
|
||||
}
|
||||
|
||||
public FlowableNode(String nodeId, String name, String description, Type type, Map<FlowableAction, String> nextNodes, List<Class<? extends FlowableListener>> listeners, LocalDateTime createdTime) {
|
||||
public FlowableNode(String nodeId, String name, String description, Type type, String automaticAction, Map<FlowableAction, String> manualActions, List<String> 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<String, Object> metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, Object> metadata) {
|
||||
return FlowableAction.APPROVE;
|
||||
}
|
||||
}
|
||||
@@ -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> T createBean(String classpath) {
|
||||
return (T) Class.forName(classpath).newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user