源码分析
根据flowable中文文档的说明可知processEngine流程引擎是通过org.flowable.spring.ProcessEngineFactoryBean
工厂类来创建的,因此先把目光聚集到这里
/**
* 这个方法即是生成流程引擎的方法
*/
public ProcessEngine getObject() throws Exception {
this.configureExternallyManagedTransactions();
if (this.processEngineConfiguration.getBeans() == null) {
this.processEngineConfiguration.setBeans(new SpringBeanFactoryProxyMap(this.applicationContext));
}
// 显然,引擎室通过配置类的buildProcessEngine方法来创建的
this.processEngine = this.processEngineConfiguration.buildProcessEngine();
return this.processEngine;
}
根据上述源码,我们可以把目光转向配置类信息,先来看看配置类的继承结构
从上图中可以看出蓝色主线标识了主要过程的继承逻辑,buildProcessEngine
经过AbstractEngineConfiguration
→ProcessEngineConfiguration
→ProcessEngineConfigurationImpl
→SpringProcessEngineConfiguration
;
通过查看3个类的buildProcessEngine
的实现,可知引擎对象是先由ProcessEngineConfigurationImpl
初始化后再教给SpringProcessEngineConfiguration
进行扩展。那就转到ProcessEngineConfigurationImpl
的源码中查看。
// 引擎构建的初次实现
public ProcessEngine buildProcessEngine() {
// 初始化工作
this.init();
// 根据当前的配置信息初始化引擎实现
ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
if (this.handleProcessEngineExecutorsAfterEngineCreate) {
processEngine.startExecutors();
}
if (this.flowable5CompatibilityEnabled && this.flowable5CompatibilityHandler != null) {
this.commandExecutor.execute(new Command<Void>() {
public Void execute(CommandContext commandContext) {
ProcessEngineConfigurationImpl.this.flowable5CompatibilityHandler.getRawProcessEngine();
return null;
}
});
}
this.postProcessEngineInitialisation();
return processEngine;
}
// init 方法太长,省略部分本次不考虑的因素
public void init() {
this.initEngineConfigurations();
this.initConfigurators();
...
if (this.usingRelationalDatabase) {
// 如果是关系型数据库,初始化数据源
this.initDataSource();
} else {
this.initNonRelationalDataSource();
}
...
}
如果仔细看过启动的异常堆栈就知道实际抛出异常的就是 this.initDataSource();
这个方法了,那就点进去看看。后续源码就不一个个放了,直接看根本造成问题的AbstractEngineConfiguration.initDatabaseType()
方法
// 初始化数据类型
public void initDatabaseType() {
Connection connection = null;
try {
connection = this.dataSource.getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
// 获取到数据库名,此处是根据相应驱动中配置来获取到的值,【KingbaseES】
String databaseProductName = databaseMetaData.getDatabaseProductName();
...
// 根据数据库名获取相应数据库类型
this.databaseType = this.databaseTypeMappings.getProperty(databaseProductName);
if (this.databaseType == null) {
throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'");
}
...
}
看到这里基本已经看到跟堆栈最终一致的异常错误了,很明显this.databaseTypeMappings.getProperty(databaseProductName);
是获取不到相应的数据库类型,因为databaseTypeMappings
是由getDefaultDatabaseTypeMappings()
这个静态方法构建的,所以我们的目标就是要重写这个静态方法,一种非常简单方法就是把AbstractEngineConfiguration
这个类再相同路径下覆盖一遍重写的时候加上,这也是网上比较多的做法。但我有另一种新的想法。
新的实现
首先先一个类来继承SpringProcessEngineConfiguration
保证他们再一个调用过程中
public class CustomEngineConfiguration extends SpringProcessEngineConfiguration {
/**
* 构造方法
* 由于AbstractEngineConfiguration没有提供特定的方法来对databaseTypeMappings属性进行操作,
* 因此就只能在构造方法中重新赋值
*/
public CustomEngineConfiguration(){
super();
super.databaseTypeMappings = extendDefaultDatabaseTypeMappings();
}
/**
* 扩展原有的getDefaultDatabaseTypeMappings,支持人大金仓
* @return
*/
public Properties extendDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();
databaseTypeMappings.setProperty("KingbaseES", DATABASE_TYPE_POSTGRES);
return databaseTypeMappings;
}
}
这里我们通过扩展getDefaultDatabaseTypeMappings()
方法,添加了kingbase的类型支持,并将它覆盖了父类中的databaseTypeMappings
属性。那么现在问题来了,怎么能让CustomEngineConfiguration
被加载呢,这时候就要把目光放到自动装配上面。查看flowable的自动装配配置文件
重点就上面圈中的自动配置类,我们可以看到在该配置类中创建了SpringProcessEngineConfiguration
并进行了配置,因此我们只要替换这个类并修改SpringProcessEngineConfiguration
的构建方法就可以搞定了
/**
* 继承ProcessEngineAutoConfiguration保证原有功能不变
*/
@Configuration
@Primary
public class CustomProcessEngineAutoConfiguration extends ProcessEngineAutoConfiguration {
public CustomProcessEngineAutoConfiguration(...) {
super(...);
}
/**
* 重写springProcessEngineConfiguration的类过程,其实整个过程都没有变
* 只是在构造SpringProcessEngineConfiguration方法的时候构造的是我们自定义的配置类,添加了关于人大金仓的支持
*/
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Bean
@Primary
@Override
public SpringProcessEngineConfiguration springProcessEngineConfiguration(...) throws IOException {
// 此处替换成构造自己定义的支持人大金仓的配置类
SpringProcessEngineConfiguration conf = new CustomEngineConfiguration();
...
}
只需要以上两个配置类即可解决人大金仓下使用flowable时的启动问题。
新的问题
解决上述问题后我尝试在空的人大金仓数据库中生成flowable相关的表结构,但是依然抛出了异常。