Merge remote-tracking branch 'origin/feature/starter' into feature/starter

# Conflicts:
#	workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowCoreService.java
This commit is contained in:
yangqicheng 2024-05-29 14:24:15 +08:00
commit f83d9fb8bb
17 changed files with 192 additions and 188 deletions

View File

@ -1,13 +1,17 @@
package cn.axzo.workflow.server.controller.web;
import cn.axzo.workflow.client.feign.bpmn.ProcessInstanceApi;
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.core.service.BpmnProcessInstanceService;
import cn.axzo.workflow.core.service.support.FlowNodeForecastService;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.axzo.workflow.starter.api.WorkflowCoreService;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
@ -58,6 +62,8 @@ public class TestController {
private ProcessInstanceApi processInstanceApi;
@Autowired
private BpmnProcessInstanceService bpmnProcessInstanceService;
@Autowired
private WorkflowCoreService workflowCoreService;
@RepeatSubmit
@GetMapping("/test")
@ -124,4 +130,14 @@ public class TestController {
return CommonResponse.success(true);
}
@GetMapping("/test5")
public CommonResponse<Boolean> test5() {
BpmnProcessInstanceCreateDTO dto = new BpmnProcessInstanceCreateDTO();
dto.setProcessDefinitionKey("1");
dto.setCooperationOrg(new CooperationOrgDTO());
dto.setBusinessKey("businessKey");
dto.setInitiator(new BpmnTaskDelegateAssigner());
workflowCoreService.createProcessInstance(dto);
return CommonResponse.success(true);
}
}

View File

@ -6,13 +6,11 @@ import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.framework.rocketmq.EventHandlerRepository;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.framework.rocketmq.RocketMQEventProducer;
import cn.axzo.workflow.starter.common.annotation.EnableWorkflowClient;
import cn.axzo.workflow.starter.invoke.ComplexInvokeClient;
import cn.axzo.workflow.starter.api.WorkflowCoreService;
import cn.axzo.workflow.starter.mq.broadcast.consumer.WorkflowEngineBroadcastEventListener;
import cn.axzo.workflow.starter.mq.retry.consumer.WorkflowEngineClientRetryEventListener;
import cn.axzo.workflow.starter.mq.retry.producer.RpcInvokeEventProducer;
import cn.axzo.workflow.starter.service.WorkflowEngineServiceFacade;
import feign.Client;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
@ -23,6 +21,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@ -39,11 +38,11 @@ import java.util.function.Consumer;
* @since 2024/5/21 11:47
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WorkflowEngineProperties.class)
@EnableWorkflowClient
public class WorkflowEngineAutoConfiguration {
@EnableConfigurationProperties(WorkflowEngineStarterProperties.class)
@EnableFeignClients(clients = {WorkflowCoreService.class})
public class WorkflowEngineStarterAutoConfiguration {
private final Logger log = LoggerFactory.getLogger(WorkflowEngineAutoConfiguration.class);
private final Logger log = LoggerFactory.getLogger(WorkflowEngineStarterAutoConfiguration.class);
private static final String DEFAULT_MODULE = "workflowEngine";
private static final String DEFAULT_EVENT = "topic_workflow_engine";
@ -55,14 +54,10 @@ public class WorkflowEngineAutoConfiguration {
@Bean
public WorkflowEngineServiceFacade workflowEngineServiceFacade(EventProducer workflowEngineClientEventProducer,
WorkflowEngineProperties workflowEngineProperties) {
return new WorkflowEngineServiceFacade(workflowEngineClientEventProducer, workflowEngineProperties);
WorkflowEngineStarterProperties workflowEngineStarterProperties) {
return new WorkflowEngineServiceFacade(workflowEngineClientEventProducer, workflowEngineStarterProperties);
}
@Bean
public Client ComplexInvokeClient() {
return new ComplexInvokeClient();
}
/**
* 客户端 RPC Retry 事件生产者

View File

@ -1,15 +1,18 @@
package cn.axzo.workflow.starter;
import cn.axzo.workflow.starter.common.enums.RpcInvokeModeEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static cn.axzo.workflow.starter.common.enums.RpcInvokeModeEnum.SYNC;
/**
* Workflow Engine Starter Properties
*
* @author wangli
* @since 2024/5/21 15:24
*/
@ConfigurationProperties(prefix = "workflow.engine.client")
public class WorkflowEngineProperties {
@ConfigurationProperties(prefix = "workflow.engine.starter")
public class WorkflowEngineStarterProperties {
/**
* 是否可管理
*/
@ -20,6 +23,11 @@ public class WorkflowEngineProperties {
*/
private Boolean localConsumer = false;
/**
* 方法调用默认采用的模式
*/
private RpcInvokeModeEnum invokeMode = SYNC;
private Boolean autoAck = false;
public Boolean getManageable() {
@ -38,6 +46,14 @@ public class WorkflowEngineProperties {
this.localConsumer = localConsumer;
}
public RpcInvokeModeEnum getInvokeMode() {
return invokeMode;
}
public void setInvokeMode(RpcInvokeModeEnum invokeMode) {
this.invokeMode = invokeMode;
}
public Boolean getAutoAck() {
return autoAck;
}

View File

@ -1,29 +0,0 @@
package cn.axzo.workflow.starter.common.annotation;
import cn.axzo.workflow.starter.invoke.WorkflowEngineClientRegistrar;
import org.springframework.context.annotation.Import;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* TODO
*
* @author wangli
* @since 2024/5/28 16:27
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(WorkflowEngineClientRegistrar.class)
public @interface EnableWorkflowClient {
String[] basePackages() default {"cn.axzo.workflow.starter.api"};
String name() default "workflow-engine-client";
String url() default "${axzo.service.workflow-engine:workflow-engine:8080}";
}

View File

@ -0,0 +1,11 @@
package cn.axzo.workflow.starter.common.constant;
/**
* Starter 常量类
*
* @author wangli
* @since 2024/5/29 11:13
*/
public interface StarterConstants {
String STARTER_INVOKE_MODE = "Workflow-Engine-Starter-Invoke-Mode";
}

View File

@ -0,0 +1,12 @@
package cn.axzo.workflow.starter.common.enums;
/**
* TODO
*
* @author wangli
* @since 2024/5/29 10:27
*/
public enum RpcInvokeModeEnum {
SYNC,
ASYNC,
}

View File

@ -6,5 +6,8 @@ package cn.axzo.workflow.starter.common.exception;
* @author wangli
* @since 2024/5/21 17:59
*/
public class AsyncNotSupportException extends WorkflowEngineClientException {
public class AsyncNotSupportException extends WorkflowEngineStarterException {
public AsyncNotSupportException(String message) {
super(message);
}
}

View File

@ -6,5 +6,8 @@ package cn.axzo.workflow.starter.common.exception;
* @author wangli
* @since 2024/5/22 13:41
*/
public class CreateProcessInstanceException extends WorkflowEngineClientException {
public class CreateProcessInstanceException extends WorkflowEngineStarterException {
public CreateProcessInstanceException(String message) {
super(message);
}
}

View File

@ -6,5 +6,8 @@ package cn.axzo.workflow.starter.common.exception;
* @author wangli
* @since 2024/5/21 17:59
*/
public class ManagementDisabledException extends WorkflowEngineClientException {
public class ManagementDisabledException extends WorkflowEngineStarterException {
public ManagementDisabledException(String message) {
super(message);
}
}

View File

@ -1,10 +0,0 @@
package cn.axzo.workflow.starter.common.exception;
/**
* TODO
*
* @author wangli
* @since 2024/5/21 17:57
*/
public class WorkflowEngineClientException extends RuntimeException {
}

View File

@ -0,0 +1,14 @@
package cn.axzo.workflow.starter.common.exception;
/**
* TODO
*
* @author wangli
* @since 2024/5/21 17:57
*/
public class WorkflowEngineStarterException extends RuntimeException {
public WorkflowEngineStarterException(String message) {
super(message);
}
}

View File

@ -0,0 +1,64 @@
package cn.axzo.workflow.starter.feign.ext;
import cn.axzo.workflow.starter.WorkflowEngineStarterProperties;
import cn.axzo.workflow.starter.common.enums.RpcInvokeModeEnum;
import cn.axzo.workflow.starter.common.exception.WorkflowEngineStarterException;
import feign.Client;
import feign.Request;
import feign.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import static cn.axzo.workflow.starter.common.constant.StarterConstants.STARTER_INVOKE_MODE;
import static cn.axzo.workflow.starter.common.enums.RpcInvokeModeEnum.SYNC;
/**
* 适用于 Starter 中复合型的 FeignClient 实现
* <p>
* 如果使用方调用的服务方法是同步则使用原生的 FeignClient 实现 否则通过 MQ 事件解耦请求
*
* @author wangli
* @since 2024/5/28 15:23
*/
public class ComplexInvokeClient implements Client {
private final Logger log = LoggerFactory.getLogger(ComplexInvokeClient.class);
private final WorkflowEngineStarterProperties starterProperties;
private final Client feignClient;
public ComplexInvokeClient(WorkflowEngineStarterProperties starterProperties, Client feignClient) {
this.starterProperties = starterProperties;
this.feignClient = feignClient;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
log.info("ComplexInvokeClient execute");
RpcInvokeModeEnum invokeMode = getInvokeMode(request);
if (Objects.equals(SYNC, invokeMode)) {
return feignClient.execute(request, options);
}
Map<String, Collection<String>> headers = request.headers();
headers.forEach((k, v) -> log.info("ComplexInvokeClient header: {} = {}", k, v));
return null;
}
private RpcInvokeModeEnum getInvokeMode(Request request) {
Collection<String> invokeModel = request.headers().getOrDefault(STARTER_INVOKE_MODE,
Collections.singletonList(starterProperties.getInvokeMode().name()));
if (invokeModel == null || invokeModel.isEmpty()) {
return starterProperties.getInvokeMode();
} else if (invokeModel.size() > 1) {
throw new WorkflowEngineStarterException("Multiple invoke mode is not supported");
}
return RpcInvokeModeEnum.valueOf(invokeModel.iterator().next());
}
}

View File

@ -0,0 +1,32 @@
package cn.axzo.workflow.starter.feign.ext;
import cn.axzo.workflow.starter.WorkflowEngineStarterProperties;
import feign.Client;
import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import static cn.axzo.workflow.client.config.WorkflowRequestInterceptor.HEADER_SERVER_NAME;
import static cn.axzo.workflow.starter.common.constant.StarterConstants.STARTER_INVOKE_MODE;
/**
* Starter Feign Client 的自定义的配置
*
* @author wangli
* @since 2024/5/28 23:17
*/
public class WorkflowEngineStarterConfiguration {
@Bean
public Client complexInvokeClient(WorkflowEngineStarterProperties starterProperties, Client feignClient) {
return new ComplexInvokeClient(starterProperties, feignClient);
}
@Bean
public RequestInterceptor workflowEngineStarterRequestInterceptor(WorkflowEngineStarterProperties starterProperties, Environment environment) {
return template -> {
template.header(HEADER_SERVER_NAME, environment.getProperty("spring.application.name"));
template.header(STARTER_INVOKE_MODE, starterProperties.getInvokeMode().name());
};
}
}

View File

@ -1,26 +0,0 @@
package cn.axzo.workflow.starter.invoke;
import feign.Client;
import feign.Request;
import feign.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* TODO
*
* @author wangli
* @since 2024/5/28 15:23
*/
public class ComplexInvokeClient implements Client {
private final Logger log = LoggerFactory.getLogger(ComplexInvokeClient.class);
@Override
public Response execute(Request request, Request.Options options) throws IOException {
log.info("ComplexInvokeClient execute");
return null;
}
}

View File

@ -1,100 +0,0 @@
package cn.axzo.workflow.starter.invoke;
import cn.axzo.workflow.starter.common.annotation.EnableWorkflowClient;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* TODO
*
* @author wangli
* @since 2024/5/28 16:18
*/
public class WorkflowEngineClientRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.setResourceLoader(this.resourceLoader);
Set<String> basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = new HashMap<>();
registerWorkflowEngineClient(registry, annotationMetadata, attributes);
}
}
}
private void registerWorkflowEngineClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
}
protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
}
protected Set<String> getBasePackages(AnnotationMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(EnableWorkflowClient.class.getCanonicalName());
Set<String> basePackages = new HashSet<>();
for (String pkg : (String[]) attributes.get("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
return basePackages;
}
}

View File

@ -5,7 +5,7 @@ import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbo
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.starter.WorkflowEngineProperties;
import cn.axzo.workflow.starter.WorkflowEngineStarterProperties;
import cn.axzo.workflow.starter.common.exception.CreateProcessInstanceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,12 +22,12 @@ import java.util.Map;
public class WorkflowEngineServiceFacade {
private final Logger log = LoggerFactory.getLogger(WorkflowEngineServiceFacade.class);
private final EventProducer workflowEngineClientEventProducer;
private final WorkflowEngineProperties workflowEngineProperties;
private final WorkflowEngineStarterProperties workflowEngineStarterProperties;
public WorkflowEngineServiceFacade(EventProducer workflowEngineClientEventProducer,
WorkflowEngineProperties workflowEngineProperties) {
WorkflowEngineStarterProperties workflowEngineStarterProperties) {
this.workflowEngineClientEventProducer = workflowEngineClientEventProducer;
this.workflowEngineProperties = workflowEngineProperties;
this.workflowEngineStarterProperties = workflowEngineStarterProperties;
}
/**

View File

@ -1,2 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.axzo.workflow.starter.WorkflowEngineAutoConfiguration
cn.axzo.workflow.starter.WorkflowEngineStarterAutoConfiguration