This is an automated email from the ASF dual-hosted git repository. jianbin pushed a commit to branch 2.x in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push: new 152a7f9489 bugfix: the drivers in the lib folder cannot be loaded (#7354) 152a7f9489 is described below commit 152a7f948953ed7245b426fa75d599391861c570 Author: funkye <jian...@apache.org> AuthorDate: Thu May 22 13:40:15 2025 +0800 bugfix: the drivers in the lib folder cannot be loaded (#7354) --- changes/en-us/2.x.md | 1 + changes/zh-cn/2.x.md | 1 + .../core/store/db/AbstractDataSourceProvider.java | 112 +++++++++++---------- .../seata/server/store/DbcpDataSourceProvider.java | 2 +- .../server/store/DruidDataSourceProvider.java | 2 +- .../store/db/AbstractDataSourceProviderTest.java | 63 ++++++++++++ 6 files changed, 125 insertions(+), 56 deletions(-) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index ff01591bfc..cf0360be89 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -26,6 +26,7 @@ Add changes here for all PR submitted to the 2.x branch. ### bugfix: - [[#7349](https://github.com/apache/incubator-seata/pull/7349)] Resolve NullPointerException in EtcdRegistryServiceImplMockTest +- [[#7354](https://github.com/apache/incubator-seata/pull/7354)] fix the drivers in the libs folder cannot be loaded - [[#7356](https://github.com/apache/incubator-seata/pull/7356)] fix codecov bug diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index e9fe80130f..2cafefb523 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -27,6 +27,7 @@ ### bugfix: - [[#7349](https://github.com/apache/incubator-seata/pull/7349)] 解决 EtcdRegistryServiceImplMockTest 中的空指针异常 +- [[#7354](https://github.com/apache/incubator-seata/pull/7354)] 修复lib文件夹中的驱动程序无法加载 ### optimize: diff --git a/core/src/main/java/org/apache/seata/core/store/db/AbstractDataSourceProvider.java b/core/src/main/java/org/apache/seata/core/store/db/AbstractDataSourceProvider.java index 860d9dc953..f24e4a3992 100644 --- a/core/src/main/java/org/apache/seata/core/store/db/AbstractDataSourceProvider.java +++ b/core/src/main/java/org/apache/seata/core/store/db/AbstractDataSourceProvider.java @@ -16,6 +16,9 @@ */ package org.apache.seata.core.store.db; +import static org.apache.seata.common.DefaultValues.DEFAULT_DB_MAX_CONN; +import static org.apache.seata.common.DefaultValues.DEFAULT_DB_MIN_CONN; + import java.io.File; import java.net.MalformedURLException; import java.net.URL; @@ -24,9 +27,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.stream.Stream; - import javax.sql.DataSource; - import org.apache.seata.common.exception.ShouldNeverHappenException; import org.apache.seata.common.exception.StoreException; import org.apache.seata.common.executor.Initialize; @@ -39,12 +40,9 @@ import org.apache.seata.core.constants.DBType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.apache.seata.common.DefaultValues.DEFAULT_DB_MAX_CONN; -import static org.apache.seata.common.DefaultValues.DEFAULT_DB_MIN_CONN; - /** * The abstract datasource provider - * + * */ public abstract class AbstractDataSourceProvider implements DataSourceProvider, Initialize { @@ -57,18 +55,18 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, */ protected static final Configuration CONFIG = ConfigurationFactory.getInstance(); - private final static String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; + private static final String MYSQL_DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; - private final static String MYSQL8_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver"; + private static final String MYSQL8_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver"; - private final static String MYSQL_DRIVER_FILE_PREFIX = "mysql-connector-j"; + private static final String MYSQL_DRIVER_FILE_PREFIX = "mysql-connector-j"; - private final static Map<String, ClassLoader> MYSQL_DRIVER_LOADERS; + private static final Map<String, ClassLoader> DRIVER_LOADERS; private static final long DEFAULT_DB_MAX_WAIT = 5000; static { - MYSQL_DRIVER_LOADERS = createMysqlDriverClassLoaders(); + DRIVER_LOADERS = createMysqlDriverClassLoaders(); } @Override @@ -87,7 +85,7 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, } public void validate() { - //valid driver class name + // valid driver class name String driverClassName = getDriverClassName(); ClassLoader loader = getDriverClassLoader(); if (null == loader) { @@ -106,14 +104,21 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, .map(file -> file.isFile() ? file.getParentFile() : file) .filter(Objects::nonNull) .filter(File::isDirectory) - .map(file -> new File(file, "jdbc")) + // Only the MySQL driver needs to be placed in the jdbc folder. + .map(file -> (MYSQL8_DRIVER_CLASS_NAME.equals(driverClassName) + || MYSQL_DRIVER_CLASS_NAME.equals(driverClassName)) + ? new File(file, "jdbc") + : file) .filter(File::exists) .filter(File::isDirectory) - .distinct().findAny().orElseThrow(() -> new ShouldNeverHappenException("can not find jdbc folder")).getAbsolutePath(); + .distinct() + .findAny() + .map(File::getAbsolutePath) + .orElseThrow(() -> new ShouldNeverHappenException("cannot find jdbc folder")); throw new StoreException(String.format( - "The driver {%s} cannot be found in the path %s. Please ensure that the appropriate database driver dependencies are included in the classpath.", driverClassName, driverClassPath)); + "The driver {%s} cannot be found in the path %s. Please ensure that the appropriate database driver dependencies are included in the classpath.", + driverClassName, driverClassPath)); } - } /** * generate the datasource @@ -139,7 +144,7 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, String driverClassName = CONFIG.getConfig(ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME); if (StringUtils.isBlank(driverClassName)) { throw new StoreException( - String.format("the {%s} can't be empty", ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME)); + String.format("the {%s} can't be empty", ConfigurationKeys.STORE_DB_DRIVER_CLASS_NAME)); } return driverClassName; } @@ -150,12 +155,12 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, * @return the db max wait */ protected Long getMaxWait() { - Long maxWait = CONFIG.getLong(ConfigurationKeys.STORE_DB_MAX_WAIT, DEFAULT_DB_MAX_WAIT); - return maxWait; + return CONFIG.getLong(ConfigurationKeys.STORE_DB_MAX_WAIT, DEFAULT_DB_MAX_WAIT); } protected ClassLoader getDriverClassLoader() { - return MYSQL_DRIVER_LOADERS.getOrDefault(getDriverClassName(), ClassLoader.getSystemClassLoader()); + return DRIVER_LOADERS.getOrDefault( + getDriverClassName(), this.getClass().getClassLoader()); } private static Map<String, ClassLoader> createMysqlDriverClassLoaders() { @@ -168,39 +173,39 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, return loaders; } Stream.of(cp.split(File.pathSeparator)) - .map(File::new) - .filter(File::exists) - .map(file -> file.isFile() ? file.getParentFile() : file) - .filter(Objects::nonNull) - .filter(File::isDirectory) - .map(file -> new File(file, "jdbc")) - .filter(File::exists) - .filter(File::isDirectory) - .distinct() - .flatMap(file -> { - File[] files = file.listFiles((f, name) -> name.startsWith(MYSQL_DRIVER_FILE_PREFIX)); - if (files != null) { - return Stream.of(files); - } else { - return Stream.of(); - } - }) - .forEach(file -> { - if (loaders.containsKey(MYSQL8_DRIVER_CLASS_NAME) && loaders.containsKey(MYSQL_DRIVER_CLASS_NAME)) { - return; - } - try { - URL url = file.toURI().toURL(); - ClassLoader loader = new URLClassLoader(new URL[]{url}, ClassLoader.getSystemClassLoader()); + .map(File::new) + .filter(File::exists) + .map(file -> file.isFile() ? file.getParentFile() : file) + .filter(Objects::nonNull) + .filter(File::isDirectory) + .map(file -> new File(file, "jdbc")) + .filter(File::exists) + .filter(File::isDirectory) + .distinct() + .flatMap(file -> { + File[] files = file.listFiles((f, name) -> name.startsWith(MYSQL_DRIVER_FILE_PREFIX)); + if (files != null) { + return Stream.of(files); + } else { + return Stream.of(); + } + }) + .forEach(file -> { + if (loaders.containsKey(MYSQL8_DRIVER_CLASS_NAME) && loaders.containsKey(MYSQL_DRIVER_CLASS_NAME)) { + return; + } try { - loader.loadClass(MYSQL8_DRIVER_CLASS_NAME); - loaders.putIfAbsent(MYSQL8_DRIVER_CLASS_NAME, loader); - } catch (ClassNotFoundException e) { - loaders.putIfAbsent(MYSQL_DRIVER_CLASS_NAME, loader); + URL url = file.toURI().toURL(); + ClassLoader loader = new URLClassLoader(new URL[] {url}, ClassLoader.getSystemClassLoader()); + try { + loader.loadClass(MYSQL8_DRIVER_CLASS_NAME); + loaders.putIfAbsent(MYSQL8_DRIVER_CLASS_NAME, loader); + } catch (ClassNotFoundException e) { + loaders.putIfAbsent(MYSQL_DRIVER_CLASS_NAME, loader); + } + } catch (MalformedURLException ignore) { } - } catch (MalformedURLException ignore) { - } - }); + }); return loaders; } @@ -243,8 +248,8 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, password = ConfigTools.publicDecrypt(password, publicKey); } catch (Exception e) { LOGGER.error( - "decryption failed,please confirm whether the ciphertext and secret key are correct! error msg: {}", - e.getMessage()); + "decryption failed,please confirm whether the ciphertext and secret key are correct! error msg: {}", + e.getMessage()); } } return password; @@ -292,5 +297,4 @@ public abstract class AbstractDataSourceProvider implements DataSourceProvider, protected String getPublicKey() { return CONFIG.getConfig(ConfigurationKeys.STORE_PUBLIC_KEY); } - } diff --git a/server/src/main/java/org/apache/seata/server/store/DbcpDataSourceProvider.java b/server/src/main/java/org/apache/seata/server/store/DbcpDataSourceProvider.java index 40bac13085..89335f4086 100644 --- a/server/src/main/java/org/apache/seata/server/store/DbcpDataSourceProvider.java +++ b/server/src/main/java/org/apache/seata/server/store/DbcpDataSourceProvider.java @@ -18,8 +18,8 @@ package org.apache.seata.server.store; import org.apache.seata.common.ConfigurationKeys; import org.apache.seata.common.loader.LoadLevel; -import org.apache.seata.core.store.db.AbstractDataSourceProvider; import org.apache.commons.dbcp2.BasicDataSource; +import org.apache.seata.core.store.db.AbstractDataSourceProvider; import javax.sql.DataSource; import java.sql.Connection; diff --git a/server/src/main/java/org/apache/seata/server/store/DruidDataSourceProvider.java b/server/src/main/java/org/apache/seata/server/store/DruidDataSourceProvider.java index d259df26f3..c2aaf7cd1a 100644 --- a/server/src/main/java/org/apache/seata/server/store/DruidDataSourceProvider.java +++ b/server/src/main/java/org/apache/seata/server/store/DruidDataSourceProvider.java @@ -20,8 +20,8 @@ import javax.sql.DataSource; import org.apache.seata.common.ConfigurationKeys; import org.apache.seata.common.loader.LoadLevel; -import org.apache.seata.core.store.db.AbstractDataSourceProvider; import com.alibaba.druid.pool.DruidDataSource; +import org.apache.seata.core.store.db.AbstractDataSourceProvider; import java.sql.Connection; diff --git a/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java b/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java index a0d8c9f8fe..222d6dd611 100644 --- a/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java +++ b/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java @@ -19,14 +19,27 @@ package org.apache.seata.server.store.db; import javax.sql.DataSource; import org.apache.seata.common.loader.EnhancedServiceLoader; +import org.apache.seata.common.loader.EnhancedServiceNotFoundException; +import org.apache.seata.config.ConfigurationFactory; import org.apache.seata.core.store.db.DataSourceProvider; +import org.apache.seata.server.lock.LockerManagerFactory; +import org.apache.seata.server.session.SessionHolder; +import org.junit.After; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; /** */ @SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class AbstractDataSourceProviderTest { private final String dbcpDatasourceType = "dbcp"; @@ -36,29 +49,79 @@ public class AbstractDataSourceProviderTest { private final String hikariDatasourceType = "hikari"; private final String mysqlJdbcDriver = "com.mysql.jdbc.Driver"; + private final String mysql8JdbcDriver = "com.mysql.cj.jdbc.Driver"; + + @BeforeAll + public static void setUp(ApplicationContext context) { + EnhancedServiceLoader.unloadAll(); + ConfigurationFactory.reload(); + System.clearProperty("store.db.driverClassName"); + } + + @AfterEach + void tearDown() { + EnhancedServiceLoader.unloadAll(); + ConfigurationFactory.reload(); + System.clearProperty("store.db.driverClassName"); + } + @Test + @Order(1) public void testDbcpDataSourceProvider() { DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); Assertions.assertNotNull(dataSource); } @Test + @Order(2) + public void testLoadMysqlDriver() { + System.setProperty("loader.path", "/tmp"); + System.setProperty("store.db.driverClassName", mysqlJdbcDriver); + DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + System.setProperty("store.db.driverClassName", mysql8JdbcDriver); + dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + } + + @Test + @Order(3) + public void testLoadDMDriver() { + System.setProperty("store.db.driverClassName", "dm.jdbc.driver.DmDriver"); + DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); + Assertions.assertNotNull(dataSource); + } + + @Test + @Order(4) + public void testLoadDriverFailed() { + System.setProperty("store.db.driverClassName", "dm.jdbc.driver.DmDriver1"); + Assertions.assertThrows(EnhancedServiceNotFoundException.class, () -> { + EnhancedServiceLoader.load(DataSourceProvider.class, dbcpDatasourceType).provide(); + }); + } + + @Test + @Order(5) public void testDruidDataSourceProvider() { DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, druidDatasourceType).provide(); Assertions.assertNotNull(dataSource); } @Test + @Order(6) public void testHikariDataSourceProvider() { DataSource dataSource = EnhancedServiceLoader.load(DataSourceProvider.class, hikariDatasourceType).provide(); Assertions.assertNotNull(dataSource); } @Test + @Order(7) public void testMySQLDataSourceProvider() throws ClassNotFoundException { ClassLoader classLoader = ClassLoader.getSystemClassLoader(); Class<?> driverClass = Class.forName(mysqlJdbcDriver, true, classLoader); Assertions.assertNotNull(driverClass); } + } --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For additional commands, e-mail: notifications-h...@seata.apache.org