一、项目场景:
提示:使用版本6.7.0
公司使用前后端项目分离,前端使用bpmn插件生成bpmn xml文件,后端解析处理数据。今天主要介绍后端集成flowable设计器的过程中遇到的问题。
如需了解flowable框架集成请参考文档
Flowable BPMN 用户手册 (v 6.3.0)
二、集成过程
提示:项目中遇到的问题:
为什么需要自己集成Flowable设计器?因为SpringBoot提供的依赖只集成Flowable引擎模块,没有集成modeler模块。SpringBoot集成Flowable需要导入如下依赖:
<!-- flowable --><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter-process</artifactId><version>${flowable.version}</version></dependency>
可以看到没有集成和modeler相关的依赖,如下是flowable源码中提供的流程设计器模块:
flowable-ui-modeler-conf: 放置一些列的配置项
flowable-ui-modeler-frontend: 前端
flowable-ui-modeler-logic: 放置Service以及dao层
flowable-ui-modeler-rest: 放置Controller层
因为只需要集成flowable操作model 接口相关组件,所以只需要集成logic模块即可,添加依赖如下:
<!-- 配置ui集成 --><dependency><groupId>org.flowable</groupId><artifactId>flowable-ui-modeler-logic</artifactId><version>${flowable.version}</version></dependency>
三、问题总结:
提示:这里填写问题的分析:
1、程序启动报错(flowable.common.app.idm-url must be set)
`Failedtoinstantiate[org.flowable.ui.common.service.idm.RemoteIdmService]:Factory method 'remoteIdmService' threw exception; nested exception is java.lang.IllegalArgumentException: `flowable.common.app.idm-url` must be set`
这个是由于flowable调用自己的用户权限导致的,如果把flowable集成自己的框架里面,就不需要用它自带的用户体现和权限了。
解决方案:将FlowableUiSecurityAutoConfiguration排除
@SpringBootApplication(exclude ={FlowableUiSecurityAutoConfiguration.class})
2、引入modelService报红,运行报错
Field modelService in com.nmb.zx.base.sys.flow.service.FlowModelInfoService required a bean of type 'org.flowable.ui.modeler.serviceapi.ModelService' that could not be found.
解决方案:参考flowable flowable-ui-modeler-conf组件中的源码中的配置类扫描我们需要的注入的类所在的包即可:
添加ModelerBeanConfig.java配置类到项目任意位置:
importorg.flowable.ui.common.properties.FlowableCommonAppProperties;importorg.flowable.ui.modeler.repository.ModelRepositoryImpl;importorg.flowable.ui.modeler.service.FlowableModelQueryService;importorg.flowable.ui.modeler.service.ModelImageService;importorg.flowable.ui.modeler.service.ModelServiceImpl;importorg.flowable.ui.modeler.serviceapi.ModelService;importorg.springframework.boot.context.properties.EnableConfigurationProperties;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.FilterType;/**
* Greated by xiang on 2023/2/27
*/@Configuration@ComponentScan(value ={// "org.flowable.ui.modeler.conf", //不引入 conf"org.flowable.ui.modeler.repository","org.flowable.ui.modeler.service",// "org.flowable.ui.modeler.security",//授权方面的都不需要// "org.flowable.ui.common.conf", // flowable 开发环境内置的数据库连接// "org.flowable.ui.common.filter",// IDM 方面的过滤器// "org.flowable.ui.common.service","org.flowable.ui.common.repository",// "org.flowable.ui.common.security",//授权方面的都不需要// "org.flowable.ui.common.tenant"}, excludeFilters ={@ComponentScan.Filter(type =FilterType.ASSIGNABLE_TYPE, value =ModelRepositoryImpl.class)})@EnableConfigurationProperties({FlowableCommonAppProperties.class})publicclassModelerBeanConfig{@BeanpublicModelServicecreateModelService(){returnnewModelServiceImpl();}@BeanpublicModelImageServicecreateModelImageService(){returnnewModelImageService();}@BeanpublicFlowableModelQueryServicecreateFlowableModelQueryService(){returnnewFlowableModelQueryService();}}
mybatisPlus中添加配置
添加BPMN配置文件FlowBpmnConfig
importcom.fasterxml.jackson.databind.ObjectMapper;importcom.nmb.zx.base.core.config.flow.customcache.CustomDeploymentCache;importcom.nmb.zx.base.core.config.flow.customcache.CustomProcessDefinitionInfoCache;importorg.apache.ibatis.session.SqlSessionFactory;importorg.flowable.bpmn.converter.BpmnXMLConverter;importorg.flowable.spring.SpringProcessEngineConfiguration;importorg.flowable.spring.boot.EngineConfigurationConfigurer;importorg.flowable.validation.ProcessValidatorFactory;importorg.mybatis.spring.SqlSessionTemplate;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.support.PropertySourcesPlaceholderConfigurer;/**
* 功能描述: <br>
* 〈flowable配置〉
* @Author: 85122
* @Date: 2023/2/28 15:16
*/@ConfigurationpublicclassFlowBpmnConfigimplementsEngineConfigurationConfigurer<SpringProcessEngineConfiguration>{@AutowiredprivateCustomDeploymentCache customDeploymentCache;@AutowiredprivateCustomProcessDefinitionInfoCache customProcessDefinitionInfoCache;@Overridepublicvoidconfigure(SpringProcessEngineConfiguration configuration){
configuration.setEnableProcessDefinitionInfoCache(true);
configuration.setProcessDefinitionCache(customDeploymentCache);
configuration.setProcessDefinitionInfoCache(customProcessDefinitionInfoCache);//设置自定义的uuid生成策略
configuration.setIdGenerator(uuidGenerator());}@BeanpublicProcessValidatorFactoryprocessValidator(){returnnewProcessValidatorFactory();}@BeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}@BeanpublicUuidGeneratoruuidGenerator(){returnnewUuidGenerator();}/**
* BpmnXMLConverter
*
* @return BpmnXMLConverter
*/@BeanpublicBpmnXMLConvertercreateBpmnXMLConverter(){returnnewBpmnXMLConverter();}/**
* 在配置文件中如果没有字段,使用@Value的时候就会忽略掉,不会报错
*
* @return
*/@BeanpublicstaticPropertySourcesPlaceholderConfigurerplaceholderConfigurer(){PropertySourcesPlaceholderConfigurer configurer =newPropertySourcesPlaceholderConfigurer();
configurer.setIgnoreUnresolvablePlaceholders(true);return configurer;}@Bean(destroyMethod ="clearCache")@Qualifier("flowableModeler")publicSqlSessionTemplatemodelerSqlSessionTemplate(SqlSessionFactory sqlSessionFactory){returnnewSqlSessionTemplate(sqlSessionFactory);}}
importorg.flowable.common.engine.impl.persistence.StrongUuidGenerator;/**
* 功能描述: <br>
* 〈uuid生成规则〉
* @Author: 85122
* @Date: 2023/2/28 15:16
*/publicclassUuidGeneratorextendsStrongUuidGenerator{@OverridepublicStringgetNextId(){String uuid =super.getNextId();
uuid = uuid.replaceAll("-","");return uuid;}}
importorg.flowable.common.engine.impl.persistence.deploy.DeploymentCache;importorg.flowable.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry;importorg.flowable.engine.repository.ProcessDefinition;importorg.springframework.stereotype.Component;importjava.util.ArrayList;importjava.util.Collection;importjava.util.Collections;/**
* Very simplistic cache implementation that only caches one process definition.
*
* @author Joram Barrez
*/@ComponentpublicclassCustomDeploymentCacheimplementsDeploymentCache<ProcessDefinitionCacheEntry>{protectedString id;protectedProcessDefinitionCacheEntry entry;@OverridepublicProcessDefinitionCacheEntryget(String id){if(id.equals(this.id)){return entry;}returnnull;}@Overridepublicvoidadd(String id,ProcessDefinitionCacheEntry object){this.id = id;this.entry = object;}@Overridepublicvoidremove(String id){if(id.equals(this.id)){this.id =null;this.entry =null;}}@Overridepublicvoidclear(){this.id =null;this.entry =null;}@Overridepublicbooleancontains(String id){return id.equals(this.id);}@OverridepublicCollection<ProcessDefinitionCacheEntry>getAll(){if(entry !=null){returnCollections.singletonList(entry);}else{returnnewArrayList<>();}}@Overridepublicintsize(){if(entry !=null){return1;}else{return0;}}// For testing purposes onlypublicProcessDefinitiongetCachedProcessDefinition(){if(entry ==null){returnnull;}return entry.getProcessDefinition();}}
importorg.flowable.common.engine.impl.persistence.deploy.DeploymentCache;importorg.flowable.engine.impl.persistence.deploy.ProcessDefinitionInfoCacheObject;importorg.springframework.stereotype.Component;importjava.util.Collection;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;@ComponentpublicclassCustomProcessDefinitionInfoCacheimplementsDeploymentCache<ProcessDefinitionInfoCacheObject>{privatefinalMap<String,ProcessDefinitionInfoCacheObject> cache =newConcurrentHashMap<>();@OverridepublicProcessDefinitionInfoCacheObjectget(String id){return cache.get(id);}@Overridepublicbooleancontains(String id){return cache.containsKey(id);}@Overridepublicvoidadd(String id,ProcessDefinitionInfoCacheObject object){
cache.put(id, object);}@Overridepublicvoidremove(String id){
cache.remove(id);}@Overridepublicvoidclear(){
cache.clear();}@OverridepublicCollection<ProcessDefinitionInfoCacheObject>getAll(){return cache.values();}@Overridepublicintsize(){return cache.size();}}
3、启动后访问接口直接重定向到登录页面
importorg.flowable.ui.common.security.SecurityConstants;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.annotation.Order;importorg.springframework.security.config.annotation.web.builders.HttpSecurity;importorg.springframework.security.config.annotation.web.configuration.EnableWebSecurity;importorg.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;importorg.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;/**
* 说明:重构ModelerSecurity 绕过登录
*/@Configuration(proxyBeanMethods =false)@EnableWebSecuritypublicclassModelerSecurityConfiguration{@Configuration@Order(SecurityConstants.MODELER_API_SECURITY_ORDER)publicstaticclassModelerApiWebSecurityConfigurationAdapterextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{SavedRequestAwareAuthenticationSuccessHandler successHandler =newSavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
http.headers().frameOptions().disable();
http.csrf().disable().authorizeRequests().antMatchers("/**/**").permitAll().anyRequest().authenticated().and().httpBasic();}}}
4、运行成功请求接口
找不到act_de_model表,因为flowable将act_re_model改成了act_de_model表了,所以需要手动添加配置类生产act_de_model表:
importliquibase.Liquibase;importliquibase.database.Database;importliquibase.database.DatabaseConnection;importliquibase.database.DatabaseFactory;importliquibase.database.jvm.JdbcConnection;importliquibase.exception.DatabaseException;importliquibase.resource.ClassLoaderResourceAccessor;importorg.flowable.ui.common.service.exception.InternalServerErrorException;importorg.slf4j.LoggerFactory;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjavax.sql.DataSource;/**
* 功能描述: <br>
* 〈生成ACT_DE_开头的数据表〉
* @Param: * @param null
* @Return:
* @Author: 85122
* @Date: 2023/2/28 15:00
*/@ConfigurationpublicclassDatabaseConfiguration{privatestaticfinalorg.slf4j.LoggerLOGGER=LoggerFactory.getLogger(DatabaseConfiguration.class);protectedstaticfinalStringLIQUIBASE_CHANGELOG_PREFIX="ACT_DE_";@BeanpublicLiquibaseliquibase(DataSource dataSource){LOGGER.info("Configuring Liquibase");Liquibase liquibase =null;try{DatabaseConnection connection =newJdbcConnection(dataSource.getConnection());Database database =DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);
database.setDatabaseChangeLogTableName(LIQUIBASE_CHANGELOG_PREFIX+ database.getDatabaseChangeLogTableName());
database.setDatabaseChangeLogLockTableName(LIQUIBASE_CHANGELOG_PREFIX+ database.getDatabaseChangeLogLockTableName());
liquibase =newLiquibase("META-INF/liquibase/flowable-modeler-app-db-changelog.xml",newClassLoaderResourceAccessor(), database);
liquibase.update("flowable");return liquibase;}catch(Exception e){thrownewInternalServerErrorException("Error creating liquibase database", e);}finally{closeDatabase(liquibase);}}privatevoidcloseDatabase(Liquibase liquibase){if(liquibase !=null){Database database = liquibase.getDatabase();if(database !=null){try{
database.close();}catch(DatabaseException e){LOGGER.warn("Error closing database", e);}}}}}
版权归原作者 我的瓦洛佳 所有, 如有侵权,请联系我们删除。