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]