Skip to content

Commit c471a22

Browse files
committed
Compatible with Fory
1 parent f87bb2c commit c471a22

File tree

6 files changed

+174
-11
lines changed

6 files changed

+174
-11
lines changed

serializer/seata-serializer-fury/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,17 @@
3737
<artifactId>seata-core</artifactId>
3838
<version>${project.version}</version>
3939
</dependency>
40+
<dependency>
41+
<groupId>${project.groupId}</groupId>
42+
<artifactId>seata-serializer-fory</artifactId>
43+
<version>${project.version}</version>
44+
<scope>provided</scope>
45+
</dependency>
4046

4147
<dependency>
4248
<groupId>org.apache.fury</groupId>
4349
<artifactId>fury-core</artifactId>
50+
<optional>true</optional>
4451
</dependency>
4552
</dependencies>
4653
</project>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.seata.serializer.fury;
18+
19+
import org.apache.seata.core.serializer.Serializer;
20+
21+
public class DynamicSerializerFactory {
22+
private static final DynamicSerializerFactory FACTORY = new DynamicSerializerFactory();
23+
24+
private final Serializer furyDelegate;
25+
26+
private DynamicSerializerFactory() {
27+
this.furyDelegate = createFuryDelegate();
28+
}
29+
30+
public static DynamicSerializerFactory getInstance() {
31+
return FACTORY;
32+
}
33+
34+
public Serializer get() {
35+
return furyDelegate;
36+
}
37+
38+
private Serializer createFuryDelegate() {
39+
// First, try to load seata-serializer-fory.
40+
try {
41+
Class.forName("org.apache.seata.serializer.fory.ForySerializer");
42+
return new ForySerializerDelegate();
43+
} catch (ClassNotFoundException e) {
44+
}
45+
// Second, try to load Apache Fory.
46+
try {
47+
Class.forName("org.apache.fory.Fury");
48+
return new ThreadSafeForyDelegate();
49+
} catch (ClassNotFoundException e) {
50+
}
51+
// If Fory is unavailable, fallback to Fury.
52+
try {
53+
Class.forName("org.apache.fury.Fury");
54+
return new ThreadSafeFuryDelegate();
55+
} catch (ClassNotFoundException e) {
56+
throw new IllegalStateException("Neither Apache Fory nor Apache Fury found in classpath", e);
57+
}
58+
}
59+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.seata.serializer.fury;
18+
19+
import org.apache.seata.core.serializer.Serializer;
20+
import org.apache.seata.serializer.fory.ForySerializer;
21+
22+
public class ForySerializerDelegate implements Serializer {
23+
24+
private static final ForySerializer SERIALIZER = new ForySerializer();
25+
26+
@Override
27+
public byte[] serialize(Object obj) {
28+
return SERIALIZER.serialize(obj);
29+
}
30+
31+
@Override
32+
public Object deserialize(byte[] bytes) {
33+
return SERIALIZER.deserialize(bytes);
34+
}
35+
36+
}

serializer/seata-serializer-fury/src/main/java/org/apache/seata/serializer/fury/FurySerializer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
package org.apache.seata.serializer.fury;
1818

19-
import org.apache.fury.ThreadSafeFury;
2019
import org.apache.seata.common.loader.LoadLevel;
2120
import org.apache.seata.core.protocol.AbstractMessage;
2221
import org.apache.seata.core.serializer.Serializer;
@@ -28,16 +27,16 @@ public <T> byte[] serialize(T t) {
2827
if (!(t instanceof AbstractMessage)) {
2928
throw new IllegalArgumentException("AbstractMessage isn't available.");
3029
}
31-
ThreadSafeFury threadSafeFury = FurySerializerFactory.getInstance().get();
32-
return threadSafeFury.serialize(t);
30+
Serializer serializer = DynamicSerializerFactory.getInstance().get();
31+
return serializer.serialize(t);
3332
}
3433

3534
@Override
3635
public <T> T deserialize(byte[] bytes) {
3736
if (bytes == null || bytes.length == 0) {
3837
throw new IllegalArgumentException("bytes is null");
3938
}
40-
ThreadSafeFury threadSafeFury = FurySerializerFactory.getInstance().get();
41-
return (T) threadSafeFury.deserialize(bytes);
39+
Serializer serializer = DynamicSerializerFactory.getInstance().get();
40+
return (T) serializer.deserialize(bytes);
4241
}
4342
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.seata.serializer.fury;
18+
19+
import org.apache.fory.Fory;
20+
import org.apache.fory.ThreadLocalFory;
21+
import org.apache.fory.ThreadSafeFory;
22+
import org.apache.fory.config.CompatibleMode;
23+
import org.apache.fory.config.Language;
24+
import org.apache.seata.core.serializer.Serializer;
25+
import org.apache.seata.core.serializer.SerializerSecurityRegistry;
26+
27+
public class ThreadSafeForyDelegate implements Serializer {
28+
29+
private static final ThreadSafeFory FORY = new ThreadLocalFory(classLoader -> {
30+
Fory f = Fory.builder()
31+
.withLanguage(Language.JAVA)
32+
// In JAVA mode, classes cannot be registered by tag, and the different registration order between the
33+
// server and the client will cause deserialization failure
34+
// In XLANG cross-language mode has problems with Java class serialization, such as enum classes
35+
// [https://github.com/apache/fory/issues/1644].
36+
.requireClassRegistration(false)
37+
// enable reference tracking for shared/circular reference.
38+
.withRefTracking(true)
39+
.withClassLoader(classLoader)
40+
.withCompatibleMode(CompatibleMode.COMPATIBLE)
41+
.build();
42+
43+
// register allow class
44+
f.getClassResolver()
45+
.setClassChecker((classResolver, className) ->
46+
SerializerSecurityRegistry.getAllowClassPattern().contains(className));
47+
return f;
48+
});
49+
50+
@Override
51+
public byte[] serialize(Object obj) {
52+
return FORY.serialize(obj);
53+
}
54+
55+
@Override
56+
public Object deserialize(byte[] bytes) {
57+
return FORY.deserialize(bytes);
58+
}
59+
60+
}
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
import org.apache.fury.config.CompatibleMode;
2323
import org.apache.fury.config.Language;
2424
import org.apache.fury.resolver.AllowListChecker;
25+
import org.apache.seata.core.serializer.Serializer;
2526
import org.apache.seata.core.serializer.SerializerSecurityRegistry;
2627

27-
public class FurySerializerFactory {
28-
private static final FurySerializerFactory FACTORY = new FurySerializerFactory();
28+
public class ThreadSafeFuryDelegate implements Serializer {
2929

3030
private static final ThreadSafeFury FURY = new ThreadLocalFury(classLoader -> {
3131
Fury f = Fury.builder()
@@ -48,11 +48,13 @@ public class FurySerializerFactory {
4848
return f;
4949
});
5050

51-
public static FurySerializerFactory getInstance() {
52-
return FACTORY;
51+
@Override
52+
public byte[] serialize(Object obj) {
53+
return FURY.serialize(obj);
5354
}
5455

55-
public ThreadSafeFury get() {
56-
return FURY;
56+
@Override
57+
public Object deserialize(byte[] bytes) {
58+
return FURY.deserialize(bytes);
5759
}
5860
}

0 commit comments

Comments
 (0)