Quarkus Fury is a Quarkus extension to use Apache Fury for serialization.
The documentation for this extension can be found here while the documentation for the Apache Fury can be found at https://fury.apache.org/.
import java.util.List;
import java.util.Map;
import io.quarkiverse.fury.FurySerialization;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.apache.fury.BaseFury;
@FurySerialization
record Foo(int f1, String f2, List<String> f3, Map<String, Long> f4) {
}
@Path("/fury")
@ApplicationScoped
public class FuryResources {
@Inject
BaseFury fury;
@GET
@Path("/record")
public Boolean testSerializeFooRecord() {
Foo foo1 = new Foo(10, "abc", List.of("str1", "str2"), Map.of("k1", 10L, "k2", 20L));
Foo foo2 = (Foo) fury.deserialize(fury.serialize(foo1));
return foo1.equals(foo2);
}
}
You can send a http request with Fury protocol, and let Fury to handle your objects serialization.
The usage will be different if class registration is disabled or enabled:
- Enable class registration: you must register class with same ID as the server, you should assign an id using
@FurySerialization(classId = xxx)
, otherwise Fury will allocate an auto-generated ID which you won't know at the client for registration. - Disable class registration: no class id are needed to register, which is more easy to use, but the serialized size
will be larger since Fury will serialize class as a string instead of an id. Note that
quarkus-fury
will only allow classes annotated by@FurySerialization
for deserialization, the deserialization will be safe as class registration enabled.
Server example:
import io.quarkiverse.fury.FurySerialization;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@FurySerialization(classId = 100)
record Struct(int f1, String f2) {
}
@Path("/fury")
@ApplicationScoped
public class FuryResources {
@POST
@Path("/struct")
@Produces("application/fury")
@Consumes("application/fury")
public Struct testStruct(Struct obj) {
return new Struct(10, "abc");
}
}
Client example:
import static io.restassured.RestAssured.given;
import org.apache.fury.ThreadSafeFury;
import io.restassured.RestAssured;
import io.restassured.response.Response;
public class FuryClient {
private static ThreadSafeFury fury = Fury.builder().requireClassRegistration(false).buildThreadSafeFury();
static {
fury.register(Struct.class, 100, true);
}
public static void main(String[] args) {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
Struct struct = Struct.create();
Response response = given().contentType("application/fury").body(fury.serialize(struct)).when()
.post("/fury/struct").then().statusCode(200).contentType("application/fury").extract().response();
byte[] result = response.body().asByteArray();
Struct struct1 = (Struct) fury.deserialize(result);
System.out.println(struct1);
}
}
Server example:
@FurySerialization
record Struct(int f1, String f2) {
}
@Path("/fury")
@ApplicationScoped
public class FuryResources {
@POST
@Path("/struct")
@Produces("application/fury")
@Consumes("application/fury")
public Struct testStruct(Struct obj) {
return new Struct(10, "abc");
}
}
Client example
public class RestClient {
private static ThreadSafeFury fury = Fury.builder().requireClassRegistration(false).buildThreadSafeFury();
public static void main(String[] args) {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
Struct struct = Struct.create();
Response response = given().contentType("application/fury").body(fury.serialize(struct)).when()
.post("/fury/struct").then().statusCode(200).contentType("application/fury").extract().response();
byte[] result = response.body().asByteArray();
Struct struct1 = (Struct) fury.deserialize(result);
System.out.println(struct1);
}
}
More details about usage can be found here.
Thanks go to these wonderful people (emoji key):
Shawn Yang 💻 🚧 |
Zheng Feng 💻 🚧 |
This project follows the all-contributors specification. Contributions of any kind welcome!