Skip to content

A blazingly fast multi-language serialization framework powered by JIT and zero-copy.

License

Notifications You must be signed in to change notification settings

quarkiverse/quarkus-fury

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quarkus Fury

All Contributors

Version

Quarkus Fury is a Quarkus extension to use Apache Fury for serialization.

Documentation

The documentation for this extension can be found here while the documentation for the Apache Fury can be found at https://fury.apache.org/.

Getting Started

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);
  }
}

Use Apache Fury with Quarkus REST/RESTEasy

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.

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);
  }
}

Class registration disabled

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.

Contributors ✨

Thanks go to these wonderful people (emoji key):

Shawn Yang
Shawn Yang

💻 🚧
Zheng Feng
Zheng Feng

💻 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!