package org.infinispan.commons.marshall; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; /** * One of the key aspects of Infinispan is that it often needs to marshall or * unmarshall objects in order to provide some of its functionality. For * example, if it needs to store objects in a write-through or write-behind * cache store, the objects stored need marshalling. If a cluster of * Infinispan nodes is formed, objects shipped around need marshalling. Even * if you enable storing as binary, objects need to marshalled so that they * can be lazily unmarshalled with the correct classloader. * * Using standard JDK serialization is slow and produces payloads that are too * big and can affect bandwidth usage. On top of that, JDK serialization does * not work well with objects that are supposed to be immutable. In order to * avoid these issues, Infinispan uses JBoss Marshalling for * marshalling/unmarshalling objects. JBoss Marshalling is fast, provides * very space efficient payloads, and on top of that, allows users to * construct objects themselves during unmarshalling, hence allowing objects * to carry on being immutable. * * Starting with 5.0, users of Infinispan can now benefit from this marshalling * framework as well. In the simplest possible form, users just need to * provide an {@link Externalizer} implementation for the type that they want * to marshall/unmarshall, and then annotate the marshalled type class with * {@link SerializeWith} indicating the externalizer class to use and that's * all about it. At runtime JBoss Marshaller will inspect the object and * discover that's marshallable thanks to the annotation and so marshall it * using the externalizer class passed. * * It's common practice to include externalizer implementations within the * classes that they marshall/unmarshall as <code>public static classes</code>. * To make externalizer implementations easier to code and more typesafe, make * sure you define type <T> as the type of object that's being * marshalled/unmarshalled. * * Even though this way of defining externalizers is very user friendly, it has * some disadvantages: * * <ul> * <li>Due to several constraints of the model, such as support different * versions of the same class or the need to marshall the Externalizer * class, the payload sizes generated via this method are not the most * efficient.</li> * <li>This model requires for the marshalled class to be annoated with * {@link SerializeWith} but a user might need to provide an Externalizer * for a class for which source code is not available, or for any other * constraints, it cannot be modified.</li> * <li>The use of annotations by this model might be limiting for framework * developers or service providers that try to abstract lower level * details, such as the marshalling layer, away from the user.</li> * </ul> * * If you're affected by any of these disadvantages, an alternative mechanism * to provide externalizers is available via {@link AdvancedExternalizer}. * More details can be found in this interface's javadoc. * * Please note that even though Externalizer is marked as {@link Serializable}, * the need to marshall the externalizer is only really needed when developing * user friendly externalizers (using {@link SerializeWith}). {@link AdvancedExternalizer} * instances do not require the externalizer to be serializable since the * externalizer itself is not marshalled. * * Even though it's not strictly necessary, to avoid breaking compatibility * with old clients, {@link Externalizer} implements {@link Serializable} but * this requirement is only needed for those user friendly externalizers. * There's a chance that in future major releases {@link Externalizer} won't * extend {@link Serializable} any more, hence we strongly recommend that any * user-friendly externalizer users mark their externalizer implementations as * either {@link Serializable} or {@link java.io.Externalizable}. * * @author Galder ZamarreƱo * @since 5.0 */ public interface Externalizer<T> extends Serializable { /** * Write the object reference to the stream. * * @param output the object output to write to * @param object the object reference to write * @throws IOException if an I/O error occurs */ void writeObject(ObjectOutput output, T object) throws IOException; /** * Read an instance from the stream. The instance will have been written by the * {@link #writeObject(ObjectOutput, Object)} method. Implementations are free * to create instances of the object read from the stream in any way that they * feel like. This could be via constructor, factory or reflection. * * @param input the object input to read from * @return the object instance * @throws IOException if an I/O error occurs * @throws ClassNotFoundException if a class could not be found */ T readObject(ObjectInput input) throws IOException, ClassNotFoundException; }