Chapter 7. Marshalling Java Objects
Marshalling converts Java objects into binary format so they can be transferred over the wire or stored to disk. The reverse process, unmarshalling, transforms data from binary format into Java objects.
Data Grid performs marshalling and unmarshalling to:
- Send data to other Data Grid nodes in a cluster.
- Store data in persistent cache stores.
- Store data in binary format to provide lazy deserialization capabilities.
Data Grid handles marshalling for all internal types. You need to configure marshalling only for the Java objects that you want to store.
Data Grid uses ProtoStream as the default for marshalling Java objects to binary format. Data Grid also provides other Marshaller implementations you can use.
7.1. Using the ProtoStream Marshaller
Data Grid integrates with the ProtoStream API to encode and decode Java objects into Protocol Buffers (Protobuf); a language-neutral, backwards compatible format.
Procedure
-
Create implementations of the ProtoStream
SerializationContextInitializer
interface so that Data Grid can marshall your Java objects. Configure Data Grid to use the implementations.
Programmatically:
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .addContextInitializers(new LibraryInitializerImpl(), new SCIImpl());
Declaratively
<serialization> <context-initializer class="org.infinispan.example.LibraryInitializerImpl"/> <context-initializer class="org.infinispan.example.another.SCIImpl"/> </serialization>
7.2. Using JBoss Marshalling
JBoss Marshalling is a serialization-based marshalling library and was the default marshaller in previous Data Grid versions.
- You should not use serialization-based marshalling with Data Grid. Instead you should use Protostream, which is a high-performance binary wire format that ensures backwards compatibility.
-
JBoss Marshalling and the
AdvancedExternalizer
interface are deprecated and will be removed in a future release. However, Data Grid ignoresAdvancedExternalizer
implementations when persisting data unless you use JBoss Marshalling.
Procedure
-
Add the
infinispan-jboss-marshalling
dependency to your classpath. Configure Data Grid to use the
JBossUserMarshaller
.Programmatically:
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization().marshaller(new JBossUserMarshaller());
Declaratively:
<serialization marshaller="org.infinispan.jboss.marshalling.core.JBossUserMarshaller"/>
7.3. Using Java Serialization
You can use Java serialization with Data Grid to marshall your objects, but only if your Java objects implement Java’s Serializable
interface.
Procedure
-
Configure Data Grid to use
JavaSerializationMarshaller
as the marshaller. Add your Java classes to the deserialization white list.
Programmatically:
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new JavaSerializationMarshaller()) .whiteList() .addRegexps("org.infinispan.example.", "org.infinispan.concrete.SomeClass");
Declaratively:
<serialization marshaller="org.infinispan.commons.marshall.JavaSerializationMarshaller"> <white-list> <class>org.infinispan.concrete.SomeClass</class> <regex>org.infinispan.example.*</regex> </white-list> </serialization>
7.4. Using the Kryo Marshaller
Data Grid provides a marshalling implementation that uses Kryo libraries.
Prerequisites for Data Grid Servers
To use Kryo marshalling with Data Grid servers, add a JAR that includes the runtime class files for the Kryo marshalling implementation as follows:
-
Copy
infinispan-marshaller-kryo-bundle.jar
from the Data Grid Maven repository. -
Add the JAR file to the
server/lib
directory in your Data Grid server installation directory.
Prerequisites for Data Grid Library Mode
To use Kryo marshalling with Data Grid as an embedded library in your application, do the following:
Add the
infinispan-marshaller-kryo
dependency to yourpom.xml
.<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-marshaller-kryo</artifactId> <version>${version.infinispan}</version> </dependency>
Specify the
org.infinispan.marshaller.kryo.KryoMarshaller
class as the marshaller.GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new org.infinispan.marshaller.kryo.KryoMarshaller());
Procedure
-
Implement a service provider for the
SerializerRegistryService.java
interface. Place all serializer registrations in the
register(Kryo)
method; where serializers are registered with the suppliedKryo
object using the Kryo API, for example:kryo.register(ExampleObject.class, new ExampleObjectSerializer())
Specify the full path of implementing classes in your deployment JAR file within:
META-INF/services/org/infinispan/marshaller/kryo/SerializerRegistryService
Reference
7.5. Using the Protostuff Marshaller
Data Grid provides a marshalling implementation that uses Protostuff libraries.
Prerequisites for Data Grid Servers
To use Protostuff marshalling with Data Grid servers, add a JAR that includes the runtime class files for the Protostuff marshalling implementation as follows:
-
Copy
infinispan-marshaller-protostuff-bundle.jar
from the Data Grid Maven repository. -
Add the JAR file to the
server/lib
directory in your Data Grid server installation directory.
Prerequisites for Data Grid Library Mode
To use Protostuff marshalling with Data Grid as an embedded library in your application, do the following:
Add the
infinispan-marshaller-protostuff
dependency to yourpom.xml
.<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-marshaller-protostuff</artifactId> <version>${version.infinispan}</version> </dependency>
Specify the
org.infinispan.marshaller.protostuff.ProtostuffMarshaller
class as the marshaller.GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new org.infinispan.marshaller.protostuff.ProtostuffMarshaller());
Procedure
Do one of the following to register custom Protostuff schemas for object marshalling:
Call the
register()
method.RuntimeSchema.register(ExampleObject.class, new ExampleObjectSchema());
Implement a service provider for the
SerializerRegistryService.java
interface that places all schema registrations in theregister()
method.You should then specify the full path of implementing classes in your deployment JAR file within:
META-INF/services/org/infinispan/marshaller/protostuff/SchemaRegistryService
Reference
7.6. Using Custom Marshallers
Data Grid provides a Marshaller
interface for custom marshallers.
Programmatic procedure
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new org.infinispan.example.marshall.CustomMarshaller()) .whiteList().addRegexp("org.infinispan.example.*");
Declarative procedure
<serialization marshaller="org.infinispan.example.marshall.CustomMarshaller"> <white-list> <class>org.infinispan.concrete.SomeClass</class> <regex>org.infinispan.example.*</regex> </white-list> </serialization>
Custom marshaller implementations can access a configured white list via the initialize() method, which is called during startup.
7.7. Adding Java Classes to Deserialization White Lists
Data Grid does not allow deserialization of arbritrary Java classes for security reasons, which applies to JSON, XML, and marshalled byte[]
content.
You must add Java classes to a deserialization white list, either using system properties or specifying them in the Data Grid configuration.
System properties
// Specify a comma-separated list of fully qualified class names -Dinfinispan.deserialization.whitelist.classes=java.time.Instant,com.myclass.Entity // Specify a regular expression to match classes -Dinfinispan.deserialization.whitelist.regexps=.*
Declarative
<cache-container> <serialization version="1.0" marshaller="org.infinispan.marshall.TestObjectStreamMarshaller"> <white-list> <class>org.infinispan.test.data.Person</class> <regex>org.infinispan.test.data.*</regex> </white-list> </serialization> </cache-container>
Java classes that you add to the deserialization whitelist apply to the Data Grid CacheContainer
and can be deserialized by all caches that the CacheContainer
controls.
7.8. Storing Deserialized Objects in Data Grid Servers
You can configure Data Grid to use the application/x-java-object
MediaType as the format for your data. In other words, Data Grid stores your data as Plain Old Java Objects (POJOs) instead of binary content.
If you store POJOs, you must put class files for all custom objects on the Data Grid server classpath.
Procedure
-
Add JAR files that contain custom classes and/or service providers for marshaller implementations in the
server/lib
directory.
├── server │ ├── lib │ │ ├── UserObjects.jar │ └── README.txt
7.9. Storing Data in Binary Format
Data Grid can store data in its serialized form, in binary format, and then either serialize or deserialize Java objects as needed. This behavior is also referred to as lazy deserialization.
Programmatic procedure
ConfigurationBuilder builder = ... builder.memory().storageType(StorageType.BINARY);
Declarative procedure
<memory> <binary /> </memory>
Equality Considerations
When storing data in binary format, Data Grid uses the WrappedBytes
interface for keys and values. This wrapper class transparently takes care of serialization and deserialization on demand, and internally may have a reference to the object itself being wrapped, or the serialized, byte array representation of the object. This has an effect on the behavior of equality, which is important to note if you implement an equals()
methods on keys.
The equals()
method of the wrapper class either compares binary representations (byte arrays) or delegates to the wrapped object instance’s equals()
method, depending on whether both instances being compared are in serialized or deserialized form at the time of comparison. If one of the instances being compared is in one form and the other in another form, then one instance is either serialized or deserialized.
Reference