springboot中集成flowable过程中出现的问题
1.实现服务任务的监听事件,该实现类实现了JavaDelegate接口时,直接使用@Resource注入的bean是null
原因:flowable执行监听事件时,是通过反射获取bean的,此时该bean不在spring的管理中,需要使用ApplicationContext来获取bean
import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @Service @Lazy(false) public class SpringContextHolder implements ApplicationContextAware, DisposableBean { private static ApplicationContext applicationContext = null; private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class); /** * 取得存储在静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { assertContextInjected(); return applicationContext; } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } /** * 清除SpringContextHolder中的ApplicationContext为Null. */ public static void clearHolder() { if (logger.isDebugEnabled()){ logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); } applicationContext = null; } /** * 实现ApplicationContextAware接口, 注入Context到静态变量中. */ public void setApplicationContext(ApplicationContext applicationContext) { // logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); if (SpringContextHolder.applicationContext != null) { logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); } SpringContextHolder.applicationContext = applicationContext; } /** * 实现DisposableBean接口, 在Context关闭时清理静态变量. */ public void destroy() throws Exception { SpringContextHolder.clearHolder(); } /** * 检查ApplicationContext不为空. */ private static void assertContextInjected() { Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); } }
package com.insgeek.platform.flow.adapter.listener; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import javax.annotation.Resource; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.JavaDelegate; import org.springframework.util.CollectionUtils; import com.insgeek.boot.web.context.IdentityContext; import com.insgeek.platform.flow.adapter.config.FlowConstants; import com.insgeek.platform.flow.enums.ElementTypeEnum; import com.insgeek.platform.flow.enums.ResultCodeEnum; import com.insgeek.platform.flow.pojo.dto.ExtensionServiceTaskDto; import com.insgeek.platform.flow.pojo.dto.ProcessModelDto; import com.insgeek.platform.flow.pojo.model.ExtensionElementModel; import com.insgeek.platform.flow.rpc.EventClientService; import com.insgeek.platform.flow.service.ExtensionService; import com.insgeek.platform.flow.service.ProcessModelService; import com.insgeek.platform.flow.util.BusinessKeyUtil; import com.insgeek.platform.flow.util.SpringContextHolder; import com.insgeek.protocol.flow.dto.InteractBusinessRequestDto; /** * @author jiangliangyou * @date 2020-11-25 */ public class ServiceTaskImpl implements JavaDelegate { private EventClientService eventClientService = SpringContextHolder.getBean(EventClientService.class); private ExtensionService extensionService = SpringContextHolder.getBean(ExtensionService.class);; private ProcessModelService processModelService = SpringContextHolder.getBean(ProcessModelService.class); @Override public void execute(DelegateExecution execution) { // System.out.println("JavaDelegate : " + getClass().getSimpleName()); // Map map = MapBuilder.of("getId", execution.getId()) // .put("getProcessInstanceId", execution.getProcessInstanceId()) // .put("getProcessDefinitionId", execution.getProcessDefinitionId()) // .put("getVariableNames", String.join(",", execution.getVariableNames())) // .put("getCurrentActivityId", execution.getCurrentActivityId()) // .put("getEventName", execution.getEventName()) // .put("getParentId", execution.getParentId()) // .put("getProcessInstanceBusinessKey", execution.getProcessInstanceBusinessKey()) // .put("getRootProcessInstanceId", execution.getRootProcessInstanceId()) // .put("getSuperExecutionId", execution.getSuperExecutionId()) // .put("getSimpleName", execution.getClass().getSimpleName()).build(); // System.out.println(JacksonUtils.writeAsString(map)); ProcessModelDto processModelDto = processModelService.findEnableProcessModelByDefinition(execution.getProcessDefinitionId()); // 根据任务elementId和modelId查询额外扩展表获取事件列表,如果没有事件,直接返回 ExtensionElementModel queryParams = new ExtensionElementModel(); queryParams.setModelId(processModelDto.getId()); queryParams.setElementId(execution.getCurrentActivityId()); queryParams.setElementType(ElementTypeEnum.SERVICE_TASK.getValue()); List<ExtensionElementModel> eventModelList = extensionService.getExtensionElementModelListByQuery(queryParams); if (CollectionUtils.isEmpty(eventModelList)) return; // 事件不为空,判断事件的执行条件是否为空 List<Long> eventIds = eventModelList.stream() .map(ExtensionServiceTaskDto::of) .map(ExtensionServiceTaskDto::getTaskEventId) .filter(Objects::nonNull) .collect(Collectors.toList()); Map<String,Object> variablesMap = execution.getVariables(); InteractBusinessRequestDto interactBusinessRequestDto = new InteractBusinessRequestDto() .setCurrentTaskId(execution.getId()) .setDataId(BusinessKeyUtil.dataId(execution.getProcessInstanceBusinessKey())) .setEntityKey(processModelDto.getEntityKey()) .setApplicantId(Long.valueOf(String.valueOf(variablesMap.get(FlowConstants.APPLICANT_ID)))) .setDefinitionId(execution.getProcessDefinitionId()) .setVariables(variablesMap) .setCurrentUserId(IdentityContext.getUserId()); eventClientService.executeEventByEventIds(eventIds, ResultCodeEnum.AFTER_EVENT_EXECUTION_ERROR,interactBusinessRequestDto); } }