diff --git a/README.md b/README.md
index ecff43685d1..645a1587765 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
# Seata: Simple Extensible Autonomous Transaction Architecture
[![Build Status](https://github.com/apache/incubator-seata/workflows/build/badge.svg?branch=develop)](https://github.com/apache/incubator-seata/actions)
-[![codecov](https://codecov.io/gh/apache/incubator-seata/branch/develop/graph/badge.svg)](https://codecov.io/gh/apache/incubator-seata)
+[![codecov](https://codecov.io/gh/apache/incubator-seata/graph/badge.svg?token=tbmHt2ZfxO)](https://codecov.io/gh/apache/incubator-seata)
[![license](https://img.shields.io/github/license/apache/incubator-seata.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![maven](https://img.shields.io/maven-central/v/io.apache/incubator-seata-parent?versionSuffix=2.0.0)](https://search.maven.org/search?q=io.seata)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index b936d95adc8..2c5b4c3879a 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -26,6 +26,9 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#6701](https://github.com/apache/incubator-seata/pull/6728)] fix support serialization for dm.jdbc.driver.DmdbTimestamp
- [[#6757](https://github.com/apache/incubator-seata/pull/6757)] the bug where multiple nodes cannot be retrieved from the naming server
- [[#6769](https://github.com/apache/incubator-seata/pull/6769)] fix tcc fence deadLock
+- [[#6778](https://github.com/apache/incubator-seata/pull/6778)] fix namingserver node term
+- [[#6765](https://github.com/apache/incubator-seata/pull/6765)] fix MySQL driver loading by replacing custom classloader with system classloader for better compatibility and simplified process
+- [[#6781](https://github.com/apache/incubator-seata/pull/6781)] the issue where the TC occasionally fails to go offline from the NamingServer
### optimize:
@@ -62,7 +65,12 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#6763](https://github.com/apache/incubator-seata/pull/6763)] optimize NacosConfiguration singleton reload
- [[#6761](https://github.com/apache/incubator-seata/pull/6761)] optimize the namingserver code to improve readability
- [[#6768](https://github.com/apache/incubator-seata/pull/6768)] report the tcc fence transaction isolation level
-
+- [[#6770](https://github.com/apache/incubator-seata/pull/6770)] Automatic deletion of namingserver vgroup through Caffeine map
+- [[#6780](https://github.com/apache/incubator-seata/pull/6780)] optimize the reflection operation in class `SerializerServiceLoader`
+- [[#6784](https://github.com/apache/incubator-seata/pull/6784)] upgrade axios to 1.7.4
+- [[#6787](https://github.com/apache/incubator-seata/pull/6787)] upgrade elliptic to 6.5.7
+- [[#6783](https://github.com/apache/incubator-seata/pull/6783)] rename the server naming/v1 api to vgroup/v1
+- [[#6793](https://github.com/apache/incubator-seata/pull/6793)] fix npmjs conflicts
### refactor:
@@ -74,7 +82,10 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#6608](https://github.com/apache/incubator-seata/pull/6608)] add unit test for sql-parser-core
- [[#6647](https://github.com/apache/incubator-seata/pull/6647)] improve the test case coverage of saga module to 70%
- [[#6695](https://github.com/apache/incubator-seata/pull/6695)] old version(< 0.7.1) client test case for multi-version protocol
+- [[#6764](https://github.com/apache/incubator-seata/pull/6764)] add Apollo mock test case
- [[#6750](https://github.com/apache/incubator-seata/pull/6750)] increase spring autoconfigure module unit test converage
+- [[#6773](https://github.com/apache/incubator-seata/pull/6773)] fix the wrong code coverage from codecov icon in default branch
+
Thanks to these contributors for their code commits. Please report an unintended omission.
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 0d9194e4be3..9a26e964fcb 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -27,6 +27,10 @@
- [[#6701](https://github.com/apache/incubator-seata/pull/6728)] 修复达梦数据库的对dm.jdbc.driver.DmdbTimestamp的支持
- [[#6757](https://github.com/apache/incubator-seata/pull/6757)] 修复client通过namingserver只能获取到一个tc节点的bug
- [[#6769](https://github.com/apache/incubator-seata/pull/6769)] 修复tcc fence死锁
+- [[#6778](https://github.com/apache/incubator-seata/pull/6778)] 修复namingserver的节点term为0问题
+- [[#6765](https://github.com/apache/incubator-seata/pull/6765)] 改进MySQL驱动加载机制,将自定义类加载器替换为系统类加载器,更兼容简化流程
+- [[#6781](https://github.com/apache/incubator-seata/pull/6781)] 修复tc下线时,由于定时任务没有先关闭,导致下线后还会被注册上,需要靠namingserver的健康检查来下线的bug
+
### optimize:
- [[#6499](https://github.com/apache/incubator-seata/pull/6499)] 拆分 committing 和 rollbacking 状态的任务线程池
@@ -62,6 +66,12 @@
- [[#6763](https://github.com/apache/incubator-seata/pull/6763)] 优化 NacosConfiguration 单例加载
- [[#6761](https://github.com/apache/incubator-seata/pull/6761)] 提升namingserver manager代码可读性
- [[#6768](https://github.com/apache/incubator-seata/pull/6768)] 上报tcc fence事务隔离级别
+- [[#6770](https://github.com/apache/incubator-seata/pull/6770)] 通过caffeine map支持namingserver事务分组的过期删除
+- [[#6780](https://github.com/apache/incubator-seata/pull/6780)] 优化类 `SerializerServiceLoader` 中的反射操作
+- [[#6784](https://github.com/apache/incubator-seata/pull/6784)] 升级 axios 至 1.7.4 版本
+- [[#6787](https://github.com/apache/incubator-seata/pull/6787)] 升级 elliptic 至 6.5.7 版本
+- [[#6783](https://github.com/apache/incubator-seata/pull/6783)] 将server事务分组修改接口改为/vgroup/v1
+- [[#6793](https://github.com/apache/incubator-seata/pull/6793)] 修复 npmjs 依赖冲突问题
### refactor:
@@ -75,8 +85,9 @@
- [[#6608](https://github.com/apache/incubator-seata/pull/6608)] 添加sql-parser-core模块测试用例
- [[#6647](https://github.com/apache/incubator-seata/pull/6647)] 增加saga模块的测试用例覆盖率
- [[#6695](https://github.com/apache/incubator-seata/pull/6695)] 多版本协议的旧版本(< 0.7.1)客户端测试用例
+- [[#6764](https://github.com/apache/incubator-seata/pull/6764)] 增加 Apollo Mock 测试用例
- [[#6750](https://github.com/apache/incubator-seata/pull/6750)] 提升spring autoconfigure模块单测覆盖率
-
+- [[#6773](https://github.com/apache/incubator-seata/pull/6773)] 修复codecov图标显示错误的代码覆盖率
diff --git a/common/src/main/java/org/apache/seata/common/NamingServerConstants.java b/common/src/main/java/org/apache/seata/common/NamingServerConstants.java
index 975a42d3ee0..11ba530cfd8 100644
--- a/common/src/main/java/org/apache/seata/common/NamingServerConstants.java
+++ b/common/src/main/java/org/apache/seata/common/NamingServerConstants.java
@@ -25,7 +25,7 @@ public interface NamingServerConstants {
/**
* The constant HTTP_ADD_GROUP_SUFFIX
*/
- String HTTP_ADD_GROUP_SUFFIX = "/naming/v1/addVGroup?";
+ String HTTP_ADD_GROUP_SUFFIX = "/vgroup/v1/addVGroup?";
/**
* The constant CONSTANT_UNIT
@@ -40,7 +40,7 @@ public interface NamingServerConstants {
/**
* The constant HTTP_REMOVE_GROUP_SUFFIX
*/
- String HTTP_REMOVE_GROUP_SUFFIX = "/naming/v1/removeVGroup?";
+ String HTTP_REMOVE_GROUP_SUFFIX = "/vgroup/v1/removeVGroup?";
/**
* The constant IP_PORT_SPLIT_CHAR
diff --git a/common/src/main/java/org/apache/seata/common/metadata/namingserver/NamingServerNode.java b/common/src/main/java/org/apache/seata/common/metadata/namingserver/NamingServerNode.java
index 5645ac0e3ed..459dd66b944 100644
--- a/common/src/main/java/org/apache/seata/common/metadata/namingserver/NamingServerNode.java
+++ b/common/src/main/java/org/apache/seata/common/metadata/namingserver/NamingServerNode.java
@@ -27,6 +27,15 @@ public class NamingServerNode extends Node {
private double weight = 1.0;
private boolean healthy = true;
private long term;
+ private String unit;
+
+ public String getUnit() {
+ return unit;
+ }
+
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
public double getWeight() {
return weight;
diff --git a/common/src/main/java/org/apache/seata/common/util/ReflectionUtil.java b/common/src/main/java/org/apache/seata/common/util/ReflectionUtil.java
index b9ba762bef6..5da00a4b611 100644
--- a/common/src/main/java/org/apache/seata/common/util/ReflectionUtil.java
+++ b/common/src/main/java/org/apache/seata/common/util/ReflectionUtil.java
@@ -89,6 +89,21 @@ public static Class> getClassByName(String className) throws ClassNotFoundExce
return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
}
+ /**
+ * Is class present boolean.
+ *
+ * @param className the class name
+ * @return boolean true if the class is present
+ */
+ public static boolean isClassPresent(String className) {
+ try {
+ Class.forName(className, false, Thread.currentThread().getContextClassLoader());
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
/**
* Get the wrapped class
*
diff --git a/common/src/test/java/org/apache/seata/common/util/ReflectionUtilTest.java b/common/src/test/java/org/apache/seata/common/util/ReflectionUtilTest.java
index 20f22c8be7a..7a1c390c14b 100644
--- a/common/src/test/java/org/apache/seata/common/util/ReflectionUtilTest.java
+++ b/common/src/test/java/org/apache/seata/common/util/ReflectionUtilTest.java
@@ -45,6 +45,12 @@ public void testGetClassByName() throws ClassNotFoundException {
ReflectionUtil.getClassByName("java.lang.String"));
}
+ @Test
+ public void testIsClassPresent() {
+ Assertions.assertTrue(ReflectionUtil.isClassPresent("java.lang.String"));
+ Assertions.assertFalse(ReflectionUtil.isClassPresent("java.lang.String2"));
+ }
+
@Test
public void testGetWrappedClass() {
Assertions.assertEquals(Byte.class, ReflectionUtil.getWrappedClass(byte.class));
diff --git a/config/seata-config-apollo/pom.xml b/config/seata-config-apollo/pom.xml
index 16d8eb80bec..2515fb9db24 100644
--- a/config/seata-config-apollo/pom.xml
+++ b/config/seata-config-apollo/pom.xml
@@ -39,6 +39,16 @@
com.ctrip.framework.apollo
apollo-client
+
+ com.squareup.okhttp3
+ mockwebserver
+ test
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ test
+
diff --git a/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloConfigurationTest.java b/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloConfigurationTest.java
new file mode 100644
index 00000000000..aff6785a55e
--- /dev/null
+++ b/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloConfigurationTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.config.apollo;
+
+import java.io.IOException;
+
+import org.apache.seata.common.exception.NotSupportYetException;
+import org.apache.seata.config.ConfigurationChangeEvent;
+import org.apache.seata.config.ConfigurationChangeListener;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * The type Apollo configuration test.
+ */
+public class ApolloConfigurationTest {
+
+ private static final int PORT = 8081;
+ private static ApolloMockServer apolloMockServer;
+
+ private static ApolloConfiguration apolloConfiguration;
+
+ /**
+ * Sets up.
+ *
+ * @throws IOException the io exception
+ */
+ @BeforeAll
+ public static void setUp() throws IOException {
+ System.setProperty("seataEnv", "test");
+ apolloMockServer = new ApolloMockServer(PORT);
+ apolloConfiguration = ApolloConfiguration.getInstance();
+ }
+
+ /**
+ * Test get config.
+ */
+ @Test
+ public void testGetConfig() {
+ String value = apolloConfiguration.getConfig("seata.test");
+ Assertions.assertEquals("mockdata", value);
+ value = apolloConfiguration.getConfig("seata.key");
+ Assertions.assertNull(value);
+ value = apolloConfiguration.getConfig("seata.key.1", "default");
+ Assertions.assertEquals("default", value);
+ value = apolloConfiguration.getLatestConfig("seata.key.2", "default", 3000);
+ Assertions.assertEquals("default", value);
+ }
+
+ /**
+ * Test update config.
+ */
+ @Test
+ public void testUpdateConfig() {
+ Assertions.assertThrows(NotSupportYetException.class, () -> {
+ apolloConfiguration.putConfig("seata.test", "mockdata");
+ });
+ Assertions.assertThrows(NotSupportYetException.class, () -> {
+ apolloConfiguration.putConfigIfAbsent("seata.test", "mockdata");
+ });
+ Assertions.assertThrows(NotSupportYetException.class, () -> {
+ apolloConfiguration.removeConfig("seata.test");
+ });
+ }
+
+ /**
+ * Test listener.
+ */
+ @Test
+ public void testListener() {
+ ConfigurationChangeListener listener = new ConfigurationChangeListener() {
+ @Override
+ public void onChangeEvent(ConfigurationChangeEvent event) {
+
+ }
+ };
+ apolloConfiguration.addConfigListener("seata.test", listener);
+ Assertions.assertEquals(1, apolloConfiguration.getConfigListeners("seata.test").size());
+ apolloConfiguration.removeConfigListener("seata.test", null);
+ Assertions.assertEquals(1, apolloConfiguration.getConfigListeners("seata.test").size());
+ apolloConfiguration.removeConfigListener("seata.test", listener);
+ Assertions.assertEquals(0, apolloConfiguration.getConfigListeners("seata.test").size());
+
+ }
+
+ /**
+ * Tear down.
+ *
+ * @throws IOException the io exception
+ */
+ @AfterAll
+ public static void tearDown() throws IOException {
+ System.clearProperty("seataEnv");
+ apolloMockServer.stop();
+ }
+
+}
diff --git a/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloMockServer.java b/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloMockServer.java
new file mode 100644
index 00000000000..aa087221777
--- /dev/null
+++ b/config/seata-config-apollo/src/test/java/org/apache/seata/config/apollo/ApolloMockServer.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.seata.config.apollo;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import com.ctrip.framework.apollo.core.dto.ApolloConfig;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.mockwebserver.Dispatcher;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import okhttp3.mockwebserver.RecordedRequest;
+
+/**
+ * The type Apollo mock server.
+ */
+public class ApolloMockServer {
+
+ private MockWebServer server;
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ private final String CONFIG_PREFIX_PATH = "/configs";
+
+ /**
+ * Instantiates a new Apollo mock server.
+ *
+ * @param port the port
+ * @throws IOException the io exception
+ */
+ public ApolloMockServer(int port) throws IOException {
+
+ server = new MockWebServer();
+ server.setDispatcher(new Dispatcher() {
+ @Override
+ public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+ if (request.getPath().startsWith(CONFIG_PREFIX_PATH)) {
+ List pathSegments = request.getRequestUrl().pathSegments();
+ String appId = pathSegments.get(1);
+ String cluster = pathSegments.get(2);
+ String namespace = pathSegments.get(3);
+ String result;
+ try {
+ result = loadMockData(appId, cluster, namespace);
+ return new MockResponse().setResponseCode(200).setBody(result);
+ } catch (JsonProcessingException e) {
+ }
+ }
+ return new MockResponse().setResponseCode(404);
+ }
+ });
+ server.start(port);
+ System.setProperty("apollo.configService", "http://localhost:" + port);
+
+ }
+
+ private String loadMockData(String appId, String Cluster, String namespace) throws JsonProcessingException {
+ String fileName = "mock-" + namespace + ".properties";
+ ApolloConfig apolloConfig = new ApolloConfig(appId, Cluster, namespace, "releaseKey");
+ Properties properties = new Properties();
+ try (InputStream input = this.getClass().getClassLoader().getResourceAsStream(fileName)) {
+ if (null != input) {
+ properties.load(input);
+ }
+ } catch (Exception ignore) {
+ }
+ Map configurations = new HashMap<>();
+ for (Map.Entry