-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes to support better separation between applying global and type serialization #7
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package info.jerrinot.subzero; | ||
|
||
import info.jerrinot.subzero.internal.strategy.GlobalKryoStrategy; | ||
|
||
public abstract class AbstractGlobalUserSerializer<T> extends AbstractSerializer<T> { | ||
|
||
public AbstractGlobalUserSerializer(UserSerializer userSerializer) { | ||
super(new GlobalKryoStrategy(userSerializer)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package info.jerrinot.subzero; | ||
|
||
import com.hazelcast.core.HazelcastInstance; | ||
import com.hazelcast.core.HazelcastInstanceAware; | ||
import com.hazelcast.nio.ObjectDataInput; | ||
import com.hazelcast.nio.ObjectDataOutput; | ||
import com.hazelcast.nio.serialization.StreamSerializer; | ||
import info.jerrinot.subzero.internal.strategy.KryoStrategy; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
|
||
public abstract class AbstractSerializer<T> implements StreamSerializer<T>, HazelcastInstanceAware { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this probably should be package private, not |
||
private int autoGeneratedTypeId; | ||
private HazelcastInstance hazelcastInstance; | ||
private KryoStrategy<T> strategy; | ||
|
||
AbstractSerializer(KryoStrategy<T> strategy) { | ||
this.strategy = strategy; | ||
} | ||
|
||
@Override | ||
public final void write(ObjectDataOutput out, T object) throws IOException { | ||
strategy.write((OutputStream) out, object); | ||
} | ||
|
||
@Override | ||
public final T read(ObjectDataInput in) throws IOException { | ||
return strategy.read((InputStream) in); | ||
} | ||
|
||
/** | ||
* Override this method to returns your own type ID. | ||
* <p> | ||
* Default implementation relies on serializers registration order - all | ||
* your cluster members have to register SubZero in the same order otherwise | ||
* things will get out-of-sync you you will get tons of serializations errors. | ||
* <p> | ||
* All serializers registered in Hazelcast have to return a unique type ID. | ||
* | ||
* @return serializer type ID. | ||
*/ | ||
@Override | ||
public int getTypeId() { | ||
return autoGeneratedTypeId; | ||
} | ||
|
||
@Override | ||
public final void destroy() { | ||
strategy.destroy(hazelcastInstance); | ||
} | ||
|
||
@Override | ||
public final void setHazelcastInstance(HazelcastInstance hazelcastInstance) { | ||
strategy.setHazelcastInstance(hazelcastInstance); | ||
this.hazelcastInstance = hazelcastInstance; | ||
this.autoGeneratedTypeId = strategy.newId(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package info.jerrinot.subzero; | ||
|
||
import info.jerrinot.subzero.internal.PropertyUserSerializer; | ||
import info.jerrinot.subzero.internal.strategy.TypedKryoStrategy; | ||
|
||
public abstract class AbstractTypeSpecificUserSerializer<T> extends AbstractSerializer<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JavaDoc is needed here. with a description when and how-to extend this class |
||
|
||
public AbstractTypeSpecificUserSerializer(Class<T> clazz, com.esotericsoftware.kryo.Serializer serializer) { | ||
super(new TypedKryoStrategy<T>(clazz, UserSerializerConfig.register(clazz, serializer))); | ||
} | ||
|
||
/** | ||
* @param clazz class this serializer uses. | ||
* | ||
*/ | ||
public AbstractTypeSpecificUserSerializer(Class<T> clazz) { | ||
super(new TypedKryoStrategy<T>(clazz, new PropertyUserSerializer())); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,21 @@ | ||
package info.jerrinot.subzero; | ||
|
||
import com.hazelcast.core.HazelcastInstance; | ||
import com.hazelcast.core.HazelcastInstanceAware; | ||
import com.hazelcast.nio.ObjectDataInput; | ||
import com.hazelcast.nio.ObjectDataOutput; | ||
import com.hazelcast.nio.serialization.StreamSerializer; | ||
import info.jerrinot.subzero.internal.PropertyUserSerializer; | ||
import info.jerrinot.subzero.internal.strategy.GlobalKryoStrategy; | ||
import info.jerrinot.subzero.internal.strategy.KryoStrategy; | ||
import info.jerrinot.subzero.internal.strategy.TypedKryoStrategy; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
|
||
public class Serializer<T> implements StreamSerializer<T>, HazelcastInstanceAware { | ||
private int autoGeneratedTypeId; | ||
private HazelcastInstance hazelcastInstance; | ||
private KryoStrategy<T> strategy; | ||
public final class Serializer<T> extends AbstractSerializer<T> { | ||
|
||
Serializer() { | ||
this.strategy = new GlobalKryoStrategy<T>(userSerializers()); | ||
super(new GlobalKryoStrategy<T>(new PropertyUserSerializer())); | ||
} | ||
|
||
/** | ||
* @param clazz class this serializer uses. | ||
* | ||
*/ | ||
public Serializer(Class<T> clazz) { | ||
this.strategy = new TypedKryoStrategy<T>(clazz, userSerializers()); | ||
} | ||
|
||
@Override | ||
public final void write(ObjectDataOutput out, T object) throws IOException { | ||
strategy.write((OutputStream) out, object); | ||
} | ||
|
||
@Override | ||
public final T read(ObjectDataInput in) throws IOException { | ||
return strategy.read((InputStream) in); | ||
super(new TypedKryoStrategy<T>(clazz, new PropertyUserSerializer())); | ||
} | ||
|
||
public UserSerializer userSerializers() { | ||
return new PropertyUserSerializer(); | ||
} | ||
|
||
/** | ||
* Override this method to returns your own type ID. | ||
* | ||
* Default implementation relies on serializers registration order - all | ||
* your cluster members have to register SubZero in the same order otherwise | ||
* things will get out-of-sync you you will get tons of serializations errors. | ||
* | ||
* All serializers registered in Hazelcast have to return a unique type ID. | ||
* | ||
* @return serializer type ID. | ||
*/ | ||
@Override | ||
public int getTypeId() { | ||
return autoGeneratedTypeId; | ||
} | ||
|
||
@Override | ||
public final void destroy() { | ||
strategy.destroy(hazelcastInstance); | ||
} | ||
|
||
@Override | ||
public final void setHazelcastInstance(HazelcastInstance hazelcastInstance) { | ||
strategy.setHazelcastInstance(hazelcastInstance); | ||
this.hazelcastInstance = hazelcastInstance; | ||
this.autoGeneratedTypeId = strategy.newId(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,22 +23,38 @@ private SubZero() { | |
* Use SubZero as a global serializer. | ||
* | ||
* This method configures Hazelcast to delegate a class serialization to SubZero when the class | ||
* has no explicit strategy configured. | ||
* has no explicit strategy configured. Uses {@link Serializer} serializer implementation | ||
* internally. | ||
* | ||
* @param config Hazelcast configuration to inject SubZero into | ||
* @return Hazelcast configuration. | ||
*/ | ||
public static Config useAsGlobalSerializer(Config config) { | ||
return useAsGlobalSerializerInternal(config, Serializer.class); | ||
} | ||
|
||
/** | ||
* Use SubZero as a global serializer. | ||
* | ||
* This method configures Hazelcast to delegate a class serialization to SubZero when the class | ||
* has no explicit strategy configured. | ||
* | ||
* @param config Hazelcast configuration to inject SubZero into | ||
* @param serializerClazz Class of global serializer implementation to use | ||
* @return Hazelcast configuration. | ||
*/ | ||
public static <T> Config useAsGlobalSerializer(Config config, Class<? extends AbstractGlobalUserSerializer> serializerClazz) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not add this method. Methods in the I expect majority of users won't/shouldn't need to create custom subclasses. The extra methods here could be confusing for new users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way I see it, SubZero is all about providing convenience, so I'm not convinced about not having some convenience method to add custom serialization configuration. The alternative is forcing the user to write out what's already available internally to SubZero class when registering the custom global serializer to hazelcast, which seems a waste. I couldn't comment on how widely used custom serialization is (probably about 10% of Kryo users going by github stars https://github.com/magro/kryo-serializers) but I will remove the methods if you're not convinced. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, makes sense. let's keep it in. |
||
SerializationConfig serializationConfig = config.getSerializationConfig(); | ||
injectSubZero(serializationConfig); | ||
injectSubZero(serializationConfig, serializerClazz); | ||
return config; | ||
} | ||
|
||
/** | ||
* Use SubZero as a global serializer. | ||
* | ||
* This method configures Hazelcast to delegate a class serialization to SubZero when the class | ||
* has no explicit strategy configured. | ||
* has no explicit strategy configured. Uses {@link Serializer} serializer implementation | ||
* internally. | ||
* | ||
* This method it intended to be used to configure {@link ClientConfig} instances, but | ||
* I do not want to create a hard-dependency on Hazelcast Client module. | ||
|
@@ -47,6 +63,27 @@ public static Config useAsGlobalSerializer(Config config) { | |
* @return Hazelcast configuration. | ||
*/ | ||
public static <T> T useAsGlobalSerializer(T config) { | ||
return useAsGlobalSerializerInternal(config, Serializer.class); | ||
} | ||
|
||
/** | ||
* Use SubZero as a global serializer. | ||
* | ||
* This method configures Hazelcast to delegate a class serialization to SubZero when the class | ||
* has no explicit strategy configured. | ||
* | ||
* This method it intended to be used to configure {@link ClientConfig} instances, but | ||
* I do not want to create a hard-dependency on Hazelcast Client module. | ||
* | ||
* @param config Hazelcast configuration to inject SubZero into | ||
* @param serializerClazz Class of global serializer implementation to use | ||
* @return Hazelcast configuration. | ||
*/ | ||
public static <T> T useAsGlobalSerializer(T config, Class<? extends AbstractGlobalUserSerializer> serializerClazz) { | ||
return useAsGlobalSerializer(config, serializerClazz); | ||
} | ||
|
||
private static <T> T useAsGlobalSerializerInternal(T config, Class<? extends AbstractSerializer> serializerClazz) { | ||
String className = config.getClass().getName(); | ||
SerializationConfig serializationConfig; | ||
if (className.equals("com.hazelcast.client.config.ClientConfig")) { | ||
|
@@ -58,17 +95,17 @@ public static <T> T useAsGlobalSerializer(T config) { | |
} else { | ||
throw new IllegalArgumentException("Unknown configuration object " + config); | ||
} | ||
injectSubZero(serializationConfig); | ||
injectSubZero(serializationConfig, serializerClazz); | ||
return config; | ||
} | ||
|
||
private static void injectSubZero(SerializationConfig serializationConfig) { | ||
private static void injectSubZero(SerializationConfig serializationConfig, Class<? extends AbstractSerializer> serializerClazz) { | ||
GlobalSerializerConfig globalSerializerConfig = serializationConfig.getGlobalSerializerConfig(); | ||
if (globalSerializerConfig == null) { | ||
globalSerializerConfig = new GlobalSerializerConfig(); | ||
serializationConfig.setGlobalSerializerConfig(globalSerializerConfig); | ||
} | ||
globalSerializerConfig.setClassName(Serializer.class.getName()).setOverrideJavaSerialization(true); | ||
globalSerializerConfig.setClassName(serializerClazz.getName()).setOverrideJavaSerialization(true); | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JavaDoc is missing. I think users will need to extend this classes if and only if
Is this correct? Do you see any other user-case?