新增自动节点
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.manager.FlowableManager;
|
||||||
import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository;
|
import com.lanyuanxiaoyao.flowable.core.repository.FlowableRepository;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
* @version 20241231
|
* @version 20241231
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class SpringFlowableManager extends FlowableManager {
|
public class SpringFlowableManager extends FlowableManager {
|
||||||
public SpringFlowableManager(FlowableRepository flowableRepository) {
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public SpringFlowableManager(FlowableRepository flowableRepository, ApplicationContext applicationContext) {
|
||||||
super(flowableRepository, () -> UUID.randomUUID().toString());
|
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)
|
@Column(nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private FlowableNode.Type type;
|
private FlowableNode.Type type;
|
||||||
|
private String automaticAction;
|
||||||
@ElementCollection(fetch = javax.persistence.FetchType.EAGER)
|
@ElementCollection(fetch = javax.persistence.FetchType.EAGER)
|
||||||
@MapKeyColumn(name = "action")
|
@MapKeyColumn(name = "action")
|
||||||
@Column(name = "nodeId")
|
@Column(name = "nodeId")
|
||||||
@CollectionTable(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
@CollectionTable(name = "flowable_node_manual_actions", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
private Map<FlowableAction, String> nextNodes;
|
private Map<FlowableAction, String> manualActions;
|
||||||
|
|
||||||
@CreatedDate
|
@CreatedDate
|
||||||
private LocalDateTime createdTime;
|
private LocalDateTime createdTime;
|
||||||
@LastModifiedDate
|
@LastModifiedDate
|
||||||
@@ -61,11 +64,12 @@ public class JpaFlowableNode {
|
|||||||
this.name = node.getName();
|
this.name = node.getName();
|
||||||
this.description = node.getDescription();
|
this.description = node.getDescription();
|
||||||
this.type = node.getType();
|
this.type = node.getType();
|
||||||
this.nextNodes = node.getNextNodes();
|
this.automaticAction = node.getAutomaticAction();
|
||||||
|
this.manualActions = node.getManualActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowableNode toFlowableNode() {
|
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);
|
node.setUpdatedTime(updateTime);
|
||||||
return node;
|
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;
|
package com.lanyuanxiaoyao.flowable.jpa;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.flowable.core.SimpleAutoAction;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,4 +16,9 @@ public class SpringFlowableApplication {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(SpringFlowableApplication.class, args);
|
SpringApplication.run(SpringFlowableApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SimpleAutoAction simpleAutoAction() {
|
||||||
|
return new SimpleAutoAction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public abstract class FlowableManager {
|
|||||||
flowableRepository.saveInstance(instance);
|
flowableRepository.saveInstance(instance);
|
||||||
|
|
||||||
if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) {
|
if (FlowableNode.Type.AUTOMATIC.equals(node.getType())) {
|
||||||
action(instance, node, FlowableAction.APPROVE, "系统审批通过", MapHelper.empty());
|
autoAction(instance, node, MapHelper.empty());
|
||||||
}
|
}
|
||||||
return instance.getInstanceId();
|
return instance.getInstanceId();
|
||||||
}
|
}
|
||||||
@@ -103,6 +103,15 @@ public abstract class FlowableManager {
|
|||||||
action(instanceId, action, comment, MapHelper.empty());
|
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) {
|
private void action(String instanceId, FlowableAction action, String comment, Map<String, Object> metadata) {
|
||||||
FlowableInstance instance = flowableRepository.getInstance(instanceId);
|
FlowableInstance instance = flowableRepository.getInstance(instanceId);
|
||||||
FlowableNode node = flowableRepository.getNode(instance.getCurrentNodeId());
|
FlowableNode node = flowableRepository.getNode(instance.getCurrentNodeId());
|
||||||
@@ -117,19 +126,19 @@ public abstract class FlowableManager {
|
|||||||
saveInstance(instance, FlowableInstance.Status.ERROR, metadata, action, comment);
|
saveInstance(instance, FlowableInstance.Status.ERROR, metadata, action, comment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Objects.isNull(node.getNextNodes())
|
if (Objects.isNull(node.getManualActions())
|
||||||
|| !node.getNextNodes().containsKey(action)
|
|| !node.getManualActions().containsKey(action)
|
||||||
|| StringHelper.isBlank(node.getNextNodes().get(action))) {
|
|| StringHelper.isBlank(node.getManualActions().get(action))) {
|
||||||
saveInstance(instance, FlowableInstance.Status.COMPLETED, metadata, action, comment);
|
saveInstance(instance, FlowableInstance.Status.COMPLETED, metadata, action, comment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String nextNodeId = node.getNextNodes().get(action);
|
String nextNodeId = node.getManualActions().get(action);
|
||||||
FlowableNode nextNode = flowableRepository.getNode(nextNodeId);
|
FlowableNode nextNode = flowableRepository.getNode(nextNodeId);
|
||||||
instance.setCurrentNodeId(nextNode.getNodeId());
|
instance.setCurrentNodeId(nextNode.getNodeId());
|
||||||
saveInstance(instance, FlowableInstance.Status.RUNNING, metadata, action, comment);
|
saveInstance(instance, FlowableInstance.Status.RUNNING, metadata, action, comment);
|
||||||
|
|
||||||
if (FlowableNode.Type.AUTOMATIC.equals(nextNode.getType())) {
|
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 {
|
public interface IdGenerator {
|
||||||
String createId();
|
String createId();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,27 @@ public class FlowableNode {
|
|||||||
private final String nodeId;
|
private final String nodeId;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
private final Type type;
|
private final Type type;
|
||||||
private final Map<FlowableAction, String> nextNodes;
|
private final String automaticAction;
|
||||||
private final List<Class<? extends FlowableListener>> listeners;
|
private final Map<FlowableAction, String> manualActions;
|
||||||
|
|
||||||
|
private final List<String> listeners;
|
||||||
private final LocalDateTime createdTime;
|
private final LocalDateTime createdTime;
|
||||||
|
|
||||||
private LocalDateTime updatedTime = LocalDateTime.now();
|
private LocalDateTime updatedTime = LocalDateTime.now();
|
||||||
|
|
||||||
public FlowableNode(String nodeId, String name, String description, Type type, Map<FlowableAction, String> nextNodes) {
|
public FlowableNode(String nodeId, String name, String description, Type type, String automaticAction, Map<FlowableAction, String> manualActions) {
|
||||||
this(nodeId, name, description, type, nextNodes, ListHelper.empty(), LocalDateTime.now());
|
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.nodeId = nodeId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.nextNodes = nextNodes;
|
this.automaticAction = automaticAction;
|
||||||
|
this.manualActions = manualActions;
|
||||||
this.listeners = listeners;
|
this.listeners = listeners;
|
||||||
this.createdTime = createdTime;
|
this.createdTime = createdTime;
|
||||||
}
|
}
|
||||||
@@ -42,4 +46,8 @@ public class FlowableNode {
|
|||||||
AUTOMATIC,
|
AUTOMATIC,
|
||||||
MANUAL,
|
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(),
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
FlowableNode.Type.MANUAL,
|
FlowableNode.Type.MANUAL,
|
||||||
|
null,
|
||||||
nextNodes
|
nextNodes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -120,4 +121,20 @@ public abstract class TestFlowableManager {
|
|||||||
|
|
||||||
Assertions.assertThrows(IllegalArgumentException.class, () -> manager.approve(instanceId));
|
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 com.lanyuanxiaoyao.flowable.core.manager.FlowableManager;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lanyuanxiaoyao
|
* @author lanyuanxiaoyao
|
||||||
@@ -11,4 +12,10 @@ public class SimpleFlowableManager extends FlowableManager {
|
|||||||
public SimpleFlowableManager() {
|
public SimpleFlowableManager() {
|
||||||
super(new InMemoryFlowableRepository(), () -> UUID.randomUUID().toString());
|
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