Skip to content

Instantly share code, notes, and snippets.

@mcollovati
Last active March 28, 2018 19:36
Show Gist options
  • Save mcollovati/c1fecceca661c6c6344fd86672baf099 to your computer and use it in GitHub Desktop.
Save mcollovati/c1fecceca661c6c6344fd86672baf099 to your computer and use it in GitHub Desktop.
Vertx Session Serialization
class ExtendedSessionImpl ExtendedSessionImpl implements ExtendedSession, Shareable, ClusterSerializable {
// The original Vert.x Session
// I need to expand it with the createdAt attribute
Session delegate;
@Override
public void writeToBuffer(Buffer buffer) {
buffer.appendLong(createdAt);
if (useKryo) {
Kryo kryo = KryoSupport.kryo();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (Output output = new Output(outputStream)) {
kryo.writeClassAndObject(output, delegate);
}
byte[] bytes = outputStream.toByteArray();
buffer.appendInt(bytes.length);
buffer.appendBytes(bytes);
} else {
((ClusterSerializable)delegate).writeToBuffer(buffer);
}
}
@Override
public int readFromBuffer(int pos, Buffer buffer) {
createdAt = buffer.getLong(pos);
pos += 8;
int end;
if (useKryo) {
int delegateLength = buffer.getInt(pos);
pos += 4;
end = pos + delegateLength;
Kryo kryo = KryoSupport.kryo();
try (Input input = new Input(buffer.getBytes(pos, pos + delegateLength))) {
input.close();
this.delegate = (Session) kryo.readClassAndObject(input);
}
} else {
end = ((ClusterSerializable)delegate).readFromBuffer(pos, buffer);
}
return end;
}
}
package com.github.mcollovati.vertx.web.sstore;
import java.io.ByteArrayOutputStream;
import java.util.Objects;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.ByteBufferInput;
import com.esotericsoftware.kryo.io.ByteBufferOutput;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.FieldSerializer;
import io.vertx.core.cli.impl.ReflectionUtils;
import org.fest.reflect.core.Reflection;
import org.fest.reflect.exception.ReflectionError;
import org.fest.reflect.field.Invoker;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.in;
public class KryoTest {
Kryo kryo = KryoSupport.kryo();
@Test
public void shouldSerializeWithNonDefaultCtor() {
MyClass obj = new MyClass("Marco", "Collovati");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (Output output = new ByteBufferOutput(baos)) {
kryo.writeObject(output, obj);
}
MyClass deserialised;
try (Input input = new ByteBufferInput(baos.toByteArray())) {
deserialised = kryo.readObject(input, MyClass.class);
}
assertThat(deserialised)
.isNotSameAs(obj).isEqualTo(obj);
}
@Test
public void shouldSerializeWithNonDefaultCtorAndCustomSerializer() {
MyClass obj = new MyClass("Marco", "Collovati");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Serializer<MyClass> serializer = new FieldSerializer<MyClass>(kryo, MyClass.class) {
@Override
public MyClass read(Kryo kryo, Input input, Class<MyClass> type) {
MyClass obj = super.read(kryo, input, type);
Injector.deserialise(obj);
return obj;
}
};
try (Output output = new ByteBufferOutput(baos)) {
kryo.writeObject(output, obj, serializer);
}
MyClass deserialised;
try (Input input = new ByteBufferInput(baos.toByteArray())) {
deserialised = kryo.readObject(input, MyClass.class, serializer);
}
assertThat(deserialised)
.isNotEqualTo(obj)
.extracting(m -> m.firstName, m -> m.lastName)
.containsExactly("Deserialised " + obj.firstName, obj.lastName);
}
@Test
public void shouldSerializeWithNonDefaultCtorAndTransientFields() {
MyClass2 obj = new MyClass2("Marco", "Collovati");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FieldSerializer<MyClass2> serializer = new FieldSerializer<>(kryo, MyClass2.class);
serializer.setSerializeTransient(true);
try (Output output = new ByteBufferOutput(baos)) {
kryo.writeObject(output, obj, serializer);
}
MyClass2 deserialised;
try (Input input = new ByteBufferInput(baos.toByteArray())) {
deserialised = kryo.readObject(input, MyClass2.class, serializer);
}
assertThat(deserialised)
.isNotSameAs(obj).isEqualTo(obj);
}
public static class MyClass {
private final String firstName;
private final String lastName;
public MyClass(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format("%s %s", firstName, lastName);
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (!(o instanceof MyClass)) { return false; }
MyClass myClass = (MyClass) o;
return Objects.equals(firstName, myClass.firstName) &&
Objects.equals(lastName, myClass.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
private void refreshTransients(Injector injector) {
assertThat(injector).isNotNull();
Reflection.field("firstName").ofType(String.class).in(this)
.set("Deserialised " + this.firstName);
}
}
public static class MyClass2 {
private final transient String firstName;
private final transient String lastName;
public MyClass2(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format("%s %s", firstName, lastName);
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (!(o instanceof MyClass2)) { return false; }
MyClass2 myClass = (MyClass2) o;
return Objects.equals(firstName, myClass.firstName) &&
Objects.equals(lastName, myClass.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
}
static class Injector {
private static final Injector injector = new Injector();
static void deserialise(Object object) {
try {
org.fest.reflect.method.Invoker<Void> deserialiser = Reflection.method("refreshTransients")
.withReturnType(void.class)
.withParameterTypes(Injector.class).in(object);
deserialiser.invoke(injector);
} catch (ReflectionError ex) {
// No custom method found; Do nothing
}
}
<T> T getInstance(Class<T> type) {
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment