apache / apache/incubator-seata
SpringMVC 动态数据源时整合Seata 同样的配置在SpringBoot 工程中是没有问题的 只有在SpringMVC 工程报这个错 配置及注册中心是nacos
- Dominant language
- Java
- Stars
- 26k
- Forks
- 8.8k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 4
Description
SpringMVC 动态数据源时整合Seata 同样的配置在SpringBoot 工程中是没有问题的 只有在SpringMVC 工程报这个错
报错 Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NullPointerException [in thread "http-nio-8080-exec-6"]
Caused by: java.lang.NoClassDefFoundError: Could not initialize class io.seata.config.ConfigurationFactory
Caused by: io.seata.common.loader.EnhancedServiceNotFoundException: java.lang.IllegalStateException: Extension instance(definition: io.seata.common.loader.ExtensionDefinition@e9dd843a, class: interface io.seata.core.model.ResourceManager) could not be instantiated: Could not initialize class io.seata.config.ConfigurationFactory
Caused by: java.lang.IllegalStateException: Extension instance(definition: io.seata.common.loader.ExtensionDefinition@e9dd843a, class: interface io.seata.core.model.ResourceManager) could not be instantiated: Could not initialize class io.seata.config.ConfigurationFactory
引入依赖
io.seata
seata-spring-boot-starter
1.7.0
配置文件
#====================================Seata Config===============================================
seata.data-source-proxy-mode=AT
seata.enabled=true
seata.application-id=vjifen-interfance
seata.tx-service-group=default_tx_group
seata.client.rm-report-success-enable=true
seata.client.rm-table-meta-check-enable=false
seata.client.rm-report-retry-count=5
seata.client.rm-async-commit-buffer-limit=10000
seata.client.rm.lock.lock-retry-internal=10
seata.client.rm.lock.lock-retry-times=30
seata.client.rm.lock.lock-retry-policy-branch-rollback-on-conflict=true
seata.client.tm-commit-retry-count=3
seata.client.tm-rollback-retry-count=3
seata.client.undo.undo-data-validation=true
seata.client.undo.undo-log-serialization=jackson
seata.client.undo.undo-log-table=undo_log
seata.client.log.exceptionRate=100
seata.client.support.spring.datasource-autoproxy=true
seata.service.vgroup-mapping.default_tx_group=default
seata.service.enable-degrade=false
seata.service.disable-global-transaction=false
seata.service.grouplist.seata-server=127.0.0.1:8091
seata.transport.shutdown.wait=3
seata.transport.thread-factory.boss-thread-prefix=NettyBoss
seata.transport.thread-factory.worker-thread-prefix=NettyServerNIOWorker
seata.transport.thread-factory.server-executor-thread-prefix=NettyServerBizHandler
seata.transport.thread-factory.share-boss-worker=false
seata.transport.thread-factory.client-selector-thread-prefix=NettyClientSelector
seata.transport.thread-factory.client-selector-thread-size=1
seata.transport.thread-factory.client-worker-thread-prefix=NettyClientWorkerThread
seata.transport.type=TCP
seata.transport.server=NIO
seata.transport.heartbeat=true
seata.transport.serialization=seata
seata.transport.compressor=none
seata.transport.enable-client-batch-send-request=true
seata.registry.application=seata-server
seata.registry.type=nacos
seata.registry.nacos.server-addr=127.0.0.1:8848
seata.registry.nacos.group=SEATA_GROUP
seata.registry.nacos.cluster=default
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
seata.config.type=nacos
seata.config.nacos.group=SEATA_GROUP
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.data-id=seata-server.properties
数据源代码
package com.dbt.datasource.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.dbt.framework.datadic.bean.ServerInfo;
import com.dbt.framework.util.CacheUtil;
import com.dbt.framework.util.RedisApiUtil;
public class DynamicDataSource extends AbstractRoutingDataSource{
private Logger log = Logger.getLogger(this.getClass());
private Map _targetDataSources;
private static final String driverClassName="com.mysql.jdbc.Driver";
private static final String defaultDataSourceName="dataSource";
private static final String XA_driverClassName = "com.alibaba.druid.pool.xa.DruidXADataSource";
/**
* @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
* @describe 数据源为空或者为0时,自动切换至默认数据源,即在配置文件中定义的dataSource数据源
*/
@Override
protected Object determineCurrentLookupKey() {
String dataSourceName = DbContextHolder.getDBType();
// log.warn("changeDataSource:"+dataSourceName);
if (StringUtils.isBlank(dataSourceName)) {
dataSourceName = defaultDataSourceName;
} else {
// 动态更新数据源
String key = CacheUtil.cacheKey.KEY_UPDATE_PROJECT_SERVER_INFO_LIST;
if(RedisApiUtil.getInstance().containsInSet(false, key, dataSourceName)){
if(null != _targetDataSources.get(dataSourceName)){
_targetDataSources.remove(dataSourceName);
RedisApiUtil.getInstance().removeSetValue(false, key, dataSourceName);
}
}
this.selectDataSource(dataSourceName);
}
// log.warn("--------> use datasource " + dataSourceName);
return dataSourceName;
}
/**
* 到数据库中查找名称为dataSourceName的数据源
*
* @param dataSourceName
*/
private void selectDataSource(String dataSourceName) {
Object sid = DbContextHolder.getDBType();
if (StringUtils.isEmpty(dataSourceName)
|| dataSourceName.trim().equals("dataSource")) {
DbContextHolder.setDBType("dataSource");
return;
}
Object obj = this._targetDataSources.get(dataSourceName);
if (obj != null && sid.equals(dataSourceName)) {
return;
} else {
DataSource dataSource = this.getDataSource(dataSourceName);
if (null != dataSource) {
this.setDataSource(dataSourceName, dataSource);
}
}
}
@Override
public void setTargetDataSources(Map targetDataSources) {
this._targetDataSources = targetDataSources;
super.setTargetDataSources(this._targetDataSources);
afterPropertiesSet();
}
private void addTargetDataSource(String key, DataSource dataSource) {
this._targetDataSources.put(key, dataSource);
this.setTargetDataSources(this._targetDataSources);
}
private DataSource createDataSource(ServerInfo serverInfo) {
//BasicDataSource dataSource = new BasicDataSource();
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(serverInfo.getServerJdbc()+"&useSSL=false");
dataSource.setUsername(serverInfo.getServerU());
dataSource.setPassword(serverInfo.getServerP());
dataSource.setInitialSize(3);
dataSource.setMinIdle(3);
dataSource.setMaxActive(serverInfo.getServerC());
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("select 1");
List connectionInitSqls = new ArrayList();
connectionInitSqls.add("set names utf8mb4;");// emoji表情
dataSource.setConnectionInitSqls(connectionInitSqls);
// 添加Seata 事务代理 new DataSourceProxy(dataSource)
return new DataSourceProxy(dataSource);
}
@SuppressWarnings("unchecked")
private DataSource getDataSource(String dataSourceName) {
ServerInfo serverInfo = ((Map) RedisApiUtil.getInstance()
.getObject(false, CacheUtil.cacheKey.KEY_PROJECT_SERVER_INFO)).get(dataSourceName);
if(serverInfo!=null) {
DataSource dataSource = this.createDataSource(serverInfo);
return dataSource;
}
return null;
}
/**
* 将已存在的数据源存储到内存中
*
* @param dataSourceName
* @param dataSource
*/
private void setDataSource(String dataSourceName, DataSource dataSource) {
this.addTargetDataSource(dataSourceName, dataSource);
DbContextHolder.setDBType(dataSourceName);
}
}
Contributor guide
Research direction
The payload names no repository file or test. Start by reproducing the SpringMVC failure with seata-spring-boot-starter 1.7.0, then compare its configuration and initialization path with the working Spring Boot setup, focusing on ConfigurationFactory and the dynamic DataSourceProxy. Done means the cause is isolated and a verifiable correction or minimal reproduction is identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, mysql, spring, spring-boot
- Domain
- backend, databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100