diff --git a/bom/pom.xml b/bom/pom.xml
index a75784c55cb..969f8487e99 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -48,12 +48,12 @@
org.apache.seata
- seata-threadpool
+ seata-spi-jdk17
${project.version}
org.apache.seata
- seata-threadpool-loom
+ seata-spi-jdk21
${project.version}
diff --git a/common/pom.xml b/common/pom.xml
index 5b157d750a4..947f30a7628 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -52,5 +52,20 @@
okhttp
provided
+
+ com.alibaba
+ fastjson
+ provided
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ provided
+
+
+ com.google.code.gson
+ gson
+ provided
+
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java b/common/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
rename to common/src/main/java/org/apache/seata/common/json/JsonAllowlistManager.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializer.java b/common/src/main/java/org/apache/seata/common/json/JsonSerializer.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializer.java
rename to common/src/main/java/org/apache/seata/common/json/JsonSerializer.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java b/common/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
rename to common/src/main/java/org/apache/seata/common/json/JsonSerializerFactory.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java b/common/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
rename to common/src/main/java/org/apache/seata/common/json/impl/Fastjson2JsonSerializer.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java b/common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
rename to common/src/main/java/org/apache/seata/common/json/impl/FastjsonJsonSerializer.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java b/common/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
rename to common/src/main/java/org/apache/seata/common/json/impl/GsonJsonSerializer.java
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java b/common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
rename to common/src/main/java/org/apache/seata/common/json/impl/JacksonJsonSerializer.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolExecutor.java b/common/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolExecutor.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolExecutor.java
rename to common/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolExecutor.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolProvider.java b/common/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolProvider.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolProvider.java
rename to common/src/main/java/org/apache/seata/common/thread/PlatformThreadPoolProvider.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolProvider.java b/common/src/main/java/org/apache/seata/common/thread/ThreadPoolProvider.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolProvider.java
rename to common/src/main/java/org/apache/seata/common/thread/ThreadPoolProvider.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolProviderOrders.java b/common/src/main/java/org/apache/seata/common/thread/ThreadPoolProviderOrders.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolProviderOrders.java
rename to common/src/main/java/org/apache/seata/common/thread/ThreadPoolProviderOrders.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolType.java b/common/src/main/java/org/apache/seata/common/thread/ThreadPoolType.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolType.java
rename to common/src/main/java/org/apache/seata/common/thread/ThreadPoolType.java
diff --git a/json-common/json-common-core/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer b/common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
similarity index 100%
rename from json-common/json-common-core/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
rename to common/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
diff --git a/threadpool/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider b/common/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
similarity index 100%
rename from threadpool/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
rename to common/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
diff --git a/compatible/pom.xml b/compatible/pom.xml
index 2ceb1ab96a0..b8e1d7e7aee 100644
--- a/compatible/pom.xml
+++ b/compatible/pom.xml
@@ -40,11 +40,6 @@
seata-saga-engine
${project.version}
-
- org.apache.seata
- json-common-core
- ${project.version}
-
org.apache.seata
seata-saga-engine-store
diff --git a/core/pom.xml b/core/pom.xml
index e0b2395a499..48d5fd29f7c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -42,11 +42,6 @@
seata-discovery-core
${project.version}
-
- ${project.groupId}
- seata-threadpool
- ${project.version}
-
io.netty
netty-all
diff --git a/json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonUtil.java b/core/src/main/java/org/apache/seata/common/json/JsonUtil.java
similarity index 100%
rename from json-common/json-common-core/src/main/java/org/apache/seata/common/json/JsonUtil.java
rename to core/src/main/java/org/apache/seata/common/json/JsonUtil.java
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java b/core/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java
similarity index 97%
rename from threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java
rename to core/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java
index e1b3090adf2..510c5c1fa36 100644
--- a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java
+++ b/core/src/main/java/org/apache/seata/common/thread/ThreadPoolExecutorFactory.java
@@ -165,9 +165,8 @@ private static ThreadPoolProvider resolveThreadPoolProvider() {
// This second warning is intentionally kept to surface the per-request fallback
// decision so that operators can correlate the missing-provider startup message
// with the actual thread-pool mode that is in effect.
- LOGGER.warn(
- "Virtual thread pool was selected but the virtual-thread SPI provider (seata-threadpool-virtual) "
- + "is not present on the classpath. Falling back to platform threads.");
+ LOGGER.warn("Virtual thread pool was selected but the virtual-thread SPI provider (seata-spi-jdk21) "
+ + "is not present on the classpath. Falling back to platform threads.");
}
return ThreadPoolProviderHolder.PLATFORM_THREAD_POOL_PROVIDER;
}
diff --git a/threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolRuntimeEnvironment.java b/core/src/main/java/org/apache/seata/common/thread/ThreadPoolRuntimeEnvironment.java
similarity index 100%
rename from threadpool/src/main/java/org/apache/seata/common/thread/ThreadPoolRuntimeEnvironment.java
rename to core/src/main/java/org/apache/seata/common/thread/ThreadPoolRuntimeEnvironment.java
diff --git a/threadpool/src/test/java/org/apache/seata/common/thread/ThreadPoolExecutorFactoryTest.java b/core/src/test/java/org/apache/seata/common/thread/ThreadPoolExecutorFactoryTest.java
similarity index 100%
rename from threadpool/src/test/java/org/apache/seata/common/thread/ThreadPoolExecutorFactoryTest.java
rename to core/src/test/java/org/apache/seata/common/thread/ThreadPoolExecutorFactoryTest.java
diff --git a/discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java b/discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java
index 8aae9178716..4f0f222237b 100644
--- a/discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java
+++ b/discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java
@@ -22,7 +22,7 @@
import com.ecwid.consul.v1.agent.model.NewService;
import com.ecwid.consul.v1.health.HealthServicesRequest;
import com.ecwid.consul.v1.health.model.HealthService;
-import org.apache.seata.common.thread.ThreadPoolExecutorFactory;
+import org.apache.seata.common.thread.PlatformThreadPoolProvider;
import org.apache.seata.common.util.NetUtil;
import org.apache.seata.common.util.StringUtils;
import org.apache.seata.config.Configuration;
@@ -96,13 +96,16 @@ private ConsulRegistryServiceImpl() {
clusterAddressMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
listenerMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
notifiers = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
- notifierExecutor = ThreadPoolExecutorFactory.newThreadPoolExecutor(
- "services-consul-notifier",
- THREAD_POOL_NUM,
- THREAD_POOL_NUM,
- Integer.MAX_VALUE,
- TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<>());
+ notifierExecutor = new PlatformThreadPoolProvider()
+ .newThreadPoolExecutor(
+ "services-consul-notifier",
+ THREAD_POOL_NUM,
+ THREAD_POOL_NUM,
+ Integer.MAX_VALUE,
+ TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(),
+ true,
+ new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
}
/**
diff --git a/discovery/seata-discovery-core/pom.xml b/discovery/seata-discovery-core/pom.xml
index ef149884506..98e7d06e5a4 100644
--- a/discovery/seata-discovery-core/pom.xml
+++ b/discovery/seata-discovery-core/pom.xml
@@ -35,12 +35,6 @@
seata-config-core
${project.version}
-
- ${project.groupId}
- seata-threadpool
- ${project.version}
-
-
ch.qos.logback
logback-classic
diff --git a/discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java b/discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java
index c85b16c3730..04864792bcc 100644
--- a/discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java
+++ b/discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java
@@ -16,7 +16,7 @@
*/
package org.apache.seata.discovery.registry;
-import org.apache.seata.common.thread.ThreadPoolExecutorFactory;
+import org.apache.seata.common.thread.PlatformThreadPoolProvider;
import org.apache.seata.config.Configuration;
import org.apache.seata.config.ConfigurationFactory;
import org.slf4j.Logger;
@@ -24,6 +24,7 @@
import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
@@ -42,8 +43,8 @@ public class RegistryHeartBeats {
private static final long DEFAULT_HEARTBEAT_PERIOD = 60 * 1000;
private static final boolean DEFAULT_HEARTBEAT_ENABLED = Boolean.TRUE;
- private static final ScheduledExecutorService HEARTBEAT_SCHEDULED =
- ThreadPoolExecutorFactory.newScheduledThreadPoolExecutor("seata-discovery-heartbeat", 1, true);
+ private static final ScheduledExecutorService HEARTBEAT_SCHEDULED = new PlatformThreadPoolProvider()
+ .newScheduledThreadPoolExecutor("seata-discovery-heartbeat", 1, true, new ThreadPoolExecutor.AbortPolicy());
public static void addHeartBeat(String registryType, InetSocketAddress serverAddress, ReRegister reRegister) {
addHeartBeat(registryType, serverAddress, getHeartbeatPeriod(registryType), reRegister);
diff --git a/discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java b/discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java
index be5bf174a39..58697840451 100644
--- a/discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java
+++ b/discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java
@@ -28,7 +28,7 @@
import io.etcd.jetcd.options.WatchOption;
import io.etcd.jetcd.watch.WatchResponse;
import org.apache.seata.common.exception.ShouldNeverHappenException;
-import org.apache.seata.common.thread.ThreadPoolExecutorFactory;
+import org.apache.seata.common.thread.PlatformThreadPoolProvider;
import org.apache.seata.common.util.NetUtil;
import org.apache.seata.common.util.StringUtils;
import org.apache.seata.config.Configuration;
@@ -104,13 +104,16 @@ private EtcdRegistryServiceImpl() {
clusterAddressMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
listenerMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
watcherMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
- executorService = ThreadPoolExecutorFactory.newThreadPoolExecutor(
- "registry-etcd3",
- THREAD_POOL_SIZE,
- THREAD_POOL_SIZE,
- Integer.MAX_VALUE,
- TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<>());
+ executorService = new PlatformThreadPoolProvider()
+ .newThreadPoolExecutor(
+ "registry-etcd3",
+ THREAD_POOL_SIZE,
+ THREAD_POOL_SIZE,
+ Integer.MAX_VALUE,
+ TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(),
+ true,
+ new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
}
/**
diff --git a/discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java
index e7712f8d286..2741bcb1d18 100644
--- a/discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java
+++ b/discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java
@@ -19,7 +19,7 @@
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.seata.common.ConfigurationKeys;
import org.apache.seata.common.exception.ShouldNeverHappenException;
-import org.apache.seata.common.thread.ThreadPoolExecutorFactory;
+import org.apache.seata.common.thread.PlatformThreadPoolProvider;
import org.apache.seata.common.util.CollectionUtils;
import org.apache.seata.common.util.NetUtil;
import org.apache.seata.common.util.StringUtils;
@@ -74,10 +74,19 @@ public class RedisRegistryServiceImpl implements RegistryService
private String transactionServiceGroup;
+ private static final PlatformThreadPoolProvider THREAD_POOL_PROVIDER = new PlatformThreadPoolProvider();
private ScheduledExecutorService threadPoolExecutorForSubscribe =
- ThreadPoolExecutorFactory.newScheduledThreadPoolExecutor("RedisRegistryService-subscribe", 1);
+ THREAD_POOL_PROVIDER.newScheduledThreadPoolExecutor(
+ "RedisRegistryService-subscribe",
+ 1,
+ true,
+ new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
private ScheduledExecutorService threadPoolExecutorForUpdateMap =
- ThreadPoolExecutorFactory.newScheduledThreadPoolExecutor("RedisRegistryService-updateClusterAddrMap", 1);
+ THREAD_POOL_PROVIDER.newScheduledThreadPoolExecutor(
+ "RedisRegistryService-updateClusterAddrMap",
+ 1,
+ true,
+ new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
private RedisRegistryServiceImpl() {
Configuration seataConfig = ConfigurationFactory.CURRENT_FILE_INSTANCE;
diff --git a/integration-tx-api/pom.xml b/integration-tx-api/pom.xml
index 46200183000..c08e5127e33 100644
--- a/integration-tx-api/pom.xml
+++ b/integration-tx-api/pom.xml
@@ -57,11 +57,6 @@
seata-common
${project.version}
-
- ${project.groupId}
- json-common-core
- ${project.version}
-
net.bytebuddy
byte-buddy
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
index 6fe82c5e01c..516672347df 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParser.java
@@ -19,7 +19,7 @@
import java.io.IOException;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in seata-common module instead.
*/
@Deprecated
public interface JsonParser {
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
index c5b38833a53..5f3bec98cc1 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserFactory.java
@@ -25,7 +25,7 @@
import java.util.concurrent.ConcurrentHashMap;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory} in seata-common module instead.
*/
@Deprecated
public class JsonParserFactory {
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
index a09b6054001..99bf50b1ace 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/json/JsonParserWrap.java
@@ -19,7 +19,7 @@
import org.apache.seata.common.exception.JsonParseException;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in seata-common module instead.
*/
@Deprecated
public class JsonParserWrap implements JsonParser {
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
index 23601b2a1b2..7963cc3e9d3 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/util/JsonUtil.java
@@ -25,7 +25,7 @@
import java.util.Objects;
/**
- * @deprecated use {@link org.apache.seata.common.json.JsonUtil} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonUtil} in seata-common module instead.
*/
@Deprecated
public class JsonUtil {
diff --git a/json-common/json-common-core/pom.xml b/json-common/json-common-core/pom.xml
deleted file mode 100644
index 9c69f312cd1..00000000000
--- a/json-common/json-common-core/pom.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
- org.apache.seata
- json-common
- ${revision}
-
- 4.0.0
- json-common-core
- jar
- json-common-core ${project.version}
- jsonUtil core for Seata modules
-
-
-
- ${project.groupId}
- seata-common
- ${project.version}
-
-
- ${project.groupId}
- seata-core
- ${project.version}
-
-
- com.alibaba
- fastjson
- provided
-
-
- com.alibaba.fastjson2
- fastjson2
- provided
-
-
- com.fasterxml.jackson.core
- jackson-databind
- provided
-
-
- com.google.code.gson
- gson
- provided
-
-
-
-
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java
deleted file mode 100644
index 16f6e1b9061..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2AllowlistTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 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.common.json;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for Fastjson2 serializer with allowlist security check
- */
-public class Fastjson2AllowlistTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson2");
- }
-
- @AfterEach
- void tearDown() {
- JsonAllowlistManager.getInstance().clearUserAllowlist();
- }
-
- @Test
- public void testParseObject_allowedSeataClass() {
-
- String json =
- "{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
-
- AllowedTestClass result = jsonSerializer.parseObject(json, AllowedTestClass.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_allowedJavaClass() {
-
- String json = "{\"@type\":\"java.util.HashMap\"}";
-
- Object result = jsonSerializer.parseObject(json, Object.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_notAllowedClass() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, Object.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("not in JSON deserialization allowlist")
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_userAllowedClass() {
-
- JsonAllowlistManager.getInstance().addUserClass("com.example.UserClass");
-
- String json = "{\"@type\":\"com.example.UserClass\",\"data\":\"test\"}";
-
- Assertions.assertDoesNotThrow(() -> jsonSerializer.parseObject(json, Object.class, false));
- }
-
- @Test
- public void testParseObject_userAllowedPrefix() {
- JsonAllowlistManager.getInstance().addUserPrefix("com.mycompany.model.");
-
- String json = "{\"@type\":\"com.mycompany.model.User\",\"id\":1}";
-
- Assertions.assertDoesNotThrow(() -> jsonSerializer.parseObject(json, Object.class, false));
- }
-
- @Test
- public void testParseObject_ignoreAutoType_bypasses_check() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- try {
- jsonSerializer.parseObject(json, Object.class, true);
- } catch (SecurityException e) {
- throw new AssertionError("Should not throw SecurityException when ignoreAutoType=true", e);
- } catch (Exception e) {
-
- assertThat(e).isNotInstanceOf(SecurityException.class);
- }
- }
-
- @Test
- public void testParseObject_noAutoType_bypasses_check() {
-
- String json = "{\"name\":\"test\",\"value\":123}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_multipleAutoTypes() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
-
- ContainerClass result = jsonSerializer.parseObject(json, ContainerClass.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_multipleAutoTypes_oneNotAllowed() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.Fastjson2AllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"com.malicious.EvilClass\",\"name\":\"evil\"}}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, ContainerClass.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_atTypeInStringValue_notBlocked() {
- String json = "{\"description\":\"the \\\"@type\\\" field is important\",\"name\":\"test\"}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testLoadUserAllowlist_thenParse() {
- JsonAllowlistManager.getInstance().loadUserAllowlist("com.trusted.model.,com.trusted.dto.SpecificDTO");
-
- String json1 = "{\"@type\":\"com.trusted.model.User\",\"id\":1}";
- try {
- jsonSerializer.parseObject(json1, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json2 = "{\"@type\":\"com.trusted.dto.SpecificDTO\",\"data\":\"test\"}";
- try {
- jsonSerializer.parseObject(json2, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json3 = "{\"@type\":\"com.untrusted.EvilClass\",\"data\":\"evil\"}";
- assertThatThrownBy(() -> jsonSerializer.parseObject(json3, Object.class, false))
- .isInstanceOf(SecurityException.class);
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-
- public static class AllowedTestClass {
- private String name;
-
- public AllowedTestClass() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
-
- public static class ContainerClass {
- private AllowedTestClass inner;
-
- public ContainerClass() {}
-
- public AllowedTestClass getInner() {
- return inner;
- }
-
- public void setInner(AllowedTestClass inner) {
- this.inner = inner;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java
deleted file mode 100644
index 060cdc0d203..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/Fastjson2JsonSerializerTest.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * 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.common.json;
-
-import com.alibaba.fastjson2.TypeReference;
-import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.Fastjson2JsonSerializer;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class Fastjson2JsonSerializerTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson2");
- }
-
- @Test
- public void testToJSONString_basicObject() {
- TestObject obj = new TestObject("test", 123);
- String json = jsonSerializer.toJSONString(obj);
-
- assertThat(json).contains("\"name\":\"test\"");
- assertThat(json).contains("\"value\":123");
- }
-
- @Test
- public void testParseObject_basicObject() {
- String json = "{\"name\":\"test\",\"value\":123}";
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
- }
-
- @Test
- public void testToJSONString_and_parseObject() {
- TestObject original = new TestObject("school", 456);
- String json = jsonSerializer.toJSONString(original);
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(restored.getName()).isEqualTo(original.getName());
- assertThat(restored.getValue()).isEqualTo(original.getValue());
- }
-
- @Test
- public void testUseAutoType_withType() {
- String json = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isTrue();
- }
-
- @Test
- public void testUseAutoType_withoutType() {
- String json = "{\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testToJSONString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, true);
-
- assertThat(prettyJson).contains("\n");
- }
-
- @Test
- public void testToJSONString_ignoreAutoType() {
- TestObject obj = new TestObject("noType", 111);
- String jsonWithoutType = jsonSerializer.toJSONString(obj, true, true);
-
- assertThat(jsonWithoutType).doesNotContain("@type");
- }
-
- @Test
- public void testParseObject_ignoreAutoType() {
- String json = jsonSerializer.toJSONString(new TestObject("ignored", 222));
-
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class, true);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("ignored");
- assertThat(obj.getValue()).isEqualTo(222);
- }
-
- @Test
- public void testEmptyList_serialization() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testEmptyList_deserialization() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testNullInput_toJSONString() {
- String json = jsonSerializer.toJSONString(null);
- assertThat(json).isEqualTo("null");
- }
-
- @Test
- public void testNullInput_parseObject() {
- TestObject obj = jsonSerializer.parseObject(null, TestObject.class);
- assertThat(obj).isNull();
-
- TestObject obj2 = jsonSerializer.parseObject("{}", null);
- assertThat(obj2).isNull();
- }
-
- @Test
- public void testParseObject_invalidJson() {
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Fastjson2 deserialize error");
- }
-
- @Test
- public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("fastjson2");
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(Fastjson2JsonSerializer.class);
- }
-
- @Test
- public void testToJSONString_withAutoType() {
- TestObject obj = new TestObject("withType", 789);
- String jsonWithAutoType = jsonSerializer.toJSONString(obj, false, false);
-
- assertThat(jsonWithAutoType).contains("@type");
- }
-
- @Test
- public void testParseObject_withAutoType() {
- TestObject original = new TestObject("autoTypeTest", 999);
- String jsonWithAutoType = jsonSerializer.toJSONString(original, false, false);
-
- TestObject restored = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("autoTypeTest");
- assertThat(restored.getValue()).isEqualTo(999);
- }
-
- @Test
- public void testParseObject_withType() {
- String json = "{\"name\":\"test\",\"value\":123}";
- Type type = new TypeReference() {}.getType();
-
- TestObject obj = jsonSerializer.parseObjectWithType(json, type);
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
-
- String listJson = "[{\"name\":\"item1\",\"value\":1},{\"name\":\"item2\",\"value\":2}]";
- Type listType = new TypeReference>() {}.getType();
-
- List list = jsonSerializer.parseObjectWithType(listJson, listType);
- assertThat(list).hasSize(2);
- assertThat(list.get(0).getName()).isEqualTo("item1");
- assertThat(list.get(1).getValue()).isEqualTo(2);
- }
-
- @Test
- public void testParseObject_nullJson() {
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
- }
-
- @Test
- public void testParseObject_emptyList() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testParseObject_withIgnoreAutoType() {
- String jsonWithAutoType = jsonSerializer.toJSONString(new TestObject("ignored", 222));
-
- TestObject objIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, true);
- assertThat(objIgnore).isNotNull();
- assertThat(objIgnore.getName()).isEqualTo("ignored");
- assertThat(objIgnore.getValue()).isEqualTo(222);
-
- TestObject objNoIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
- assertThat(objNoIgnore).isNotNull();
- assertThat(objNoIgnore.getName()).isEqualTo("ignored");
- assertThat(objNoIgnore.getValue()).isEqualTo(222);
-
- List> emptyList = jsonSerializer.parseObject("[]", List.class, false);
- assertThat(emptyList).isEmpty();
-
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
-
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class, false))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Fastjson2 deserialize error");
- }
-
- /**
- * The "[]" shortcut in parseObject(String, Class, boolean) must only apply when the
- * target type is a Collection. Otherwise it would silently return an empty ArrayList
- * cast to T, causing a ClassCastException at the call site. The exact behaviour of the
- * underlying library when asked to map "[]" to a POJO may vary (return null, return an
- * empty POJO, or throw); the only requirement enforced here is that the result is never
- * an ArrayList.
- */
- @Test
- public void testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
- assertEmptyArrayDoesNotProduceCollection(true);
- assertEmptyArrayDoesNotProduceCollection(false);
- }
-
- private void assertEmptyArrayDoesNotProduceCollection(boolean ignoreAutoType) {
- Object result;
- try {
- result = jsonSerializer.parseObject("[]", TestObject.class, ignoreAutoType);
- } catch (JsonParseException ignored) {
- // throwing is also an acceptable outcome
- return;
- }
- if (result != null) {
- assertThat(result).isNotInstanceOf(java.util.Collection.class);
- }
- }
-
- @Test
- public void testToJSONString_withIgnoreAutoTypeAndPrettyPrint() {
- TestObject obj = new TestObject("noType", 111);
-
- String jsonIgnorePretty = jsonSerializer.toJSONString(obj, true, true);
- assertThat(jsonIgnorePretty).contains("\n");
- assertThat(jsonIgnorePretty).doesNotContain("@type");
-
- String jsonIgnoreNormal = jsonSerializer.toJSONString(obj, true, false);
- assertThat(jsonIgnoreNormal).doesNotContain("\n");
- assertThat(jsonIgnoreNormal).doesNotContain("@type");
-
- String jsonNoIgnorePretty = jsonSerializer.toJSONString(obj, false, true);
- assertThat(jsonNoIgnorePretty).contains("\n");
- assertThat(jsonNoIgnorePretty).contains("@type");
-
- String jsonNoIgnoreNormal = jsonSerializer.toJSONString(obj, false, false);
- assertThat(jsonNoIgnoreNormal).doesNotContain("\n");
- assertThat(jsonNoIgnoreNormal).contains("@type");
- }
-
- @Test
- public void testUseAutoType() {
- String jsonWithAutoType = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- assertThat(jsonSerializer.useAutoType(jsonWithAutoType)).isTrue();
-
- String jsonWithoutAutoType = "{\"name\":\"test\"}";
- assertThat(jsonSerializer.useAutoType(jsonWithoutAutoType)).isFalse();
-
- String jsonWithTypeInValue = "{\"comment\":\"this has @type in it\"}";
- assertThat(jsonSerializer.useAutoType(jsonWithTypeInValue)).isFalse();
-
- assertThat(jsonSerializer.useAutoType(null)).isFalse();
-
- assertThat(jsonSerializer.useAutoType("")).isFalse();
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public TestObject(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
deleted file mode 100644
index fc792c4ad0e..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonAllowlistTest.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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.common.json;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for FastJSON serializer with allowlist security check
- */
-public class FastjsonAllowlistTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson");
- }
-
- @AfterEach
- void tearDown() {
- JsonAllowlistManager.getInstance().clearUserAllowlist();
- }
-
- @Test
- public void testParseObject_allowedSeataClass() {
-
- String json =
- "{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
-
- AllowedTestClass result = jsonSerializer.parseObject(json, AllowedTestClass.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_allowedJavaClass() {
-
- String json = "{\"@type\":\"java.util.HashMap\"}";
-
- Object result = jsonSerializer.parseObject(json, Object.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_notAllowedClass() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, Object.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("not in JSON deserialization allowlist")
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_userAllowedClass() {
-
- JsonAllowlistManager.getInstance().addUserClass("com.example.UserClass");
-
- String json = "{\"@type\":\"com.example.UserClass\",\"data\":\"test\"}";
-
- Assertions.assertDoesNotThrow(() -> jsonSerializer.parseObject(json, Object.class, false));
- }
-
- @Test
- public void testParseObject_userAllowedPrefix() {
- JsonAllowlistManager.getInstance().addUserPrefix("com.mycompany.model.");
-
- String json = "{\"@type\":\"com.mycompany.model.User\",\"id\":1}";
-
- Assertions.assertDoesNotThrow(() -> jsonSerializer.parseObject(json, Object.class, false));
- }
-
- @Test
- public void testParseObject_ignoreAutoType_bypasses_check() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- try {
- jsonSerializer.parseObject(json, Object.class, true);
- } catch (SecurityException e) {
- throw new AssertionError("Should not throw SecurityException when ignoreAutoType=true", e);
- } catch (Exception e) {
-
- assertThat(e).isNotInstanceOf(SecurityException.class);
- }
- }
-
- @Test
- public void testParseObject_noAutoType_bypasses_check() {
-
- String json = "{\"name\":\"test\",\"value\":123}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_multipleAutoTypes() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
-
- ContainerClass result = jsonSerializer.parseObject(json, ContainerClass.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_multipleAutoTypes_oneNotAllowed() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.FastjsonAllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"com.malicious.EvilClass\",\"name\":\"evil\"}}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, ContainerClass.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_atTypeInStringValue_notBlocked() {
- // @type appearing inside a string value should not be treated as AutoType metadata
- String json = "{\"description\":\"the \\\"@type\\\" field is important\",\"name\":\"test\"}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testLoadUserAllowlist_thenParse() {
- JsonAllowlistManager.getInstance().loadUserAllowlist("com.trusted.model.,com.trusted.dto.SpecificDTO");
-
- String json1 = "{\"@type\":\"com.trusted.model.User\",\"id\":1}";
- try {
- jsonSerializer.parseObject(json1, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json2 = "{\"@type\":\"com.trusted.dto.SpecificDTO\",\"data\":\"test\"}";
- try {
- jsonSerializer.parseObject(json2, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json3 = "{\"@type\":\"com.untrusted.EvilClass\",\"data\":\"evil\"}";
- assertThatThrownBy(() -> jsonSerializer.parseObject(json3, Object.class, false))
- .isInstanceOf(SecurityException.class);
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-
- public static class AllowedTestClass {
- private String name;
-
- public AllowedTestClass() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
-
- public static class ContainerClass {
- private AllowedTestClass inner;
-
- public ContainerClass() {}
-
- public AllowedTestClass getInner() {
- return inner;
- }
-
- public void setInner(AllowedTestClass inner) {
- this.inner = inner;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
deleted file mode 100644
index 15f752fb35f..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/FastjsonJsonSerializerTest.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * 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.common.json;
-
-import com.alibaba.fastjson.TypeReference;
-import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.FastjsonJsonSerializer;
-import org.apache.seata.common.json.impl.JacksonJsonSerializer;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class FastjsonJsonSerializerTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- // Use factory to get FastJSON serializer by name
- jsonSerializer = JsonSerializerFactory.getSerializer("fastjson");
- }
-
- @Test
- public void testToJSONString_basicObject() {
- TestObject obj = new TestObject("test", 123);
- String json = jsonSerializer.toJSONString(obj);
-
- assertThat(json).contains("\"name\":\"test\"");
- assertThat(json).contains("\"value\":123");
- }
-
- @Test
- public void testParseObject_basicObject() {
- String json = "{\"name\":\"test\",\"value\":123}";
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
- }
-
- @Test
- public void testToJSONString_and_parseObject() {
- TestObject original = new TestObject("school", 456);
- String json = jsonSerializer.toJSONString(original);
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(restored.getName()).isEqualTo(original.getName());
- assertThat(restored.getValue()).isEqualTo(original.getValue());
- }
-
- @Test
- public void testUseAutoType_withType() {
- String json = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isTrue();
- }
-
- @Test
- public void testUseAutoType_withoutType() {
- String json = "{\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testUseAutoType_typeInValue() {
- String json = "{\"comment\":\"this has @type in it\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testToJSONString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, true);
-
- assertThat(prettyJson).contains("\n");
- assertThat(prettyJson).contains("\t");
- }
-
- @Test
- public void testToJSONString_ignoreAutoType() {
- TestObject obj = new TestObject("noType", 111);
- String jsonWithoutType = jsonSerializer.toJSONString(obj, true, true);
-
- assertThat(jsonWithoutType).doesNotContain("@type");
- }
-
- @Test
- public void testParseObject_ignoreAutoType() {
- String json = jsonSerializer.toJSONString(new TestObject("ignored", 222));
-
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class, true);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("ignored");
- assertThat(obj.getValue()).isEqualTo(222);
- }
-
- @Test
- public void testEmptyList_serialization() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testEmptyList_deserialization() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testNullInput_toJSONString() {
- String json = jsonSerializer.toJSONString(null);
- assertThat(json).isEqualTo("null");
- }
-
- @Test
- public void testNullInput_parseObject() {
- TestObject obj = jsonSerializer.parseObject(null, TestObject.class);
- assertThat(obj).isNull();
-
- TestObject obj2 = jsonSerializer.parseObject("{}", null);
- assertThat(obj2).isNull();
- }
-
- @Test
- public void testParseObject_invalidJson() {
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("FastJSON deserialize error");
- }
-
- @Test
- public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("fastjson");
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(FastjsonJsonSerializer.class);
- }
-
- @Test
- public void testFactoryReturnsDefaultInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testToJSONString_emptyList() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testToJSONString_withAutoType() {
- TestObject obj = new TestObject("withType", 789);
- String jsonWithAutoType = jsonSerializer.toJSONString(obj, false, false);
-
- assertThat(jsonWithAutoType).contains("@type");
- }
-
- @Test
- public void testParseObject_nullJson() {
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
- }
-
- @Test
- public void testParseObject_emptyList() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testParseObject_withAutoType() {
- TestObject original = new TestObject("autoTypeTest", 999);
- String jsonWithAutoType = jsonSerializer.toJSONString(original, false, false);
-
- TestObject restored = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("autoTypeTest");
- assertThat(restored.getValue()).isEqualTo(999);
- }
-
- @Test
- public void testParseObject_withType() {
-
- String json = "{\"name\":\"test\",\"value\":123}";
- Type type = new TypeReference() {}.getType();
-
- TestObject obj = jsonSerializer.parseObjectWithType(json, type);
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
-
- String listJson = "[{\"name\":\"item1\",\"value\":1},{\"name\":\"item2\",\"value\":2}]";
- Type listType = new TypeReference>() {}.getType();
-
- List list = jsonSerializer.parseObjectWithType(listJson, listType);
- assertThat(list).hasSize(2);
- assertThat(list.get(0).getName()).isEqualTo("item1");
- assertThat(list.get(1).getValue()).isEqualTo(2);
- }
-
- @Test
- public void testParseObject_withIgnoreAutoType() {
-
- String jsonWithAutoType = jsonSerializer.toJSONString(new TestObject("ignored", 222));
-
- TestObject objIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, true);
- assertThat(objIgnore).isNotNull();
- assertThat(objIgnore.getName()).isEqualTo("ignored");
- assertThat(objIgnore.getValue()).isEqualTo(222);
-
- TestObject objNoIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
- assertThat(objNoIgnore).isNotNull();
- assertThat(objNoIgnore.getName()).isEqualTo("ignored");
- assertThat(objNoIgnore.getValue()).isEqualTo(222);
-
- List> emptyListResult = jsonSerializer.parseObject("", List.class, false);
- assertThat(emptyListResult).isNull();
-
- List> emptyList = jsonSerializer.parseObject("[]", List.class, false);
- assertThat(emptyList).isEmpty();
-
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
-
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class, false))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("FastJSON deserialize error");
- }
-
- /**
- * The "[]" shortcut in parseObject(String, Class, boolean) must only apply when the
- * target type is a Collection. Otherwise it would silently return an empty ArrayList
- * cast to T, causing a ClassCastException at the call site. The exact behaviour of the
- * underlying library when asked to map "[]" to a POJO may vary (return null, return an
- * empty POJO, or throw); the only requirement enforced here is that the result is never
- * an ArrayList.
- */
- @Test
- public void testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
- assertEmptyArrayDoesNotProduceCollection(true);
- assertEmptyArrayDoesNotProduceCollection(false);
- }
-
- private void assertEmptyArrayDoesNotProduceCollection(boolean ignoreAutoType) {
- Object result;
- try {
- result = jsonSerializer.parseObject("[]", TestObject.class, ignoreAutoType);
- } catch (JsonParseException ignored) {
- // throwing is also an acceptable outcome
- return;
- }
- if (result != null) {
- assertThat(result).isNotInstanceOf(java.util.Collection.class);
- }
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public TestObject(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
deleted file mode 100644
index ed2419912bd..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/GsonJsonSerializerTest.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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.common.json;
-
-import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.GsonJsonSerializer;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class GsonJsonSerializerTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- // Use factory to get Gson serializer by name
- jsonSerializer = JsonSerializerFactory.getSerializer("gson");
- }
-
- @Test
- public void testToJSONString_basicObject() {
- TestObject obj = new TestObject("test", 123);
- String json = jsonSerializer.toJSONString(obj);
-
- assertThat(json).contains("\"name\":\"test\"");
- assertThat(json).contains("\"value\":123");
- assertThat(json).doesNotContain("@type");
- }
-
- @Test
- public void testParseObject_basicObject() {
- String json = "{\"name\":\"test\",\"value\":123}";
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
- }
-
- @Test
- public void testToJSONString_and_parseObject() {
- TestObject original = new TestObject("school", 456);
- String json = jsonSerializer.toJSONString(original);
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(restored.getName()).isEqualTo(original.getName());
- assertThat(restored.getValue()).isEqualTo(original.getValue());
- }
-
- @Test
- public void testUseAutoType_withType() {
- String json = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testUseAutoType_withoutType() {
- String json = "{\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testToJSONString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, true);
-
- assertThat(prettyJson).contains("\n");
- assertThat(prettyJson).contains(" \"");
- }
-
- @Test
- public void testToJSONString_ignoreAutoType() {
- TestObject obj = new TestObject("noType", 111);
- String jsonWithoutType = jsonSerializer.toJSONString(obj, true, true);
-
- assertThat(jsonWithoutType).doesNotContain("@type");
- }
-
- @Test
- public void testParseObject_ignoreAutoType() {
- TestObject obj = new TestObject("ignored", 222);
- String json = jsonSerializer.toJSONString(obj);
-
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class, true);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("ignored");
- assertThat(restored.getValue()).isEqualTo(222);
- }
-
- @Test
- public void testEmptyList_serialization() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testEmptyList_deserialization() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testNullInput_toJSONString() {
- String json = jsonSerializer.toJSONString(null);
- assertThat(json).isEqualTo("null");
- }
-
- @Test
- public void testNullInput_parseObject() {
- TestObject obj = jsonSerializer.parseObject(null, TestObject.class);
- assertThat(obj).isNull();
-
- TestObject obj2 = jsonSerializer.parseObject("{}", null);
- assertThat(obj2).isNull();
- }
-
- @Test
- public void testParseObject_invalidJson() {
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Gson deserialize error");
- }
-
- @Test
- public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("gson");
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(GsonJsonSerializer.class);
- }
-
- @Test
- public void testParseObject_nullText() {
- assertThat(jsonSerializer.parseObject(null, String.class)).isNull();
- }
-
- @Test
- public void testToJSONString_emptyList() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testToJSONString_withAutoType() {
- TestObject obj = new TestObject("withType", 789);
- String jsonWithAutoType = jsonSerializer.toJSONString(obj, false, false);
-
- assertThat(jsonWithAutoType).doesNotContain("@type");
- }
-
- @Test
- public void testToJsonString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, false, true);
-
- // Pretty JSON should contain newlines and indentation
- assertThat(prettyJson).contains("\n");
- }
-
- @Test
- public void testParseObject_nullJson() {
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
- }
-
- @Test
- public void testParseObject_emptyList() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- /**
- * The "[]" shortcut in parseObject(String, Class, boolean) must only apply when the
- * target type is a Collection. Otherwise it would silently return an empty ArrayList
- * cast to T, causing a ClassCastException at the call site. The exact behaviour of the
- * underlying library when asked to map "[]" to a POJO may vary (return null, return an
- * empty POJO, or throw); the only requirement enforced here is that the result is never
- * an ArrayList.
- */
- @Test
- public void testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
- assertEmptyArrayDoesNotProduceCollection(true);
- assertEmptyArrayDoesNotProduceCollection(false);
- }
-
- private void assertEmptyArrayDoesNotProduceCollection(boolean ignoreAutoType) {
- Object result;
- try {
- result = jsonSerializer.parseObject("[]", TestObject.class, ignoreAutoType);
- } catch (JsonParseException ignored) {
- // throwing is also an acceptable outcome
- return;
- }
- if (result != null) {
- assertThat(result).isNotInstanceOf(java.util.Collection.class);
- }
- }
-
- @Test
- public void testParseObject_withAutoType() {
- TestObject original = new TestObject("autoTypeTest", 999);
- String jsonWithAutoType = jsonSerializer.toJSONString(original, false, false);
-
- TestObject restored = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("autoTypeTest");
- assertThat(restored.getValue()).isEqualTo(999);
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {
- // Default constructor required for Gson
- }
-
- public TestObject(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
deleted file mode 100644
index 522b301a08c..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonAllowlistTest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * 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.common.json;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for Jackson serializer with allowlist security check
- */
-public class JacksonAllowlistTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- jsonSerializer = JsonSerializerFactory.getSerializer("jackson");
- }
-
- @AfterEach
- void tearDown() {
- JsonAllowlistManager.getInstance().clearUserAllowlist();
- }
-
- @Test
- public void testParseObject_allowedSeataClass() {
-
- String json =
- "{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$AllowedTestClass\",\"name\":\"test\"}";
-
- AllowedTestClass result = jsonSerializer.parseObject(json, AllowedTestClass.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_allowedJavaClass() {
-
- String json = "{\"@type\":\"java.util.HashMap\"}";
-
- Object result = jsonSerializer.parseObject(json, Object.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_notAllowedClass() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, Object.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("not in JSON deserialization allowlist")
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_userAllowedClass() {
-
- JsonAllowlistManager.getInstance().addUserClass("com.example.UserClass");
-
- String json = "{\"@type\":\"com.example.UserClass\",\"data\":\"test\"}";
-
- try {
- jsonSerializer.parseObject(json, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
- assertThat(e).isNotInstanceOf(SecurityException.class);
- }
- }
-
- @Test
- public void testParseObject_userAllowedPrefix() {
- JsonAllowlistManager.getInstance().addUserPrefix("com.mycompany.model.");
-
- String json = "{\"@type\":\"com.mycompany.model.User\",\"id\":1}";
-
- try {
- jsonSerializer.parseObject(json, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- assertThat(e).isNotInstanceOf(SecurityException.class);
- }
- }
-
- @Test
- public void testParseObject_ignoreAutoType_bypasses_check() {
-
- String json = "{\"@type\":\"com.malicious.EvilClass\",\"command\":\"rm -rf /\"}";
-
- try {
- jsonSerializer.parseObject(json, Object.class, true);
- } catch (SecurityException e) {
- throw new AssertionError("Should not throw SecurityException when ignoreAutoType=true", e);
- } catch (Exception e) {
-
- assertThat(e).isNotInstanceOf(SecurityException.class);
- }
- }
-
- @Test
- public void testParseObject_noAutoType_bypasses_check() {
- // Jackson's objectMapperWithAutoType requires @type for non-final types,
- // so use the 2-arg parseObject (defaultObjectMapper, no AutoType) to verify
- // that normal JSON without @type does not trigger any SecurityException.
- String json = "{\"name\":\"test\",\"value\":123}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("test");
- }
-
- @Test
- public void testParseObject_multipleAutoTypes() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$AllowedTestClass\",\"name\":\"nested\"}}";
-
- ContainerClass result = jsonSerializer.parseObject(json, ContainerClass.class, false);
-
- assertThat(result).isNotNull();
- }
-
- @Test
- public void testParseObject_multipleAutoTypes_oneNotAllowed() {
-
- String json = "{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$ContainerClass\","
- + "\"inner\":{\"@type\":\"com.malicious.EvilClass\",\"name\":\"evil\"}}";
-
- assertThatThrownBy(() -> jsonSerializer.parseObject(json, ContainerClass.class, false))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("com.malicious.EvilClass");
- }
-
- @Test
- public void testParseObject_atTypeInStringValue_notBlocked() {
- // @type appearing inside a string value should not be treated as AutoType metadata.
- // The JSON has a real @type for the root object (required by Jackson's DefaultTyping),
- // and a fake @type inside a string value which should not be flagged.
- String json = "{\"@type\":\"org.apache.seata.common.json.JacksonAllowlistTest$TestObject\","
- + "\"name\":\"the \\\"@type\\\" field is important\",\"value\":123}";
-
- TestObject result = jsonSerializer.parseObject(json, TestObject.class, false);
-
- assertThat(result).isNotNull();
- assertThat(result.getName()).isEqualTo("the \"@type\" field is important");
- }
-
- @Test
- public void testLoadUserAllowlist_thenParse() {
- JsonAllowlistManager.getInstance().loadUserAllowlist("com.trusted.model.,com.trusted.dto.SpecificDTO");
-
- String json1 = "{\"@type\":\"com.trusted.model.User\",\"id\":1}";
- try {
- jsonSerializer.parseObject(json1, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json2 = "{\"@type\":\"com.trusted.dto.SpecificDTO\",\"data\":\"test\"}";
- try {
- jsonSerializer.parseObject(json2, Object.class, false);
- } catch (SecurityException e) {
- throw e;
- } catch (Exception e) {
-
- }
-
- String json3 = "{\"@type\":\"com.untrusted.EvilClass\",\"data\":\"evil\"}";
- assertThatThrownBy(() -> jsonSerializer.parseObject(json3, Object.class, false))
- .isInstanceOf(SecurityException.class);
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-
- public static class AllowedTestClass {
- private String name;
-
- public AllowedTestClass() {}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
- }
-
- public static class ContainerClass {
- private AllowedTestClass inner;
-
- public ContainerClass() {}
-
- public AllowedTestClass getInner() {
- return inner;
- }
-
- public void setInner(AllowedTestClass inner) {
- this.inner = inner;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
deleted file mode 100644
index 1433fb0ca2d..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JacksonJsonSerializerTest.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * 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.common.json;
-
-import com.alibaba.fastjson.TypeReference;
-import org.apache.seata.common.exception.JsonParseException;
-import org.apache.seata.common.json.impl.JacksonJsonSerializer;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class JacksonJsonSerializerTest {
-
- private JsonSerializer jsonSerializer;
-
- @BeforeEach
- void setUp() {
- // Use factory to get Jackson serializer by name
- jsonSerializer = JsonSerializerFactory.getSerializer("jackson");
- }
-
- @Test
- public void testToJSONString_basicObject() {
- TestObject obj = new TestObject("test", 123);
- String json = jsonSerializer.toJSONString(obj);
-
- assertThat(json).contains("\"name\":\"test\"");
- assertThat(json).contains("\"value\":123");
- }
-
- @Test
- public void testParseObject_basicObject() {
- String json =
- "{\"@class\":\"org.apache.seata.common.json.JacksonJsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
- TestObject obj = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
- }
-
- @Test
- public void testToJSONString_and_parseObject() {
- TestObject original = new TestObject("school", 456);
- String json = jsonSerializer.toJSONString(original);
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class);
-
- assertThat(restored.getName()).isEqualTo(original.getName());
- assertThat(restored.getValue()).isEqualTo(original.getValue());
- }
-
- @Test
- public void testUseAutoType_withType() {
- String json = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isTrue();
- }
-
- @Test
- public void testUseAutoType_withoutType() {
- String json = "{\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testUseAutoType_typeInValue() {
- String json = "{\"comment\":\"this has @type in it\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(json);
- assertThat(hasAutoType).isFalse();
- }
-
- @Test
- public void testToJSONString_withAutoType() {
- TestObject obj = new TestObject("withType", 789);
- String jsonWithAutoType = jsonSerializer.toJSONString(obj, false, false);
-
- assertThat(jsonWithAutoType).isNotNull();
- assertThat(jsonWithAutoType).contains("@type");
- assertThat(jsonWithAutoType).contains("\"name\":\"withType\"");
- assertThat(jsonWithAutoType).contains("\"value\":789");
- }
-
- @Test
- public void testParseObject_withAutoType() {
- TestObject original = new TestObject("autoTypeTest", 999);
- // Serialize with autoType enabled
- String jsonWithAutoType = jsonSerializer.toJSONString(original, false, false);
-
- // Deserialize with autoType enabled
- TestObject restored = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("autoTypeTest");
- assertThat(restored.getValue()).isEqualTo(999);
- }
-
- @Test
- public void testEmptyList_serialization() {
- List emptyList = new ArrayList<>();
- String json = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(json).isEqualTo("[]");
- }
-
- @Test
- public void testEmptyList_deserialization() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testNullInput_toJSONString() {
- String json = jsonSerializer.toJSONString(null);
- assertThat(json).isEqualTo("null");
- }
-
- @Test
- public void testNullInput_parseObject() {
- TestObject obj = jsonSerializer.parseObject(null, TestObject.class);
- assertThat(obj).isNull();
-
- TestObject obj2 = jsonSerializer.parseObject("{}", null);
- assertThat(obj2).isNull();
- }
-
- @Test
- public void testParseObject_invalidJson() {
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
- }
-
- @Test
- public void testFactoryReturnsCorrectInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("jackson");
- assertThat(serializer).isNotNull();
- assertThat(serializer).isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testFactoryReturnsDefaultInstance() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
- assertThat(serializer).isNotNull();
- }
-
- @Test
- public void testToJSONString_throwsException() {
- Object unserializable = new Object() {
- private final java.io.InputStream stream = System.in;
- };
-
- assertThatThrownBy(() -> jsonSerializer.toJSONString(unserializable))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson serialize error");
- }
-
- @Test
- public void testParseObject_nullText() {
- assertThat(jsonSerializer.parseObject(null, String.class)).isNull();
- }
-
- @Test
- public void testToJSONString_prettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
- String prettyJson = jsonSerializer.toJSONString(obj, true);
-
- // Pretty JSON should contain newlines and indentation
- assertThat(prettyJson).contains("\n");
- }
-
- @Test
- public void testParseObject_nullJson() {
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
- }
-
- @Test
- public void testParseObject_emptyList() {
- String json = "[]";
- List> list = jsonSerializer.parseObject(json, List.class, false);
- assertThat(list).isEmpty();
- }
-
- @Test
- public void testParseObject_ignoreAutoType() {
- TestObject obj = new TestObject("ignored", 222);
- String json = jsonSerializer.toJSONString(obj);
-
- TestObject restored = jsonSerializer.parseObject(json, TestObject.class, true);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("ignored");
- assertThat(restored.getValue()).isEqualTo(222);
- }
-
- @Test
- public void testParseObject_withType() {
- String json =
- "{\"@type\":\"org.apache.seata.common.json.JacksonJsonSerializerTest$TestObject\",\"name\":\"test\",\"value\":123}";
- Type type = new TypeReference() {}.getType();
-
- TestObject obj = jsonSerializer.parseObjectWithType(json, type);
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
-
- assertThatThrownBy(() -> jsonSerializer.parseObjectWithType("{invalid json}", type))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
- }
-
- @Test
- public void testUseAutoType() {
- String jsonWithAutoType = "{\"@type\":\"some.type\",\"name\":\"test\"}";
- boolean hasAutoType = jsonSerializer.useAutoType(jsonWithAutoType);
- assertThat(hasAutoType).isTrue();
-
- String jsonWithoutAutoType = "{\"name\":\"test\"}";
- boolean noAutoType = jsonSerializer.useAutoType(jsonWithoutAutoType);
- assertThat(noAutoType).isFalse();
-
- String jsonWithTypeInValue = "{\"comment\":\"this has @type in it\"}";
- boolean typeInValue = jsonSerializer.useAutoType(jsonWithTypeInValue);
- assertThat(typeInValue).isFalse();
-
- boolean nullAutoType = jsonSerializer.useAutoType(null);
- assertThat(nullAutoType).isFalse();
-
- boolean emptyAutoType = jsonSerializer.useAutoType("");
- assertThat(emptyAutoType).isFalse();
- }
-
- @Test
- public void testToJSONString_withPrettyPrint() {
- TestObject obj = new TestObject("pretty", 789);
-
- String prettyJson = jsonSerializer.toJSONString(obj, true);
- assertThat(prettyJson).contains("\n");
- assertThat(prettyJson).contains("@type");
-
- String normalJson = jsonSerializer.toJSONString(obj, false);
- assertThat(normalJson).doesNotContain("\n");
- assertThat(normalJson).contains("@type");
- }
-
- @Test
- public void testToJSONString_withIgnoreAutoTypeAndPrettyPrint() {
- TestObject obj = new TestObject("noType", 111);
-
- String jsonIgnorePretty = jsonSerializer.toJSONString(obj, true, true);
- assertThat(jsonIgnorePretty).contains("\n");
- assertThat(jsonIgnorePretty).doesNotContain("@type");
-
- String jsonIgnoreNormal = jsonSerializer.toJSONString(obj, true, false);
- assertThat(jsonIgnoreNormal).doesNotContain("\n");
- assertThat(jsonIgnoreNormal).doesNotContain("@type");
-
- String jsonNoIgnorePretty = jsonSerializer.toJSONString(obj, false, true);
- assertThat(jsonNoIgnorePretty).contains("\n");
- assertThat(jsonNoIgnorePretty).contains("@type");
-
- String jsonNoIgnoreNormal = jsonSerializer.toJSONString(obj, false, false);
- assertThat(jsonNoIgnoreNormal).doesNotContain("\n");
- assertThat(jsonNoIgnoreNormal).contains("@type");
-
- List emptyList = new ArrayList<>();
- String emptyListJson = jsonSerializer.toJSONString(emptyList, false, false);
- assertThat(emptyListJson).isEqualTo("[]");
-
- Object invalidObject = new Object() {
- private final java.io.InputStream stream = System.in;
- };
-
- assertThatThrownBy(() -> jsonSerializer.toJSONString(invalidObject, false, false))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson serialize error");
- }
-
- /**
- * The "[]" shortcut in parseObject(String, Class, boolean) must only apply when the
- * target type is a Collection. Otherwise it would silently return an empty ArrayList
- * cast to T, causing a ClassCastException at the call site. The exact behaviour of the
- * underlying library when asked to map "[]" to a POJO may vary (return null, return an
- * empty POJO, or throw); the only requirement enforced here is that the result is never
- * an ArrayList.
- */
- @Test
- public void testParseObject_emptyArrayJson_nonCollectionType_doesNotReturnArrayList() {
- assertEmptyArrayDoesNotProduceCollection(true);
- assertEmptyArrayDoesNotProduceCollection(false);
- }
-
- private void assertEmptyArrayDoesNotProduceCollection(boolean ignoreAutoType) {
- Object result;
- try {
- result = jsonSerializer.parseObject("[]", TestObject.class, ignoreAutoType);
- } catch (JsonParseException ignored) {
- // throwing is also an acceptable outcome
- return;
- }
- if (result != null) {
- assertThat(result).isNotInstanceOf(java.util.Collection.class);
- }
- }
-
- @Test
- public void testParseObject_withIgnoreAutoType() {
- String jsonWithAutoType = jsonSerializer.toJSONString(new TestObject("ignored", 222), false, false);
-
- TestObject objIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, true);
- assertThat(objIgnore).isNotNull();
- assertThat(objIgnore.getName()).isEqualTo("ignored");
- assertThat(objIgnore.getValue()).isEqualTo(222);
-
- TestObject objNoIgnore = jsonSerializer.parseObject(jsonWithAutoType, TestObject.class, false);
- assertThat(objNoIgnore).isNotNull();
- assertThat(objNoIgnore.getName()).isEqualTo("ignored");
- assertThat(objNoIgnore.getValue()).isEqualTo(222);
-
- List> emptyList = jsonSerializer.parseObject("[]", List.class, false);
- assertThat(emptyList).isEmpty();
-
- List> emptyListIgnore = jsonSerializer.parseObject("[]", List.class, true);
- assertThat(emptyListIgnore).isEmpty();
-
- assertThat(jsonSerializer.parseObject(null, TestObject.class, false)).isNull();
-
- assertThatThrownBy(() -> jsonSerializer.parseObject("{invalid json}", TestObject.class, false))
- .isInstanceOf(JsonParseException.class)
- .hasMessageContaining("Jackson deserialize error");
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public TestObject(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
deleted file mode 100644
index c33425308ba..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonAllowlistManagerTest.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * 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.common.json;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-/**
- * Tests for {@link JsonAllowlistManager}
- */
-public class JsonAllowlistManagerTest {
-
- @AfterEach
- void tearDown() {
-
- JsonAllowlistManager.getInstance().clearUserAllowlist();
- }
-
- @Test
- public void testBuiltinAllowlist_primitiveWrappers() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("java.lang.String")).isTrue();
- assertThat(manager.isAllowed("java.lang.Integer")).isTrue();
- assertThat(manager.isAllowed("java.lang.Long")).isTrue();
- assertThat(manager.isAllowed("java.lang.Boolean")).isTrue();
- assertThat(manager.isAllowed("java.lang.Double")).isTrue();
- assertThat(manager.isAllowed("java.lang.Float")).isTrue();
- assertThat(manager.isAllowed("java.lang.Byte")).isTrue();
- assertThat(manager.isAllowed("java.lang.Short")).isTrue();
- assertThat(manager.isAllowed("java.lang.Character")).isTrue();
- assertThat(manager.isAllowed("java.lang.Number")).isTrue();
- assertThat(manager.isAllowed("java.math.BigDecimal")).isTrue();
- assertThat(manager.isAllowed("java.math.BigInteger")).isTrue();
- }
-
- @Test
- public void testBuiltinAllowlist_arrays() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- // 1D primitive arrays
- assertThat(manager.isAllowed("[B")).isTrue();
- assertThat(manager.isAllowed("[I")).isTrue();
- assertThat(manager.isAllowed("[J")).isTrue();
- assertThat(manager.isAllowed("[Z")).isTrue();
- assertThat(manager.isAllowed("[C")).isTrue();
- assertThat(manager.isAllowed("[S")).isTrue();
- assertThat(manager.isAllowed("[F")).isTrue();
- assertThat(manager.isAllowed("[D")).isTrue();
-
- // Multi-dimensional primitive arrays
- assertThat(manager.isAllowed("[[I")).isTrue();
- assertThat(manager.isAllowed("[[Z")).isTrue();
- assertThat(manager.isAllowed("[[B")).isTrue();
- assertThat(manager.isAllowed("[[J")).isTrue();
- assertThat(manager.isAllowed("[[[D")).isTrue();
- assertThat(manager.isAllowed("[[[F")).isTrue();
-
- // Object arrays
- assertThat(manager.isAllowed("[Ljava.lang.String;")).isTrue();
- assertThat(manager.isAllowed("[Ljava.lang.Object;")).isTrue();
- }
-
- @Test
- public void testBuiltinAllowlist_dateTime() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("java.util.Date")).isTrue();
- assertThat(manager.isAllowed("java.sql.Timestamp")).isTrue();
- assertThat(manager.isAllowed("java.time.LocalDateTime")).isTrue();
- assertThat(manager.isAllowed("java.time.LocalDate")).isTrue();
- assertThat(manager.isAllowed("java.time.Instant")).isTrue();
- assertThat(manager.isAllowed("java.time.ZonedDateTime")).isTrue();
- }
-
- @Test
- public void testBuiltinAllowlist_collections() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("java.util.ArrayList")).isTrue();
- assertThat(manager.isAllowed("java.util.LinkedList")).isTrue();
- assertThat(manager.isAllowed("java.util.HashMap")).isTrue();
- assertThat(manager.isAllowed("java.util.LinkedHashMap")).isTrue();
- assertThat(manager.isAllowed("java.util.HashSet")).isTrue();
- assertThat(manager.isAllowed("java.util.TreeMap")).isTrue();
- assertThat(manager.isAllowed("java.util.concurrent.ConcurrentHashMap")).isTrue();
- }
-
- @Test
- public void testBuiltinAllowlist_seataPrefix() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("org.apache.seata.core.model.BranchType")).isTrue();
- assertThat(manager.isAllowed("io.seata.saga.engine.mock.DemoService$People"))
- .isTrue();
- assertThat(manager.isAllowed("org.apache.seata.rm.datasource.undo.UndoLogParser"))
- .isTrue();
- assertThat(manager.isAllowed("org.apache.seata.common.json.JsonAllowlistManager"))
- .isTrue();
- }
-
- @Test
- public void testBuiltinAllowlist_objectArrayDescriptorsByPrefix() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("[Lorg.apache.seata.common.json.JsonAllowlistManager;"))
- .isTrue();
- assertThat(manager.isAllowed("[Lio.seata.saga.engine.mock.DemoService$People;"))
- .isTrue();
- assertThat(manager.isAllowed("[[Lio.seata.saga.engine.mock.DemoService$People;"))
- .isTrue();
- assertThat(manager.isAllowed("[Lcom.malicious.EvilClass;")).isFalse();
- }
-
- @Test
- public void testBuiltinAllowlist_objectArrayCanonicalNameByPrefix() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("io.seata.saga.engine.mock.DemoService$People[]"))
- .isTrue();
- assertThat(manager.isAllowed("io.seata.saga.engine.mock.DemoService$People[][]"))
- .isTrue();
- assertThat(manager.isAllowed("com.malicious.EvilClass[]")).isFalse();
- }
-
- @Test
- public void testBuiltinAllowlist_notAllowed() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed("com.sun.rowset.JdbcRowSetImpl")).isFalse();
- assertThat(manager.isAllowed("java.lang.Runtime")).isFalse();
- assertThat(manager.isAllowed("java.lang.ProcessBuilder")).isFalse();
- assertThat(manager.isAllowed("javax.naming.InitialContext")).isFalse();
- assertThat(manager.isAllowed("com.example.MaliciousClass")).isFalse();
- }
-
- @Test
- public void testLoadUserAllowlist_exactMatch() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.example.MyClass,com.example.AnotherClass");
-
- assertThat(manager.isAllowed("com.example.MyClass")).isTrue();
- assertThat(manager.isAllowed("com.example.AnotherClass")).isTrue();
- assertThat(manager.isAllowed("com.example.NotInList")).isFalse();
- }
-
- @Test
- public void testLoadUserAllowlist_prefixMatch() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.company.model.,com.company.dto.");
-
- assertThat(manager.isAllowed("com.company.model.User")).isTrue();
- assertThat(manager.isAllowed("com.company.model.Order")).isTrue();
- assertThat(manager.isAllowed("com.company.dto.UserDTO")).isTrue();
- assertThat(manager.isAllowed("com.company.service.UserService")).isFalse();
- }
-
- @Test
- public void testLoadUserAllowlist_mixedMatch() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.company.model.,com.thirdparty.SpecificClass");
-
- assertThat(manager.isAllowed("com.company.model.User")).isTrue();
- assertThat(manager.isAllowed("com.company.model.sub.NestedClass")).isTrue();
- assertThat(manager.isAllowed("com.thirdparty.SpecificClass")).isTrue();
- assertThat(manager.isAllowed("com.thirdparty.OtherClass")).isFalse();
- }
-
- @Test
- public void testLoadUserAllowlist_withSpaces() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist(" com.example.Class1 , com.example.Class2 ");
-
- assertThat(manager.isAllowed("com.example.Class1")).isTrue();
- assertThat(manager.isAllowed("com.example.Class2")).isTrue();
- }
-
- @Test
- public void testLoadUserAllowlist_emptyEntries() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.example.Class1,,com.example.Class2,");
-
- assertThat(manager.isAllowed("com.example.Class1")).isTrue();
- assertThat(manager.isAllowed("com.example.Class2")).isTrue();
- }
-
- @Test
- public void testLoadUserAllowlist_nullOrEmpty() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist(null);
- manager.loadUserAllowlist("");
-
- assertThat(manager.isAllowed("java.lang.String")).isTrue();
- }
-
- @Test
- public void testAddUserClass() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.addUserClass("com.example.DynamicClass");
-
- assertThat(manager.isAllowed("com.example.DynamicClass")).isTrue();
- }
-
- @Test
- public void testAddUserPrefix() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.addUserPrefix("com.dynamic.pkg.");
-
- assertThat(manager.isAllowed("com.dynamic.pkg.Class1")).isTrue();
- assertThat(manager.isAllowed("com.dynamic.pkg.sub.Class2")).isTrue();
- }
-
- @Test
- public void testClearUserAllowlist() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.example.ToBeCleared");
- assertThat(manager.isAllowed("com.example.ToBeCleared")).isTrue();
-
- manager.clearUserAllowlist();
- assertThat(manager.isAllowed("com.example.ToBeCleared")).isFalse();
-
- assertThat(manager.isAllowed("java.lang.String")).isTrue();
- }
-
- @Test
- public void testCheckClass_allowed() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.checkClass("java.lang.String");
- manager.checkClass("java.util.ArrayList");
- manager.checkClass("org.apache.seata.core.model.BranchType");
- }
-
- @Test
- public void testCheckClass_notAllowed() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThatThrownBy(() -> manager.checkClass("com.malicious.EvilClass"))
- .isInstanceOf(SecurityException.class)
- .hasMessageContaining("not in JSON deserialization allowlist")
- .hasMessageContaining("com.malicious.EvilClass")
- .hasMessageContaining("seata.json.allowlist");
- }
-
- @Test
- public void testCheckClass_userAllowed() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.loadUserAllowlist("com.myapp.model.");
-
- manager.checkClass("com.myapp.model.User");
- }
-
- @Test
- public void testIsAllowed_null() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThat(manager.isAllowed(null)).isFalse();
- }
-
- @Test
- public void testCheckClass_null() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- assertThatThrownBy(() -> manager.checkClass(null)).isInstanceOf(SecurityException.class);
- }
-
- @Test
- public void testAddUserClass_nullOrEmpty() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.addUserClass(null);
- manager.addUserClass("");
- }
-
- @Test
- public void testAddUserPrefix_nullOrEmpty() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.addUserPrefix(null);
- manager.addUserPrefix("");
- }
-
- @Test
- public void testSingleton() {
- JsonAllowlistManager instance1 = JsonAllowlistManager.getInstance();
- JsonAllowlistManager instance2 = JsonAllowlistManager.getInstance();
-
- assertThat(instance1).isSameAs(instance2);
- }
-
- @Test
- public void testCacheWorks() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- boolean result1 = manager.isAllowed("java.lang.String");
-
- boolean result2 = manager.isAllowed("java.lang.String");
-
- assertThat(result1).isTrue();
- assertThat(result2).isTrue();
- }
-
- @Test
- public void testCacheClearedOnLoadUserAllowlist() {
- JsonAllowlistManager manager = JsonAllowlistManager.getInstance();
-
- manager.isAllowed("com.example.CacheTest");
-
- manager.loadUserAllowlist("com.example.CacheTest");
-
- assertThat(manager.isAllowed("com.example.CacheTest")).isTrue();
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java
deleted file mode 100644
index 99a66966f3e..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonSerializerFactoryTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.common.json;
-
-import org.apache.seata.common.json.impl.Fastjson2JsonSerializer;
-import org.apache.seata.common.json.impl.FastjsonJsonSerializer;
-import org.apache.seata.common.json.impl.GsonJsonSerializer;
-import org.apache.seata.common.json.impl.JacksonJsonSerializer;
-import org.apache.seata.common.loader.EnhancedServiceNotFoundException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.lang.reflect.Field;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class JsonSerializerFactoryTest {
-
- @BeforeEach
- @SuppressWarnings("unchecked")
- void clearInstancesCache() throws Exception {
- Field field = JsonSerializerFactory.class.getDeclaredField("INSTANCES");
- field.setAccessible(true);
- ((Map) field.get(null)).clear();
- }
-
- @Test
- public void testGetSerializer_jackson() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("jackson");
- assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_fastjson() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("fastjson");
- assertThat(serializer).isNotNull().isInstanceOf(FastjsonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_fastjson2() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("fastjson2");
- assertThat(serializer).isNotNull().isInstanceOf(Fastjson2JsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_gson() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("gson");
- assertThat(serializer).isNotNull().isInstanceOf(GsonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_nullName_returnsDefaultJackson() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer(null);
- assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_unknownName_throwsException() {
- assertThatThrownBy(() -> JsonSerializerFactory.getSerializer("definitely-not-a-real-serializer"))
- .isInstanceOf(EnhancedServiceNotFoundException.class);
- }
-
- @Test
- public void testGetSerializer_sameNameReturnsCachedInstance() {
- JsonSerializer first = JsonSerializerFactory.getSerializer("jackson");
- JsonSerializer second = JsonSerializerFactory.getSerializer("jackson");
- assertThat(second).isSameAs(first);
- }
-
- /**
- * In json-common-core tests, the jackson3 SPI lives in the separate json-common-jackson3
- * module which is NOT on the test classpath. The factory must catch the
- * EnhancedServiceNotFoundException for "jackson3" and fall back to the default "jackson"
- * serializer.
- */
- @Test
- public void testGetSerializer_jackson3_fallsBackToJacksonWhenUnavailable() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("jackson3");
- assertThat(serializer).isNotNull().isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_jackson3FallbackIsCached() {
- JsonSerializer first = JsonSerializerFactory.getSerializer("jackson3");
- JsonSerializer second = JsonSerializerFactory.getSerializer("jackson3");
- assertThat(second).isSameAs(first);
- assertThat(first).isInstanceOf(JacksonJsonSerializer.class);
- }
-
- @Test
- public void testGetSerializer_jackson3FallbackIsUsableForSerialization() {
- JsonSerializer serializer = JsonSerializerFactory.getSerializer("jackson3");
- String json = serializer.toJSONString(new SimplePojo("hello", 7));
- assertThat(json).contains("\"name\":\"hello\"").contains("\"value\":7");
-
- SimplePojo restored = serializer.parseObject(json, SimplePojo.class);
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("hello");
- assertThat(restored.getValue()).isEqualTo(7);
- }
-
- public static class SimplePojo {
- private String name;
- private int value;
-
- public SimplePojo() {}
-
- public SimplePojo(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonUtilTest.java b/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
deleted file mode 100644
index 2dab9ba4ecc..00000000000
--- a/json-common/json-common-core/src/test/java/org/apache/seata/common/json/JsonUtilTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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.common.json;
-
-import org.apache.seata.common.ConfigurationKeys;
-import org.apache.seata.common.DefaultValues;
-import org.apache.seata.config.Configuration;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class JsonUtilTest {
-
- @BeforeEach
- void setUp() {}
-
- @Test
- public void testToJSONStringBasicObject() {
- TestObject obj = new TestObject("test", 123);
- String json = JsonUtil.toJSONString(obj);
-
- assertThat(json).isNotNull();
- assertThat(json).contains("\"name\":\"test\"");
- assertThat(json).contains("\"value\":123");
- }
-
- @Test
- public void testParseObjectBasicObject() {
- String json = "{\"name\":\"test\",\"value\":123}";
- TestObject obj = JsonUtil.parseObject(json, TestObject.class);
-
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("test");
- assertThat(obj.getValue()).isEqualTo(123);
- }
-
- @Test
- public void testToJSONStringAndParseObjectApple() {
- TestObject original = new TestObject("apple", 456);
- String json = JsonUtil.toJSONString(original);
- TestObject restored = JsonUtil.parseObject(json, TestObject.class);
-
- assertThat(restored.getName()).isEqualTo(original.getName());
- assertThat(restored.getValue()).isEqualTo(original.getValue());
- }
-
- @Test
- public void testParseObjectNullInputs() {
- TestObject obj1 = JsonUtil.parseObject(null, TestObject.class);
- assertThat(obj1).isNull();
-
- TestObject obj2 = JsonUtil.parseObject("{\"name\":\"test\"}", null);
- assertThat(obj2).isNull();
- }
-
- @Test
- public void testParseObjectPrefixLogic() {
- String normalJson = "{\"name\":\"normalTest\",\"value\":888}";
- TestObject obj = JsonUtil.parseObject(normalJson, TestObject.class);
- assertThat(obj).isNotNull();
- assertThat(obj.getName()).isEqualTo("normalTest");
- assertThat(obj.getValue()).isEqualTo(888);
- }
-
- @Test
- public void testToJSONStringNullObject() {
- String json = JsonUtil.toJSONString(null);
- assertThat(json).isEqualTo("null");
- }
-
- @Test
- public void testParseObjectComplexObject() {
- ComplexTestObject complexObj = new ComplexTestObject();
- complexObj.setName("complex");
- complexObj.setValue(789);
- complexObj.setNested(new TestObject("nested", 1));
-
- String json = JsonUtil.toJSONString(complexObj);
- ComplexTestObject restored = JsonUtil.parseObject(json, ComplexTestObject.class);
-
- assertThat(restored).isNotNull();
- assertThat(restored.getName()).isEqualTo("complex");
- assertThat(restored.getValue()).isEqualTo(789);
- assertThat(restored.getNested()).isNotNull();
- assertThat(restored.getNested().getName()).isEqualTo("nested");
- assertThat(restored.getNested().getValue()).isEqualTo(1);
- }
-
- @Test
- public void testResolveJsonSerializerNamePrefersNewConfig() {
- Configuration configuration = mock(Configuration.class);
- when(configuration.getConfig(ConfigurationKeys.JSON_SERIALIZER_TYPE)).thenReturn("gson");
-
- assertThat(JsonUtil.resolveJsonSerializerName(configuration)).isEqualTo("gson");
- }
-
- @Test
- public void testResolveJsonSerializerNameFallsBackToDeprecatedConfig() {
- Configuration configuration = mock(Configuration.class);
- when(configuration.getConfig(ConfigurationKeys.JSON_SERIALIZER_TYPE)).thenReturn(null);
- when(configuration.getConfig(ConfigurationKeys.TCC_BUSINESS_ACTION_CONTEXT_JSON_PARSER_NAME))
- .thenReturn("fastjson2");
-
- assertThat(JsonUtil.resolveJsonSerializerName(configuration)).isEqualTo("fastjson2");
- }
-
- @Test
- public void testResolveJsonSerializerNameReturnsDefaultWhenConfigMissing() {
- Configuration configuration = mock(Configuration.class);
- when(configuration.getConfig(ConfigurationKeys.JSON_SERIALIZER_TYPE)).thenReturn(null);
- when(configuration.getConfig(ConfigurationKeys.TCC_BUSINESS_ACTION_CONTEXT_JSON_PARSER_NAME))
- .thenReturn(null);
-
- assertThat(JsonUtil.resolveJsonSerializerName(configuration))
- .isEqualTo(DefaultValues.BUSINESS_ACTION_CONTEXT_JSON_PARSER);
- }
-
- @Test
- public void testResolveJsonSerializerNameIgnoresBlankNewConfigAndFallsBackToDeprecatedConfig() {
- Configuration configuration = mock(Configuration.class);
- when(configuration.getConfig(ConfigurationKeys.JSON_SERIALIZER_TYPE)).thenReturn(" ");
- when(configuration.getConfig(ConfigurationKeys.TCC_BUSINESS_ACTION_CONTEXT_JSON_PARSER_NAME))
- .thenReturn("fastjson2");
-
- assertThat(JsonUtil.resolveJsonSerializerName(configuration)).isEqualTo("fastjson2");
- }
-
- public static class TestObject {
- private String name;
- private int value;
-
- public TestObject() {}
-
- public TestObject(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-
- public static class ComplexTestObject {
- private String name;
- private int value;
- private TestObject nested;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getValue() {
- return value;
- }
-
- public void setValue(int value) {
- this.value = value;
- }
-
- public TestObject getNested() {
- return nested;
- }
-
- public void setNested(TestObject nested) {
- this.nested = nested;
- }
- }
-}
diff --git a/json-common/json-common-core/src/test/resources/file.conf b/json-common/json-common-core/src/test/resources/file.conf
deleted file mode 100644
index 46c3e0401cc..00000000000
--- a/json-common/json-common-core/src/test/resources/file.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# 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.
-#
-
-service {
- #transaction service group mapping
- vgroupMapping.default_tx_group = "default"
- #only support when registry.type=file, please don't set multiple addresses
- default.grouplist = "127.0.0.1:8091"
- #disable seata
- disableGlobalTransaction = false
-}
\ No newline at end of file
diff --git a/json-common/json-common-core/src/test/resources/registry.conf b/json-common/json-common-core/src/test/resources/registry.conf
deleted file mode 100644
index 5ad014bf55a..00000000000
--- a/json-common/json-common-core/src/test/resources/registry.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# 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.
-#
-
-registry {
- # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
- type = "file"
-
- file {
- name = "file.conf"
- }
-}
-
-config {
- # file、nacos 、apollo、zk、consul、etcd3
- type = "file"
-
- file {
- name = "file.conf"
- }
-}
\ No newline at end of file
diff --git a/json-common/pom.xml b/json-common/pom.xml
deleted file mode 100644
index 1c0d9a5b5ff..00000000000
--- a/json-common/pom.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
- org.apache.seata
- seata-parent
- ${revision}
-
- 4.0.0
- json-common
- pom
- json-common ${project.version}
- json-common top parent for Seata built with Maven
-
-
- json-common-core
-
-
-
-
-
- JDK17Plus
-
- [17,)
-
-
- json-common-jackson3
-
-
-
-
-
diff --git a/pom.xml b/pom.xml
index 05129717f49..b2fb282f29f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,6 @@
bom
common
config
- threadpool
core
compatible
@@ -63,7 +62,6 @@
test-suite/test-new-version
test-suite/test-old-version
test-suite/seata-benchmark-cli
- json-common
@@ -129,6 +127,16 @@
+
+
+ JDK17Plus
+
+ [17,)
+
+
+ spi-jdk17
+
+
JDK21Plus
@@ -136,7 +144,7 @@
[21,)
- threadpool-loom
+ spi-jdk21
diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml
index c08172c2943..ddcb08734a8 100644
--- a/rm-datasource/pom.xml
+++ b/rm-datasource/pom.xml
@@ -159,10 +159,5 @@
oscarJDBC8
test
-
- ${project.groupId}
- json-common-core
- ${project.version}
-
diff --git a/saga/pom.xml b/saga/pom.xml
index a5919647bf4..37376d671e9 100644
--- a/saga/pom.xml
+++ b/saga/pom.xml
@@ -48,12 +48,6 @@
${project.version}
-
- ${project.groupId}
- json-common-core
- ${project.version}
-
-
com.alibaba
fastjson
diff --git a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
index ccc2342ef48..6b390b83120 100644
--- a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
+++ b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParser.java
@@ -19,7 +19,7 @@
/**
* Json Parser
*
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializer} in seata-common module instead.
*/
@Deprecated
public interface JsonParser {
diff --git a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
index a8b4ab9e493..c4b4bd97476 100644
--- a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
+++ b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/JsonParserFactory.java
@@ -25,7 +25,7 @@
/**
* JsonParserFactory
*
- * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.JsonSerializerFactory} in seata-common module instead.
*/
@Deprecated
public class JsonParserFactory {
diff --git a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
index 851e4d1bd69..ad49e4462df 100644
--- a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
+++ b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/FastjsonParser.java
@@ -25,7 +25,7 @@
/**
* JsonParser implement by Fastjson
*
- * @deprecated use {@link org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.impl.FastjsonJsonSerializer} in seata-common module instead.
*/
@Deprecated
@LoadLevel(name = FastjsonParser.NAME)
diff --git a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
index f79abf45669..4e4a238ba16 100644
--- a/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
+++ b/saga/seata-saga-statelang/src/main/java/org/apache/seata/saga/statelang/parser/impl/JacksonJsonParser.java
@@ -32,7 +32,7 @@
/**
* JsonParser implement by Jackson
*
- * @deprecated use {@link org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.impl.JacksonJsonSerializer} in seata-common module instead.
*/
@Deprecated
@LoadLevel(name = JacksonJsonParser.NAME)
diff --git a/server/pom.xml b/server/pom.xml
index 9de1f407868..31287410998 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -486,7 +486,7 @@
${project.groupId}
- seata-threadpool-loom
+ seata-spi-jdk21
${project.version}
diff --git a/json-common/json-common-jackson3/pom.xml b/spi-jdk17/pom.xml
similarity index 86%
rename from json-common/json-common-jackson3/pom.xml
rename to spi-jdk17/pom.xml
index da4d5c48329..64c520ef5a7 100644
--- a/json-common/json-common-jackson3/pom.xml
+++ b/spi-jdk17/pom.xml
@@ -22,14 +22,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
org.apache.seata
- json-common
+ seata-parent
${revision}
4.0.0
- json-common-jackson3
+ seata-spi-jdk17
jar
- json-common-jackson3 ${project.version}
- Jackson 3 JSON serializer for Seata (requires JDK 17+)
+ seata-spi-jdk17 ${project.version}
+ JDK 17+ SPI extensions for Seata (Jackson 3 JSON serializer)
17
@@ -40,7 +40,7 @@
${project.groupId}
- json-common-core
+ seata-common
${project.version}
diff --git a/json-common/json-common-jackson3/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java b/spi-jdk17/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
similarity index 100%
rename from json-common/json-common-jackson3/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
rename to spi-jdk17/src/main/java/org/apache/seata/common/json/impl/Jackson3JsonSerializer.java
diff --git a/json-common/json-common-jackson3/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer b/spi-jdk17/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
similarity index 100%
rename from json-common/json-common-jackson3/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
rename to spi-jdk17/src/main/resources/META-INF/services/org.apache.seata.common.json.JsonSerializer
diff --git a/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java b/spi-jdk17/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
similarity index 100%
rename from json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
rename to spi-jdk17/src/test/java/org/apache/seata/common/json/Jackson3AllowlistTest.java
diff --git a/json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java b/spi-jdk17/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
similarity index 100%
rename from json-common/json-common-jackson3/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
rename to spi-jdk17/src/test/java/org/apache/seata/common/json/Jackson3JsonSerializerTest.java
diff --git a/threadpool/pom.xml b/spi-jdk21/pom.xml
similarity index 79%
rename from threadpool/pom.xml
rename to spi-jdk21/pom.xml
index e0ec17f0e49..5618cb320da 100644
--- a/threadpool/pom.xml
+++ b/spi-jdk21/pom.xml
@@ -26,10 +26,15 @@
${revision}
4.0.0
- seata-threadpool
+ seata-spi-jdk21
jar
- seata-threadpool ${project.version}
- Managed thread pool factory for Seata
+ seata-spi-jdk21 ${project.version}
+ JDK 21+ SPI extensions for Seata (virtual thread pool provider)
+
+
+ 21
+ 21
+
@@ -39,8 +44,9 @@
org.apache.seata
- seata-config-core
+ seata-core
${project.version}
+ test
diff --git a/threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualScheduledThreadPoolExecutor.java b/spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualScheduledThreadPoolExecutor.java
similarity index 100%
rename from threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualScheduledThreadPoolExecutor.java
rename to spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualScheduledThreadPoolExecutor.java
diff --git a/threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadFactoryHelper.java b/spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadFactoryHelper.java
similarity index 100%
rename from threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadFactoryHelper.java
rename to spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadFactoryHelper.java
diff --git a/threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolExecutor.java b/spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolExecutor.java
similarity index 100%
rename from threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolExecutor.java
rename to spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolExecutor.java
diff --git a/threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolProvider.java b/spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolProvider.java
similarity index 100%
rename from threadpool-loom/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolProvider.java
rename to spi-jdk21/src/main/java/org/apache/seata/common/thread/VirtualThreadPoolProvider.java
diff --git a/threadpool-loom/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider b/spi-jdk21/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
similarity index 100%
rename from threadpool-loom/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
rename to spi-jdk21/src/main/resources/META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider
diff --git a/threadpool-loom/src/test/java/org/apache/seata/common/thread/VirtualThreadPoolProviderTest.java b/spi-jdk21/src/test/java/org/apache/seata/common/thread/VirtualThreadPoolProviderTest.java
similarity index 100%
rename from threadpool-loom/src/test/java/org/apache/seata/common/thread/VirtualThreadPoolProviderTest.java
rename to spi-jdk21/src/test/java/org/apache/seata/common/thread/VirtualThreadPoolProviderTest.java
diff --git a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
index f0c5fb6fa3c..998d81f144f 100644
--- a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
+++ b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-client/pom.xml
@@ -37,11 +37,6 @@
seata-spring-autoconfigure-core
${project.version}
-
- org.apache.seata
- json-common-core
- ${project.version}
-
javax.annotation
javax.annotation-api
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
index 120e986f360..11442b86b06 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/FastJsonParser.java
@@ -22,7 +22,7 @@
import org.apache.seata.integration.tx.api.json.JsonParser;
/**
- * @deprecated use {@link org.apache.seata.common.json.impl.FastjsonJsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.impl.FastjsonJsonSerializer} in seata-common module instead.
*/
@Deprecated
@LoadLevel(name = Constants.FASTJSON_JSON_PARSER_NAME)
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
index 26caf1e678e..efe27b3f902 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/GsonJsonParser.java
@@ -25,7 +25,7 @@
import java.lang.reflect.Modifier;
/**
- * @deprecated use {@link org.apache.seata.common.json.impl.GsonJsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.impl.GsonJsonSerializer} in seata-common module instead.
*/
@Deprecated
@LoadLevel(name = Constants.GSON_JSON_PARSER_NAME)
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
index ea33594c244..a51f9cff88b 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/json/JacksonJsonParser.java
@@ -28,7 +28,7 @@
import java.io.IOException;
/**
- * @deprecated use {@link org.apache.seata.common.json.impl.JacksonJsonSerializer} in json-common-core module instead.
+ * @deprecated use {@link org.apache.seata.common.json.impl.JacksonJsonSerializer} in seata-common module instead.
*/
@Deprecated
@LoadLevel(name = Constants.JACKSON_JSON_PARSER_NAME)
diff --git a/threadpool-loom/pom.xml b/threadpool-loom/pom.xml
deleted file mode 100644
index 1717daf07dd..00000000000
--- a/threadpool-loom/pom.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
- org.apache.seata
- seata-parent
- ${revision}
-
- 4.0.0
- seata-threadpool-loom
- jar
- seata-threadpool-loom ${project.version}
- Loom-backed thread pool provider for Seata managed thread pools
-
-
- 21
- 21
-
-
-
-
- org.apache.seata
- seata-threadpool
- ${project.version}
-
-
-