This is an automated email from the ASF dual-hosted git repository.

jimin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new ba2c224576 feature: support fory serializer and fory undolog parser 
(#7503)
ba2c224576 is described below

commit ba2c224576071563ed672038d56a569f80ae338c
Author: diguage <[email protected]>
AuthorDate: Sat Dec 20 21:00:54 2025 +0800

    feature: support fory serializer and fory undolog parser (#7503)
---
 all/pom.xml                                        |  5 ++
 changes/en-us/2.x.md                               |  1 +
 changes/zh-cn/2.x.md                               |  1 +
 .../core/serializer/SerializerServiceLoader.java   |  3 +-
 .../seata/core/serializer/SerializerType.java      |  7 +-
 dependencies/pom.xml                               |  8 +-
 rm-datasource/pom.xml                              |  6 ++
 .../datasource/undo/parser/ForyUndoLogParser.java  | 68 ++++++++++++++++
 ...g.apache.seata.rm.datasource.undo.UndoLogParser |  3 +-
 .../undo/parser/ForyUndoLogParserTest.java         | 35 ++++++++
 serializer/pom.xml                                 |  1 +
 serializer/seata-serializer-all/pom.xml            |  5 ++
 .../pom.xml                                        | 10 +--
 .../seata/serializer/fory/ForySerializer.java}     | 17 ++--
 .../serializer/fory/ForySerializerFactory.java}    | 35 ++++----
 .../org.apache.seata.core.serializer.Serializer    |  7 +-
 .../seata/serializer/fory/ForySerializerTest.java} | 42 ++--------
 serializer/seata-serializer-fury/pom.xml           |  8 ++
 .../serializer/fury/DynamicSerializerFactory.java  | 59 ++++++++++++++
 ...Serializer.java => ForySerializerDelegate.java} | 26 +++---
 .../seata/serializer/fury/FurySerializer.java      |  9 +--
 ...zerFactory.java => ThreadSafeForyDelegate.java} | 37 ++++-----
 ...zerFactory.java => ThreadSafeFuryDelegate.java} | 14 ++--
 .../seata/serializer/fury/FurySerializerTest.java  | 92 +++++++++++++++++++---
 24 files changed, 368 insertions(+), 131 deletions(-)

diff --git a/all/pom.xml b/all/pom.xml
index 82e67e12a2..bf608490e3 100644
--- a/all/pom.xml
+++ b/all/pom.xml
@@ -267,6 +267,11 @@
             <artifactId>seata-serializer-fury</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.seata</groupId>
+            <artifactId>seata-serializer-fory</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.seata</groupId>
             <artifactId>seata-serializer-kryo</artifactId>
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 48638c11a4..9ad85116b0 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -199,6 +199,7 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [xiaoxiangyeyu0](https://github.com/xiaoxiangyeyu0)
 - [jsbxyyx](https://github.com/jsbxyyx)
 - [xingfudeshi](https://github.com/xingfudeshi)
+- [diguage](https://github.com/diguage)
 - [aias00](https://github.com/aias00)
 
 
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 7e89008a1c..3758e06b0b 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -198,6 +198,7 @@
 - [xiaoxiangyeyu0](https://github.com/xiaoxiangyeyu0)
 - [jsbxyyx](https://github.com/jsbxyyx)
 - [xingfudeshi](https://github.com/xingfudeshi)
+- [diguage](https://github.com/diguage)
 - [aias00](https://github.com/aias00)
 
 
diff --git 
a/core/src/main/java/org/apache/seata/core/serializer/SerializerServiceLoader.java
 
b/core/src/main/java/org/apache/seata/core/serializer/SerializerServiceLoader.java
index 3461b5cd16..8ce367cabd 100644
--- 
a/core/src/main/java/org/apache/seata/core/serializer/SerializerServiceLoader.java
+++ 
b/core/src/main/java/org/apache/seata/core/serializer/SerializerServiceLoader.java
@@ -33,6 +33,7 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 import static org.apache.seata.core.serializer.SerializerType.FASTJSON2;
+import static org.apache.seata.core.serializer.SerializerType.FORY;
 import static org.apache.seata.core.serializer.SerializerType.FURY;
 import static org.apache.seata.core.serializer.SerializerType.HESSIAN;
 import static org.apache.seata.core.serializer.SerializerType.KRYO;
@@ -48,7 +49,7 @@ public final class SerializerServiceLoader {
     private static final Configuration CONFIG = 
ConfigurationFactory.getInstance();
 
     private static final SerializerType[] DEFAULT_SERIALIZER_TYPE =
-            new SerializerType[] {SEATA, PROTOBUF, KRYO, HESSIAN, FASTJSON2, 
FURY};
+            new SerializerType[] {SEATA, PROTOBUF, KRYO, HESSIAN, FASTJSON2, 
FURY, FORY};
 
     private static final Map<String, Serializer> SERIALIZER_MAP = new 
HashMap<>();
 
diff --git 
a/core/src/main/java/org/apache/seata/core/serializer/SerializerType.java 
b/core/src/main/java/org/apache/seata/core/serializer/SerializerType.java
index 243cc11911..6ebe863094 100644
--- a/core/src/main/java/org/apache/seata/core/serializer/SerializerType.java
+++ b/core/src/main/java/org/apache/seata/core/serializer/SerializerType.java
@@ -67,7 +67,12 @@ public enum SerializerType {
     /**
      * The fury.
      */
-    FURY((byte) 86);
+    FURY((byte) 86),
+
+    /**
+     * The fory.
+     */
+    FORY((byte) 87);
 
     private final byte code;
 
diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index 7519faf6a0..8a26a838e4 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -144,7 +144,8 @@
         <native-lib-loader.version>2.4.0</native-lib-loader.version>
 
         <!--  for fury  -->
-        <fury.version>0.8.0</fury.version>
+        <fury.version>0.10.3</fury.version>
+        <fory.version>0.12.3</fory.version>
     </properties>
 
     <dependencyManagement>
@@ -900,6 +901,11 @@
                 <artifactId>fury-core</artifactId>
                 <version>${fury.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.fory</groupId>
+                <artifactId>fory-core</artifactId>
+                <version>${fory.version}</version>
+            </dependency>
             <dependency>
                 <groupId>commons-io</groupId>
                 <artifactId>commons-io</artifactId>
diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml
index 28da98f41e..9672700b81 100644
--- a/rm-datasource/pom.xml
+++ b/rm-datasource/pom.xml
@@ -149,6 +149,12 @@
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.apache.fory</groupId>
+            <artifactId>fory-core</artifactId>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
         <dependency>
             <groupId>cn.com.kingbase</groupId>
             <artifactId>kingbase8</artifactId>
diff --git 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParser.java
 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParser.java
new file mode 100644
index 0000000000..a06bddd0c6
--- /dev/null
+++ 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParser.java
@@ -0,0 +1,68 @@
+/*
+ * 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.rm.datasource.undo.parser;
+
+import org.apache.fory.Fory;
+import org.apache.fory.ThreadLocalFory;
+import org.apache.fory.ThreadSafeFory;
+import org.apache.fory.config.CompatibleMode;
+import org.apache.fory.config.Language;
+import org.apache.seata.common.executor.Initialize;
+import org.apache.seata.common.loader.LoadLevel;
+import org.apache.seata.rm.datasource.undo.BranchUndoLog;
+import org.apache.seata.rm.datasource.undo.UndoLogParser;
+
+@LoadLevel(name = ForyUndoLogParser.NAME)
+public class ForyUndoLogParser implements UndoLogParser, Initialize {
+    public static final String NAME = "fory";
+
+    private static final ThreadSafeFory FORY = new ThreadLocalFory(classLoader 
-> Fory.builder()
+            .withLanguage(Language.JAVA)
+            // In JAVA mode, classes cannot be registered by tag, and the 
different registration order between the
+            // server and the client will cause deserialization failure
+            // In XLANG cross-language mode has problems with Java class 
serialization, such as enum classes
+            // [https://github.com/apache/fory/issues/1644].
+            .requireClassRegistration(false)
+            // enable reference tracking for shared/circular reference.
+            .withRefTracking(true)
+            .withClassLoader(classLoader)
+            .withCompatibleMode(CompatibleMode.COMPATIBLE)
+            .build());
+
+    @Override
+    public void init() {}
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public byte[] getDefaultContent() {
+        return encode(new BranchUndoLog());
+    }
+
+    @Override
+    public byte[] encode(BranchUndoLog branchUndoLog) {
+        return FORY.serializeJavaObject(branchUndoLog);
+    }
+
+    @Override
+    public BranchUndoLog decode(byte[] bytes) {
+        return FORY.deserializeJavaObject(bytes, BranchUndoLog.class);
+    }
+}
diff --git 
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
 
b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
index 41596cc4c6..d9a37d043e 100644
--- 
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
+++ 
b/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
@@ -19,4 +19,5 @@ 
org.apache.seata.rm.datasource.undo.parser.JacksonUndoLogParser
 org.apache.seata.rm.datasource.undo.parser.ProtostuffUndoLogParser
 org.apache.seata.rm.datasource.undo.parser.KryoUndoLogParser
 org.apache.seata.rm.datasource.undo.parser.Fastjson2UndoLogParser
-org.apache.seata.rm.datasource.undo.parser.FuryUndoLogParser
\ No newline at end of file
+org.apache.seata.rm.datasource.undo.parser.FuryUndoLogParser
+org.apache.seata.rm.datasource.undo.parser.ForyUndoLogParser
\ No newline at end of file
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParserTest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParserTest.java
new file mode 100644
index 0000000000..f80f343e91
--- /dev/null
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/undo/parser/ForyUndoLogParserTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.rm.datasource.undo.parser;
+
+import org.apache.seata.common.loader.EnhancedServiceLoader;
+import org.apache.seata.rm.datasource.undo.BaseUndoLogParserTest;
+import org.apache.seata.rm.datasource.undo.UndoLogParser;
+
+public class ForyUndoLogParserTest extends BaseUndoLogParserTest {
+
+    ForyUndoLogParser parser =
+            (ForyUndoLogParser) 
EnhancedServiceLoader.load(UndoLogParser.class, ForyUndoLogParser.NAME);
+
+    @Override
+    public UndoLogParser getParser() {
+        return parser;
+    }
+
+    @Override
+    public void testTimestampEncodeAndDecode() {}
+}
diff --git a/serializer/pom.xml b/serializer/pom.xml
index e4435a724d..e0aa5e5b9d 100644
--- a/serializer/pom.xml
+++ b/serializer/pom.xml
@@ -39,6 +39,7 @@
         <module>seata-serializer-hessian</module>
         <module>seata-serializer-fastjson2</module>
         <module>seata-serializer-fury</module>
+        <module>seata-serializer-fory</module>
     </modules>
 
 </project>
diff --git a/serializer/seata-serializer-all/pom.xml 
b/serializer/seata-serializer-all/pom.xml
index d34e9f6b14..7d9cd6e8aa 100644
--- a/serializer/seata-serializer-all/pom.xml
+++ b/serializer/seata-serializer-all/pom.xml
@@ -60,5 +60,10 @@
             <artifactId>seata-serializer-fury</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>seata-serializer-fory</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/serializer/seata-serializer-fury/pom.xml 
b/serializer/seata-serializer-fory/pom.xml
similarity index 85%
copy from serializer/seata-serializer-fury/pom.xml
copy to serializer/seata-serializer-fory/pom.xml
index 18a40ac202..e1c6238d58 100644
--- a/serializer/seata-serializer-fury/pom.xml
+++ b/serializer/seata-serializer-fory/pom.xml
@@ -26,10 +26,10 @@
         <version>${revision}</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>seata-serializer-fury</artifactId>
+    <artifactId>seata-serializer-fory</artifactId>
     <packaging>jar</packaging>
-    <name>seata-serializer-fury ${project.version}</name>
-    <description>serializer-fury for Seata built with Maven</description>
+    <name>seata-serializer-fory ${project.version}</name>
+    <description>serializer-fory for Seata built with Maven</description>
 
     <dependencies>
         <dependency>
@@ -39,8 +39,8 @@
         </dependency>
 
         <dependency>
-            <groupId>org.apache.fury</groupId>
-            <artifactId>fury-core</artifactId>
+            <groupId>org.apache.fory</groupId>
+            <artifactId>fory-core</artifactId>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
 
b/serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializer.java
similarity index 78%
copy from 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
copy to 
serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializer.java
index 8724475e45..9ed64e81fb 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
+++ 
b/serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializer.java
@@ -14,22 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.serializer.fury;
+package org.apache.seata.serializer.fory;
 
-import org.apache.fury.ThreadSafeFury;
+import org.apache.fory.ThreadSafeFory;
 import org.apache.seata.common.loader.LoadLevel;
 import org.apache.seata.core.protocol.AbstractMessage;
 import org.apache.seata.core.serializer.Serializer;
 
-@LoadLevel(name = "FURY")
-public class FurySerializer implements Serializer {
+@LoadLevel(name = "FORY")
+public class ForySerializer implements Serializer {
     @Override
     public <T> byte[] serialize(T t) {
         if (!(t instanceof AbstractMessage)) {
             throw new IllegalArgumentException("AbstractMessage isn't 
available.");
         }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return threadSafeFury.serialize(t);
+
+        ThreadSafeFory threadSafeFory = 
ForySerializerFactory.getInstance().get();
+        return threadSafeFory.serialize(t);
     }
 
     @Override
@@ -37,7 +38,7 @@ public class FurySerializer implements Serializer {
         if (bytes == null || bytes.length == 0) {
             throw new IllegalArgumentException("bytes is null");
         }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return (T) threadSafeFury.deserialize(bytes);
+        ThreadSafeFory threadSafeFory = 
ForySerializerFactory.getInstance().get();
+        return (T) threadSafeFory.deserialize(bytes);
     }
 }
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
 
b/serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializerFactory.java
similarity index 65%
copy from 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
copy to 
serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializerFactory.java
index f99358622a..fe8b576f36 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
+++ 
b/serializer/seata-serializer-fory/src/main/java/org/apache/seata/serializer/fory/ForySerializerFactory.java
@@ -14,26 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.serializer.fury;
+package org.apache.seata.serializer.fory;
 
-import org.apache.fury.Fury;
-import org.apache.fury.ThreadLocalFury;
-import org.apache.fury.ThreadSafeFury;
-import org.apache.fury.config.CompatibleMode;
-import org.apache.fury.config.Language;
-import org.apache.fury.resolver.AllowListChecker;
+import org.apache.fory.Fory;
+import org.apache.fory.ThreadLocalFory;
+import org.apache.fory.ThreadSafeFory;
+import org.apache.fory.config.CompatibleMode;
+import org.apache.fory.config.Language;
 import org.apache.seata.core.serializer.SerializerSecurityRegistry;
 
-public class FurySerializerFactory {
-    private static final FurySerializerFactory FACTORY = new 
FurySerializerFactory();
+public class ForySerializerFactory {
+    private static final ForySerializerFactory FACTORY = new 
ForySerializerFactory();
 
-    private static final ThreadSafeFury FURY = new ThreadLocalFury(classLoader 
-> {
-        Fury f = Fury.builder()
+    private static final ThreadSafeFory FORY = new ThreadLocalFory(classLoader 
-> {
+        Fory f = Fory.builder()
                 .withLanguage(Language.JAVA)
                 // In JAVA mode, classes cannot be registered by tag, and the 
different registration order between the
                 // server and the client will cause deserialization failure
                 // In XLANG cross-language mode has problems with Java class 
serialization, such as enum classes
-                // [https://github.com/apache/fury/issues/1644].
+                // [https://github.com/apache/fory/issues/1644].
                 .requireClassRegistration(false)
                 // enable reference tracking for shared/circular reference.
                 .withRefTracking(true)
@@ -42,17 +41,17 @@ public class FurySerializerFactory {
                 .build();
 
         // register allow class
-        AllowListChecker checker = new 
AllowListChecker(AllowListChecker.CheckLevel.STRICT);
-        f.getClassResolver().setClassChecker(checker);
-        
checker.allowClasses(SerializerSecurityRegistry.getAllowClassPattern());
+        f.getClassResolver()
+                .setClassChecker((classResolver, className) ->
+                        
SerializerSecurityRegistry.getAllowClassPattern().contains(className));
         return f;
     });
 
-    public static FurySerializerFactory getInstance() {
+    public static ForySerializerFactory getInstance() {
         return FACTORY;
     }
 
-    public ThreadSafeFury get() {
-        return FURY;
+    public ThreadSafeFory get() {
+        return FORY;
     }
 }
diff --git 
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
 
b/serializer/seata-serializer-fory/src/main/resources/META-INF/services/org.apache.seata.core.serializer.Serializer
similarity index 67%
copy from 
rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
copy to 
serializer/seata-serializer-fory/src/main/resources/META-INF/services/org.apache.seata.core.serializer.Serializer
index 41596cc4c6..58c6d0ce84 100644
--- 
a/rm-datasource/src/main/resources/META-INF/services/org.apache.seata.rm.datasource.undo.UndoLogParser
+++ 
b/serializer/seata-serializer-fory/src/main/resources/META-INF/services/org.apache.seata.core.serializer.Serializer
@@ -14,9 +14,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-org.apache.seata.rm.datasource.undo.parser.FastjsonUndoLogParser
-org.apache.seata.rm.datasource.undo.parser.JacksonUndoLogParser
-org.apache.seata.rm.datasource.undo.parser.ProtostuffUndoLogParser
-org.apache.seata.rm.datasource.undo.parser.KryoUndoLogParser
-org.apache.seata.rm.datasource.undo.parser.Fastjson2UndoLogParser
-org.apache.seata.rm.datasource.undo.parser.FuryUndoLogParser
\ No newline at end of file
+org.apache.seata.serializer.fory.ForySerializer
\ No newline at end of file
diff --git 
a/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
 
b/serializer/seata-serializer-fory/src/test/java/org/apache/seata/serializer/fory/ForySerializerTest.java
similarity index 67%
copy from 
serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
copy to 
serializer/seata-serializer-fory/src/test/java/org/apache/seata/serializer/fory/ForySerializerTest.java
index 79e9325ed8..8fe4ec555a 100644
--- 
a/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
+++ 
b/serializer/seata-serializer-fory/src/test/java/org/apache/seata/serializer/fory/ForySerializerTest.java
@@ -14,31 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.serializer.fury;
+package org.apache.seata.serializer.fory;
 
-import org.apache.fury.Fury;
-import org.apache.fury.config.CompatibleMode;
-import org.apache.fury.exception.DeserializationException;
-import org.apache.fury.exception.InsecureException;
 import org.apache.seata.core.exception.TransactionExceptionCode;
 import org.apache.seata.core.model.BranchStatus;
 import org.apache.seata.core.model.BranchType;
 import org.apache.seata.core.protocol.ResultCode;
 import org.apache.seata.core.protocol.transaction.BranchCommitRequest;
 import org.apache.seata.core.protocol.transaction.BranchCommitResponse;
-import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.seata.test.TestUnSafeSerializer;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class FurySerializerTest {
-    private static FurySerializer furySerializer;
+public class ForySerializerTest {
+    private static ForySerializer forySerializer;
 
     @BeforeAll
     public static void before() {
-        furySerializer = new FurySerializer();
+        forySerializer = new ForySerializer();
     }
 
     @Test
@@ -51,8 +45,8 @@ public class FurySerializerTest {
         branchCommitRequest.setBranchId(20190809);
         branchCommitRequest.setApplicationData("app");
 
-        byte[] bytes = furySerializer.serialize(branchCommitRequest);
-        BranchCommitRequest t = furySerializer.deserialize(bytes);
+        byte[] bytes = forySerializer.serialize(branchCommitRequest);
+        BranchCommitRequest t = forySerializer.deserialize(bytes);
 
         
assertThat(t.getTypeCode()).isEqualTo(branchCommitRequest.getTypeCode());
         
assertThat(t.getBranchType()).isEqualTo(branchCommitRequest.getBranchType());
@@ -73,8 +67,8 @@ public class FurySerializerTest {
         branchCommitResponse.setXid("20190809");
         branchCommitResponse.setResultCode(ResultCode.Failed);
 
-        byte[] bytes = furySerializer.serialize(branchCommitResponse);
-        BranchCommitResponse t = furySerializer.deserialize(bytes);
+        byte[] bytes = forySerializer.serialize(branchCommitResponse);
+        BranchCommitResponse t = forySerializer.deserialize(bytes);
 
         
assertThat(t.getTransactionExceptionCode()).isEqualTo(branchCommitResponse.getTransactionExceptionCode());
         
assertThat(t.getBranchId()).isEqualTo(branchCommitResponse.getBranchId());
@@ -82,24 +76,4 @@ public class FurySerializerTest {
         assertThat(t.getMsg()).isEqualTo(branchCommitResponse.getMsg());
         
assertThat(t.getResultCode()).isEqualTo(branchCommitResponse.getResultCode());
     }
-
-    @Test
-    public void testUnSafeDeserializer() {
-        // Test deserialization of an object that is not in allow list
-        TestUnSafeSerializer testUnSafeSerializer = new TestUnSafeSerializer();
-        Fury fury = Fury.builder()
-                .requireClassRegistration(false)
-                .withRefTracking(true)
-                .withCompatibleMode(CompatibleMode.COMPATIBLE)
-                .build();
-        Assertions.assertThrows(
-                DeserializationException.class, () -> 
furySerializer.deserialize(fury.serialize(testUnSafeSerializer)));
-    }
-
-    @Test
-    public void testUnSafeSerializer() {
-        // Test serialization of an object that is not in allow list
-        TestUnSafeSerializer testUnSafeSerializer = new TestUnSafeSerializer();
-        Assertions.assertThrows(InsecureException.class, () -> 
furySerializer.serialize(testUnSafeSerializer));
-    }
 }
diff --git a/serializer/seata-serializer-fury/pom.xml 
b/serializer/seata-serializer-fury/pom.xml
index 18a40ac202..e5310f3f8e 100644
--- a/serializer/seata-serializer-fury/pom.xml
+++ b/serializer/seata-serializer-fury/pom.xml
@@ -37,10 +37,18 @@
             <artifactId>seata-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>seata-serializer-fory</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.fury</groupId>
             <artifactId>fury-core</artifactId>
+            <optional>true</optional>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/DynamicSerializerFactory.java
 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/DynamicSerializerFactory.java
new file mode 100644
index 0000000000..8de2a20cf1
--- /dev/null
+++ 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/DynamicSerializerFactory.java
@@ -0,0 +1,59 @@
+/*
+ * 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.serializer.fury;
+
+import org.apache.seata.core.serializer.Serializer;
+
+public class DynamicSerializerFactory {
+    private static final DynamicSerializerFactory FACTORY = new 
DynamicSerializerFactory();
+
+    private final Serializer furyDelegate;
+
+    private DynamicSerializerFactory() {
+        this.furyDelegate = createFuryDelegate();
+    }
+
+    public static DynamicSerializerFactory getInstance() {
+        return FACTORY;
+    }
+
+    public Serializer get() {
+        return furyDelegate;
+    }
+
+    private Serializer createFuryDelegate() {
+        // First, try to load seata-serializer-fory.
+        try {
+            Class.forName("org.apache.seata.serializer.fory.ForySerializer");
+            return new ForySerializerDelegate();
+        } catch (ClassNotFoundException e) {
+        }
+        // Second, try to load Apache Fory.
+        try {
+            Class.forName("org.apache.fory.Fury");
+            return new ThreadSafeForyDelegate();
+        } catch (ClassNotFoundException e) {
+        }
+        // If Fory is unavailable, fallback to Fury.
+        try {
+            Class.forName("org.apache.fury.Fury");
+            return new ThreadSafeFuryDelegate();
+        } catch (ClassNotFoundException e) {
+            throw new IllegalStateException("Neither Apache Fory nor Apache 
Fury found in classpath", e);
+        }
+    }
+}
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ForySerializerDelegate.java
similarity index 53%
copy from 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
copy to 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ForySerializerDelegate.java
index 8724475e45..130092af68 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
+++ 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ForySerializerDelegate.java
@@ -16,28 +16,20 @@
  */
 package org.apache.seata.serializer.fury;
 
-import org.apache.fury.ThreadSafeFury;
-import org.apache.seata.common.loader.LoadLevel;
-import org.apache.seata.core.protocol.AbstractMessage;
 import org.apache.seata.core.serializer.Serializer;
+import org.apache.seata.serializer.fory.ForySerializer;
+
+public class ForySerializerDelegate implements Serializer {
+
+    private static final ForySerializer SERIALIZER = new ForySerializer();
 
-@LoadLevel(name = "FURY")
-public class FurySerializer implements Serializer {
     @Override
-    public <T> byte[] serialize(T t) {
-        if (!(t instanceof AbstractMessage)) {
-            throw new IllegalArgumentException("AbstractMessage isn't 
available.");
-        }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return threadSafeFury.serialize(t);
+    public byte[] serialize(Object obj) {
+        return SERIALIZER.serialize(obj);
     }
 
     @Override
-    public <T> T deserialize(byte[] bytes) {
-        if (bytes == null || bytes.length == 0) {
-            throw new IllegalArgumentException("bytes is null");
-        }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return (T) threadSafeFury.deserialize(bytes);
+    public Object deserialize(byte[] bytes) {
+        return SERIALIZER.deserialize(bytes);
     }
 }
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
index 8724475e45..5ace1545dd 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
+++ 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java
@@ -16,7 +16,6 @@
  */
 package org.apache.seata.serializer.fury;
 
-import org.apache.fury.ThreadSafeFury;
 import org.apache.seata.common.loader.LoadLevel;
 import org.apache.seata.core.protocol.AbstractMessage;
 import org.apache.seata.core.serializer.Serializer;
@@ -28,8 +27,8 @@ public class FurySerializer implements Serializer {
         if (!(t instanceof AbstractMessage)) {
             throw new IllegalArgumentException("AbstractMessage isn't 
available.");
         }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return threadSafeFury.serialize(t);
+        Serializer serializer = DynamicSerializerFactory.getInstance().get();
+        return serializer.serialize(t);
     }
 
     @Override
@@ -37,7 +36,7 @@ public class FurySerializer implements Serializer {
         if (bytes == null || bytes.length == 0) {
             throw new IllegalArgumentException("bytes is null");
         }
-        ThreadSafeFury threadSafeFury = 
FurySerializerFactory.getInstance().get();
-        return (T) threadSafeFury.deserialize(bytes);
+        Serializer serializer = DynamicSerializerFactory.getInstance().get();
+        return (T) serializer.deserialize(bytes);
     }
 }
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeForyDelegate.java
similarity index 65%
copy from 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
copy to 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeForyDelegate.java
index f99358622a..8a8843d2d4 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
+++ 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeForyDelegate.java
@@ -16,24 +16,23 @@
  */
 package org.apache.seata.serializer.fury;
 
-import org.apache.fury.Fury;
-import org.apache.fury.ThreadLocalFury;
-import org.apache.fury.ThreadSafeFury;
-import org.apache.fury.config.CompatibleMode;
-import org.apache.fury.config.Language;
-import org.apache.fury.resolver.AllowListChecker;
+import org.apache.fory.Fory;
+import org.apache.fory.ThreadLocalFory;
+import org.apache.fory.ThreadSafeFory;
+import org.apache.fory.config.CompatibleMode;
+import org.apache.fory.config.Language;
+import org.apache.seata.core.serializer.Serializer;
 import org.apache.seata.core.serializer.SerializerSecurityRegistry;
 
-public class FurySerializerFactory {
-    private static final FurySerializerFactory FACTORY = new 
FurySerializerFactory();
+public class ThreadSafeForyDelegate implements Serializer {
 
-    private static final ThreadSafeFury FURY = new ThreadLocalFury(classLoader 
-> {
-        Fury f = Fury.builder()
+    private static final ThreadSafeFory FORY = new ThreadLocalFory(classLoader 
-> {
+        Fory f = Fory.builder()
                 .withLanguage(Language.JAVA)
                 // In JAVA mode, classes cannot be registered by tag, and the 
different registration order between the
                 // server and the client will cause deserialization failure
                 // In XLANG cross-language mode has problems with Java class 
serialization, such as enum classes
-                // [https://github.com/apache/fury/issues/1644].
+                // [https://github.com/apache/fory/issues/1644].
                 .requireClassRegistration(false)
                 // enable reference tracking for shared/circular reference.
                 .withRefTracking(true)
@@ -42,17 +41,19 @@ public class FurySerializerFactory {
                 .build();
 
         // register allow class
-        AllowListChecker checker = new 
AllowListChecker(AllowListChecker.CheckLevel.STRICT);
-        f.getClassResolver().setClassChecker(checker);
-        
checker.allowClasses(SerializerSecurityRegistry.getAllowClassPattern());
+        f.getClassResolver()
+                .setClassChecker((classResolver, className) ->
+                        
SerializerSecurityRegistry.getAllowClassPattern().contains(className));
         return f;
     });
 
-    public static FurySerializerFactory getInstance() {
-        return FACTORY;
+    @Override
+    public byte[] serialize(Object obj) {
+        return FORY.serialize(obj);
     }
 
-    public ThreadSafeFury get() {
-        return FURY;
+    @Override
+    public Object deserialize(byte[] bytes) {
+        return FORY.deserialize(bytes);
     }
 }
diff --git 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeFuryDelegate.java
similarity index 88%
rename from 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
rename to 
serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeFuryDelegate.java
index f99358622a..872558b5be 100644
--- 
a/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializerFactory.java
+++ 
b/serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/ThreadSafeFuryDelegate.java
@@ -22,10 +22,10 @@ import org.apache.fury.ThreadSafeFury;
 import org.apache.fury.config.CompatibleMode;
 import org.apache.fury.config.Language;
 import org.apache.fury.resolver.AllowListChecker;
+import org.apache.seata.core.serializer.Serializer;
 import org.apache.seata.core.serializer.SerializerSecurityRegistry;
 
-public class FurySerializerFactory {
-    private static final FurySerializerFactory FACTORY = new 
FurySerializerFactory();
+public class ThreadSafeFuryDelegate implements Serializer {
 
     private static final ThreadSafeFury FURY = new ThreadLocalFury(classLoader 
-> {
         Fury f = Fury.builder()
@@ -48,11 +48,13 @@ public class FurySerializerFactory {
         return f;
     });
 
-    public static FurySerializerFactory getInstance() {
-        return FACTORY;
+    @Override
+    public byte[] serialize(Object obj) {
+        return FURY.serialize(obj);
     }
 
-    public ThreadSafeFury get() {
-        return FURY;
+    @Override
+    public Object deserialize(byte[] bytes) {
+        return FURY.deserialize(bytes);
     }
 }
diff --git 
a/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
 
b/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
index 79e9325ed8..6ff14c7c13 100644
--- 
a/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
+++ 
b/serializer/seata-serializer-fury/src/test/java/org/apache/seata/serializer/fury/FurySerializerTest.java
@@ -16,16 +16,16 @@
  */
 package org.apache.seata.serializer.fury;
 
+import org.apache.fory.Fory;
 import org.apache.fury.Fury;
 import org.apache.fury.config.CompatibleMode;
-import org.apache.fury.exception.DeserializationException;
-import org.apache.fury.exception.InsecureException;
 import org.apache.seata.core.exception.TransactionExceptionCode;
 import org.apache.seata.core.model.BranchStatus;
 import org.apache.seata.core.model.BranchType;
 import org.apache.seata.core.protocol.ResultCode;
 import org.apache.seata.core.protocol.transaction.BranchCommitRequest;
 import org.apache.seata.core.protocol.transaction.BranchCommitResponse;
+import org.apache.seata.core.serializer.Serializer;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -87,19 +87,91 @@ public class FurySerializerTest {
     public void testUnSafeDeserializer() {
         // Test deserialization of an object that is not in allow list
         TestUnSafeSerializer testUnSafeSerializer = new TestUnSafeSerializer();
-        Fury fury = Fury.builder()
-                .requireClassRegistration(false)
-                .withRefTracking(true)
-                .withCompatibleMode(CompatibleMode.COMPATIBLE)
-                .build();
-        Assertions.assertThrows(
-                DeserializationException.class, () -> 
furySerializer.deserialize(fury.serialize(testUnSafeSerializer)));
+        byte[] bytes = new 
TestSerializerFactory().get().serialize(testUnSafeSerializer);
+        String className = null;
+        try {
+            furySerializer.deserialize(bytes);
+        } catch (Exception e) {
+            className = e.getClass().getSimpleName();
+        }
+        Assertions.assertEquals("DeserializationException", className);
     }
 
     @Test
     public void testUnSafeSerializer() {
         // Test serialization of an object that is not in allow list
         TestUnSafeSerializer testUnSafeSerializer = new TestUnSafeSerializer();
-        Assertions.assertThrows(InsecureException.class, () -> 
furySerializer.serialize(testUnSafeSerializer));
+        String className = null;
+        try {
+            furySerializer.serialize(testUnSafeSerializer);
+        } catch (Exception e) {
+            className = e.getClass().getSimpleName();
+        }
+        Assertions.assertEquals("InsecureException", className);
+    }
+
+    private static class TestSerializerFactory {
+
+        private final Serializer furyDelegate;
+
+        public TestSerializerFactory() {
+            this.furyDelegate = createFuryDelegate();
+        }
+
+        public Serializer get() {
+            return furyDelegate;
+        }
+
+        private Serializer createFuryDelegate() {
+            // First, try to load Apache Fory.
+            try {
+                Class.forName("org.apache.fory.Fury");
+                return new ForyDelegate();
+            } catch (ClassNotFoundException e) {
+            }
+            // If Fory is unavailable, fallback to Fury.
+            try {
+                Class.forName("org.apache.fury.Fury");
+                return new FuryDelegate();
+            } catch (ClassNotFoundException e) {
+                throw new IllegalStateException("Neither Apache Fory nor 
Apache Fury found in classpath", e);
+            }
+        }
+    }
+
+    private static class ForyDelegate implements Serializer {
+
+        @Override
+        public byte[] serialize(Object obj) {
+            Fory fory = Fory.builder()
+                    .requireClassRegistration(false)
+                    .withRefTracking(true)
+                    
.withCompatibleMode(org.apache.fory.config.CompatibleMode.COMPATIBLE)
+                    .build();
+            return fory.serialize(obj);
+        }
+
+        @Override
+        public Object deserialize(byte[] bytes) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private static class FuryDelegate implements Serializer {
+
+        @Override
+        public byte[] serialize(Object obj) {
+            Fury fury = Fury.builder()
+                    .requireClassRegistration(false)
+                    .withRefTracking(true)
+                    .withCompatibleMode(CompatibleMode.COMPATIBLE)
+                    .build();
+            return fury.serialize(obj);
+        }
+
+        @Override
+        public Object deserialize(byte[] bytes) {
+            throw new UnsupportedOperationException();
+        }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to