26. flowable 变量判断汇总

项目地址:https://gitee.com/lwj/flowable.git 分支flowable-base
视频地址:https://www.bilibili.com/video/av79774697/

1、判断变量是否相等
<![CDATA[${variables:get(myVar) == "00000001"}]]>

解释:传入字符串是否等于字符串00000001

2、判断传入的list变量是否相等
<![CDATA[${var:contains(myVar, 1, 2)}]]>

解释:传入list 判断是否相等

3、判断传入的list变量任意有一个值在其中返回true
<![CDATA[${var:containsAny(myVar, 1, 2)}]]> 

传入list 判断传入list的任意有一个在1,2中就返回true

4、判断传入的变量是否相等
<![CDATA[${var:eq(myVar, 123)}]]> 

判断的值等于123

5、判断传入的变量是否存在
<![CDATA[${var:exists('myVar')}]]> 

判断变量是否有这个值

6、判断传入的变量是否大于

如果判断是float类型的时候你需要把10变成10.00

<![CDATA[${var:gt('myVar', 10)}]]> 

判断值是否是大于10

7、判断传入的变量是否大于等于
<![CDATA[${var:gte('myVar', 10)}]]> 

判断值是否是大于等于10

8、判断传入的变量是否等于空串
<![CDATA[${variables:empty(myVar)}]]>

判断值是空串

9、判断传入的变量不是空串
<![CDATA[${var:isNotEmpty(myVar)}]]> 

判断值不是空串

9、判断传入的变量小于给定的值
<![CDATA[${var:lt('myVar', 10)}]]> 

判断值小于10

10、判断传入的变量小于等于给定的值
<![CDATA[${var:lte('myVar', 10)}]]> 

判断小于等于10

11、判断传入的变量不等于给定的值
<![CDATA[${variables:notEquals(myVar, "hello")}]]>

判断变量不等于hello

12、判断传入的变量是否大于给定的值,不大于取默认值然后与给定的值比较
<![CDATA[${vars:getOrDefault(myVar, 123) > 100}]]>

判断myVar是否大于123 大于则取myVar 否则取默认值 与100比较

13、判断传入的变量的base64编码是否相等
<![CDATA[${variables:base64(myVar) == "aGVsbG8="}]]> 

myVar的base64编码是否与aGVsbG8=相等

14、动态设置变量
${execution.setVariable('theUser', authenticatedUserId)}

设置一个变量为theUser 值为authenticatedUserId

15、动态执行变量的方法
${myVar.testMethod(execution)} 

变量myVar的testMethod方法执行的结果传入执行实例

16、截取字符串
${aString.substring(3,7)}

截取字符串

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngine': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1828) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1265) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ... 84 common frames omitted Caused by: java.lang.NullPointerException: null at org.flowable.engine.impl.db.ProcessDbSchemaManager.schemaUpdate(ProcessDbSchemaManager.java:232) at org.flowable.engine.impl.SchemaOperationsProcessEngineBuild.execute(SchemaOperationsProcessEngineBuild.java:54) at org.flowable.engine.impl.SchemaOperationsProcessEngineBuild.execute(SchemaOperationsProcessEngineBuild.java:28) at org.flowable.engine.impl.interceptor.CommandInvoker$1.run(CommandInvoker.java:67) at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:140) at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:114) at org.flowable.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:72) at org.flowable.engine.impl.interceptor.BpmnOverrideContextInterceptor.execute(BpmnOverrideContextInterceptor.java:26) at org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:53) at org.flowable.common.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:105) at org.flowable.common.spring.SpringTransactionInterceptor.lambda$execute$0(SpringTransactionInterceptor.java:57) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) at org.flowable.common.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:57) at org.flowable.common.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30) at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:56) at org.flowable.engine.impl.ProcessEngineImpl.<init>(ProcessEngineImpl.java:83) at org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl.buildProcessEngine(ProcessEngineConfigurationImpl.java:917) at org.flowable.spring.SpringProcessEngineConfiguration.buildProcessEngine(SpringProcessEngineConfiguration.java:76) at org.flowable.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:59) at org.flowable.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:32) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:169) ... 94 common frames omitted Disconnected from the target VM, address: '127.0.0.1:63966', transport: 'socket'
09-04
<think> 根据错误堆栈,问题发生在Flowable流程引擎初始化过程中,具体是在创建`processEngine` Bean时,执行数据库模式更新(`ProcessDbSchemaManager.schemaUpdate`)时抛出了空指针异常(NullPointerException)。这通常是由于数据库连接配置问题或Flowable配置不正确导致的。下面将提供详细的解决方案。 ### 问题分析 1. **堆栈关键点**: - `Caused by: java.lang.NullPointerException: null` - `at org.flowable.engine.impl.db.ProcessDbSchemaManager.schemaUpdate(ProcessDbSchemaManager.java:232)` 2. **可能原因**: - **数据库连接未正确配置**:Flowable无法获数据库连接。 - **数据库驱动缺失**:项目依赖中缺少数据库驱动。 - **Flowable配置错误**:如数据库类型、数据源Bean未注入等。 - **数据库表已存在或权限问题**:导致更新模式时出错。 ### 解决方案 #### 1. 检查数据源配置 确保在`application.properties`或`application.yml`中正确配置了数据库连接。 **示例配置(MySQL)**: ```properties # application.properties spring.datasource.url=jdbc:mysql://localhost:3306/flowable_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` #### 2. 添加数据库驱动依赖 在`pom.xml`中添加对应的数据库驱动依赖(以MySQL为例): ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> ``` #### 3. 配置Flowable数据源 如果使用了多数据源,确保Flowable使用的是正确的数据源Bean。在配置类中显式配置Flowable的数据源和事务管理器: ```java @Configuration public class FlowableConfig { @Bean public SpringProcessEngineConfiguration processEngineConfiguration( DataSource dataSource, PlatformTransactionManager transactionManager) { SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration(); config.setDataSource(dataSource); config.setTransactionManager(transactionManager); config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); config.setAsyncExecutorActivate(true); return config; } } ``` #### 4. 处理数据库模式更新策略 在Flowable配置中设置数据库模式更新策略为`true`(如果数据库不存在表则自动创建): ```java config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); ``` #### 5. 检查数据库连接可用性 添加一个简单的数据库连接测试Bean,在应用启动时测试数据库连接: ```java @Bean public CommandLineRunner testConnection(DataSource dataSource) { return args -> { try (Connection conn = dataSource.getConnection()) { System.out.println("✅ 数据库连接成功: " + conn.getMetaData().getURL()); } catch (SQLException e) { System.err.println("❌ 数据库连接失败: " + e.getMessage()); throw e; } }; } ``` #### 6. 处理Flowable依赖冲突 如果项目中存在多个版本的Flowable依赖,可能导致类加载问题。使用Maven依赖树检查冲突: ```bash mvn dependency:tree -Dincludes=org.flowable ``` 排除冲突依赖示例: ```xml <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>6.7.2</version> <exclusions> <exclusion> <groupId>org.flowable</groupId> <artifactId>flowable-common-engine</artifactId> </exclusion> </exclusions> </dependency> ``` #### 7. 完整的Flowable配置修复方案 ```java @Configuration public class FlowableEngineConfig { @Autowired private DataSource dataSource; @Autowired private PlatformTransactionManager transactionManager; @Bean public ProcessEngineFactoryBean processEngine() { ProcessEngineFactoryBean factoryBean = new ProcessEngineFactoryBean(); factoryBean.setProcessEngineConfiguration(processEngineConfiguration()); return factoryBean; } @Bean public ProcessEngineConfiguration processEngineConfiguration() { SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration(); config.setDataSource(dataSource); config.setTransactionManager(transactionManager); config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); config.setJobExecutorActivate(true); config.setMailServerPort(1025); config.setMailServerHost("localhost"); return config; } @Bean public RepositoryService repositoryService(ProcessEngine processEngine) { return processEngine.getRepositoryService(); } // 其他服务Bean... } ``` ### 错误诊断增强 添加自定义的Flowable启动监听器,捕获初始化阶段的详细错误: ```java import org.flowable.common.engine.api.delegate.event.FlowableEvent; import org.flowable.common.engine.api.delegate.event.FlowableEventListener; import org.flowable.engine.delegate.event.impl.FlowableProcessEngineEventImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FlowableEventConfig { @Bean public FlowableEventListener engineInitializationListener() { return new FlowableEventListener() { @Override public void onEvent(FlowableEvent event) { if (event instanceof FlowableProcessEngineEventImpl) { FlowableProcessEngineEventImpl engineEvent = (FlowableProcessEngineEventImpl) event; if (engineEvent.getType().name().contains("ENGINE_CREATED")) { System.out.println("✅ Flowable引擎初始化成功"); } } } @Override public boolean isFailOnException() { return false; } }; } } ``` ### 数据库权限检查 确保数据库用户有创建表和执行DDL语句的权限: ```sql -- 创建用户并授权 CREATE USER 'flowable'@'%' IDENTIFIED BY 'SecurePass123!'; GRANT ALL PRIVILEGES ON flowable_db.* TO 'flowable'@'%'; FLUSH PRIVILEGES; ``` ### 总结 通过以上步骤,应该能够解决Flowable引擎初始化时的空指针异常。关键在于确保数据库连接正确、依赖完整、配置无误。 --- §§相关问题§§: 1. 如何配置Flowable在Spring Boot中使用多数据源? 2. Flowable引擎初始化过程中可能出现的其他常见异常有哪些? 3. 如何实现Flowable数据库模式的手动更新? 4. 在微服务架构中如何共享Flowable引擎配置? </think> ### 解决 Flowable 流程引擎初始化时的 NullPointerException 问题 根据错误堆栈,问题发生在 Flowable 流程引擎初始化过程中,具体是在数据库模式更新阶段(`ProcessDbSchemaManager.schemaUpdate`)抛出了空指针异常。以下是完整的解决方案: #### 1. 配置数据源和事务管理器 ```java @Configuration public class FlowableDataSourceConfig { @Bean(name = "flowableDataSource") @ConfigurationProperties(prefix = "spring.datasource.flowable") public DataSource flowableDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "flowableTransactionManager") public PlatformTransactionManager flowableTransactionManager( @Qualifier("flowableDataSource") DataSource dataSource ) { return new DataSourceTransactionManager(dataSource); } } ``` #### 2. Flowable 引擎配置修复 ```java @Configuration @EnableTransactionManagement public class FlowableEngineConfig { @Autowired @Qualifier("flowableDataSource") private DataSource dataSource; @Autowired @Qualifier("flowableTransactionManager") private PlatformTransactionManager transactionManager; @Bean public SpringProcessEngineConfiguration processEngineConfiguration() { SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration(); // 核心配置 config.setDataSource(dataSource); config.setTransactionManager(transactionManager); config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); config.setAsyncExecutorActivate(true); // 解决空指针的关键配置 config.setDatabaseType("mysql"); // 明确指定数据库类型 config.setJdbcDriver("com.mysql.cj.jdbc.Driver"); config.setJdbcUrl(dataSource.getConnection().getMetaData().getURL()); // 启用历史记录 config.setHistory(HistoryLevel.FULL.getKey()); // 添加自定义类型解析器(解决NPE问题) config.setCustomMybatisTypeHandlers( Collections.singletonList(new CustomFlowableTypeHandler()) ); return config; } @Bean public ProcessEngineFactoryBean processEngine( SpringProcessEngineConfiguration config ) { ProcessEngineFactoryBean factory = new ProcessEngineFactoryBean(); factory.setProcessEngineConfiguration(config); return factory; } public static class CustomFlowableTypeHandler extends BaseTypeHandler<Object> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { // 处理空值 if (parameter == null) { ps.setNull(i, Types.OTHER); } else { ps.setObject(i, parameter); } } // 其他必要方法实现... } } ``` #### 3. 数据库连接诊断工具 ```java @Component public class FlowableDbDiagnoser implements InitializingBean { @Autowired private DataSource dataSource; @Override public void afterPropertiesSet() throws Exception { try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) { // 检查核心表是否存在 checkTableExists(stmt, "ACT_GE_PROPERTY"); checkTableExists(stmt, "ACT_RE_PROCDEF"); // 检查表结构版本 String schemaVersion = getSchemaVersion(stmt); System.out.println("Flowable 数据库版本: " + schemaVersion); // 验证DDL执行权限 testDdlPermission(stmt); } catch (SQLException ex) { throw new FlowableDbException("数据库连接验证失败", ex); } } private void checkTableExists(Statement stmt, String tableName) throws SQLException { try { stmt.executeQuery("SELECT 1 FROM " + tableName + " LIMIT 1"); System.out.println("✅ 表存在: " + tableName); } catch (SQLException e) { System.err.println("❌ 表缺失: " + tableName); throw e; } } private String getSchemaVersion(Statement stmt) throws SQLException { try (ResultSet rs = stmt.executeQuery( "SELECT VALUE_ FROM ACT_GE_PROPERTY WHERE NAME_ = 'schema.version'")) { if (rs.next()) return rs.getString(1); } return "unknown"; } private void testDdlPermission(Statement stmt) throws SQLException { try { stmt.execute("CREATE TABLE __flowable_test_permission (id INT)"); stmt.execute("DROP TABLE __flowable_test_permission"); System.out.println("✅ 数据库DDL权限验证通过"); } catch (SQLException e) { System.err.println("❌ 缺少数据库DDL权限: " + e.getMessage()); throw e; } } public static class FlowableDbException extends RuntimeException { public FlowableDbException(String message, Throwable cause) { super(message, cause); } } } ``` #### 4. Flowable 启动监听器(捕获初始化错误) ```java @Configuration public class FlowableLifecycleConfig { @Bean public ApplicationListener<ApplicationReadyEvent> flowableStartupListener() { return event -> { try { ProcessEngine engine = event.getApplicationContext() .getBean(ProcessEngine.class); System.out.println("✅ Flowable 引擎启动成功"); System.out.println("引擎名称: " + engine.getName()); System.out.println("版本: " + ProcessEngine.VERSION); } catch (Exception ex) { System.err.println("❌ Flowable 引擎启动失败"); analyzeStartupFailure(ex); throw ex; } }; } private void analyzeStartupFailure(Throwable ex) { Throwable cause = ex; while (cause != null) { if (cause instanceof NullPointerException) { System.err.println("空指针异常位置: " + getNpeLocation(cause)); System.err.println("可能原因: " + suggestNpeSolutions(cause)); } if (cause instanceof SQLException) { SQLException sqlEx = (SQLException) cause; System.err.println("SQL错误: [Code=" + sqlEx.getErrorCode() + "] " + sqlEx.getMessage()); } cause = cause.getCause(); } } private String getNpeLocation(Throwable npe) { return Arrays.stream(npe.getStackTrace()) .filter(frame -> frame.getClassName().contains("flowable")) .findFirst() .map(frame -> frame.getClassName() + "." + frame.getMethodName() + ":" + frame.getLineNumber()) .orElse("未知位置"); } private String suggestNpeSolutions(Throwable npe) { if (npe.getMessage() != null && npe.getMessage().contains("dbSchemaManager")) { return "数据库连接配置错误或缺少权限"; } return "检查数据源注入和数据库驱动"; } } ``` #### 5. 数据库修复脚本 ```sql -- 确保ACT_GE_PROPERTY表存在 CREATE TABLE IF NOT EXISTS ACT_GE_PROPERTY ( NAME_ VARCHAR(64) NOT NULL, VALUE_ VARCHAR(300), REV_ INT, PRIMARY KEY (NAME_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 初始化必要属性 INSERT IGNORE INTO ACT_GE_PROPERTY (NAME_, VALUE_, REV_) VALUES ('schema.version', '6.7.2', 1), ('schema.history', 'create(6.7.2)', 1), ('next.dbid', '10001', 1); -- 授予Flowable所需权限 GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON flowable_db.* TO 'flowable_user'@'%'; ``` #### 6. 配置验证端点 ```java @RestController @RequestMapping("/actuator/flowable") public class FlowableHealthEndpoint { @Autowired(required = false) private ProcessEngine processEngine; @GetMapping("/health") public ResponseEntity<Map<String, Object>> health() { Map<String, Object> healthInfo = new LinkedHashMap<>(); if (processEngine != null) { healthInfo.put("status", "UP"); healthInfo.put("engineName", processEngine.getName()); healthInfo.put("version", ProcessEngine.VERSION); try { long procDefCount = processEngine.getRepositoryService() .createProcessDefinitionQuery() .count(); healthInfo.put("processDefinitions", procDefCount); } catch (Exception e) { healthInfo.put("repositoryError", e.getMessage()); } } else { healthInfo.put("status", "DOWN"); healthInfo.put("error", "ProcessEngine not initialized"); } return processEngine != null ? ResponseEntity.ok(healthInfo) : ResponseEntity.status(503).body(healthInfo); } } ``` ### 问题根本原因分析 1. **数据库连接问题**(最常见原因): - 数据源未正确注入到 Flowable 配置中 - 数据库驱动缺失或版本不兼容 - 数据库用户缺少必要的 DDL 权限 2. **Flowable 内部配置问题**: - 未正确设置数据库类型(如 MySQL、PostgreSQL) - 数据库模式更新策略配置错误 - 缺少必要的数据库表(如 ACT_GE_PROPERTY) 3. **依赖冲突**: - 多个 Flowable 版本冲突 - MyBatis 版本与 Flowable 不兼容 ### 验证修复步骤 1. **检查依赖树**: ```bash mvn dependency:tree -Dincludes=org.flowable,org.mybatis ``` 2. **启动诊断模式**: ```bash java -jar your-app.jar --debug-flowable-db ``` 3. **访问健康检查端点**: ``` GET /actuator/flowable/health ``` 4. **验证数据库表**: ```sql SHOW TABLES LIKE 'ACT_%'; SELECT * FROM ACT_GE_PROPERTY; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小学生05101

flowable

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值