public class MatsSerializerJson extends java.lang.Object implements MatsSerializer<java.lang.String>
MatsSerializer
that employs Jackson JSON
library for serialization and deserialization, and compress and decompress using Deflater
and
Inflater
.
The Jackson ObjectMapper
is configured to only handle fields (think "data struct"), i.e. not use setters or
getters; and to only include non-null fields; and upon deserialization to ignore properties from the JSON that has no
field in the class to be deserialized into (both to enable the modification of DTOs on the client side by removing
fields that aren't used in that client scenario, and to handle widening conversions for incoming DTOs), and to
use string serialization for dates (and handle the JSR310 new dates):
// Create Jackson ObjectMapper ObjectMapper mapper = new ObjectMapper(); // Do not use setters and getters, thus only fields, and ignore visibility modifiers. mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); // Drop null fields (null fields in DTOs are dropped from serialization to JSON) mapper.setSerializationInclusion(Include.NON_NULL); // Do not fail on unknown fields (i.e. if DTO class to deserialize to lacks fields that are present in the JSON) mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Handle the java.time classes sanely, i.e. as dates, not a bunch of integers. mapper.registerModule(new JavaTimeModule()); // .. and write dates and times as Strings, e.g. 2020-11-15 mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // Handle JDK8 Optionals as normal fields. mapper.registerModule(new Jdk8Module());
MatsSerializer.DeserializedMatsTrace<Z>, MatsSerializer.SerializationException, MatsSerializer.SerializedMatsTrace
Modifier and Type | Field and Description |
---|---|
static int |
DEFAULT_COMPRESSION_LEVEL
The default compression level - which I chose to be
Deflater.BEST_SPEED (compression level 1), since I
assume that the rather small incremental reduction in size does not outweigh the pretty large increase in time,
as one hopefully runs on a pretty fast network (and that the MQ backing store is fast). |
static java.lang.String |
IDENTIFICATION |
META_KEY_POSTFIX
Modifier | Constructor and Description |
---|---|
protected |
MatsSerializerJson(int compressionLevel)
Constructs a MatsSerializer, using the specified Compression Level - refer to
Deflater 's constants and
levels. |
Modifier and Type | Method and Description |
---|---|
protected byte[] |
compress(byte[] data) |
static MatsSerializerJson |
create()
Constructs a MatsSerializer, using the
DEFAULT_COMPRESSION_LEVEL (which is Deflater.BEST_SPEED ,
which is 1). |
static MatsSerializerJson |
create(int compressionLevel)
Constructs a MatsSerializer, using the specified Compression Level - refer to
Deflater 's constants and
levels. |
MatsTrace<java.lang.String> |
createNewMatsTrace(java.lang.String traceId,
java.lang.String flowId,
MatsTrace.KeepMatsTrace keepMatsTrace,
boolean nonPersistent,
boolean interactive,
long ttlMillis,
boolean noAudit)
Used when initiating a new Mats flow.
|
protected byte[] |
decompress(byte[] data,
int offset,
int length,
int bestGuessDecompressedSize) |
MatsSerializer.DeserializedMatsTrace<java.lang.String> |
deserializeMatsTrace(byte[] matsTraceBytes,
int offset,
int length,
java.lang.String meta)
Used for deserializing a byte array into a
MatsTrace - this includes offset and length. |
MatsSerializer.DeserializedMatsTrace<java.lang.String> |
deserializeMatsTrace(byte[] matsTraceBytes,
java.lang.String meta)
Used for deserializing a byte array into a
MatsTrace - this uses the entire byte array. |
<T> T |
deserializeObject(java.lang.String serialized,
java.lang.Class<T> type)
Used for deserializing type Z (typically
String ) to STOs and DTOs. |
boolean |
handlesMeta(java.lang.String meta)
Whether this implementation of MatsSerializer handles the specified
"meta" . |
<T> T |
newInstance(java.lang.Class<T> clazz)
Will return a new instance of the requested type.
|
MatsSerializer.SerializedMatsTrace |
serializeMatsTrace(MatsTrace<java.lang.String> matsTrace)
Used for serializing the
MatsTrace to a byte array. |
java.lang.String |
serializeObject(java.lang.Object object)
Used for serializing STOs and DTOs into type Z, typically
String . |
int |
sizeOfSerialized(java.lang.String s) |
public static java.lang.String IDENTIFICATION
public static int DEFAULT_COMPRESSION_LEVEL
Deflater.BEST_SPEED
(compression level 1), since I
assume that the rather small incremental reduction in size does not outweigh the pretty large increase in time,
as one hopefully runs on a pretty fast network (and that the MQ backing store is fast).protected MatsSerializerJson(int compressionLevel)
Deflater
's constants and
levels.compressionLevel
- the compression level given to Deflater
to use.public static MatsSerializerJson create()
DEFAULT_COMPRESSION_LEVEL
(which is Deflater.BEST_SPEED
,
which is 1).public static MatsSerializerJson create(int compressionLevel)
Deflater
's constants and
levels.compressionLevel
- the compression level given to Deflater
to use.public boolean handlesMeta(java.lang.String meta)
MatsSerializer
"meta"
.
This feature can at some point be used to configure up a bunch of serializers, whereby the one that handles the incoming format gets the job to deserialize it into a MatsTrace. One can then also migrate to a newer version in a two (three)-step fashion: First make a revision-change that includes the new serializer version, but still employs the old for serialization. Then, when all parties are upgraded to the new config, you make a new revision or minor change that changes the config to employ the new serializer for serialization. Then, when all parties are up on this version, you can potentially make a third version that removes the old serializer.
handlesMeta
in interface MatsSerializer<java.lang.String>
public MatsTrace<java.lang.String> createNewMatsTrace(java.lang.String traceId, java.lang.String flowId, MatsTrace.KeepMatsTrace keepMatsTrace, boolean nonPersistent, boolean interactive, long ttlMillis, boolean noAudit)
MatsSerializer
MatsTrace
implementation is dependent on the
serialization mechanism in use, we need a way provided by the serializer to instantiate new instances of the
implementation of MatsTrace. A MatsTrace.Call
must be added before it is good to be sent.createNewMatsTrace
in interface MatsSerializer<java.lang.String>
traceId
- the Trace Id of this new MatsTrace
.flowId
- System-defined id for this call flow - guaranteed unique.keepMatsTrace
- to which extent the MatsTrace should "keep trace", i.e. whether all Calls and States should be kept
through the entire flow from initiation to terminator - default shall be
MatsTrace.KeepMatsTrace.COMPACT
. The only reason for why this exists is for debugging: The
implementation cannot depend on this feature. To see the call history, do a toString() on the
ProcessContext of the lambda, which should perform a toString() on the corresponding MatsTrace, which
should have a human readable trace output.nonPersistent
- whether the message should be JMS-style "non-persistent" - default shall be false
, i.e.
the default is that a message is persistent.interactive
- whether the message should be prioritized in that a human is actively waiting for the reply, default
shall be false
.ttlMillis
- the number of milliseconds the message should live before being time out. 0 means "forever", and is
the default.noAudit
- hint to the underlying implementation, or to any monitoring/auditing tooling on the Message Broker,
that it does not make much value in auditing this message flow, typically because it is just a
"getter" of information to show to some user, or a health-check validating that some service is up and
answers in a timely fashion.MatsTrace
implementation.public MatsSerializer.SerializedMatsTrace serializeMatsTrace(MatsTrace<java.lang.String> matsTrace)
MatsSerializer
MatsTrace
to a byte array.serializeMatsTrace
in interface MatsSerializer<java.lang.String>
matsTrace
- the MatsTrace
instance to serialize.MatsTrace
.MatsSerializer.META_KEY_POSTFIX
public MatsSerializer.DeserializedMatsTrace<java.lang.String> deserializeMatsTrace(byte[] matsTraceBytes, java.lang.String meta)
MatsSerializer
MatsTrace
- this uses the entire byte array.deserializeMatsTrace
in interface MatsSerializer<java.lang.String>
matsTraceBytes
- the byte array from which to reconstitute the MatsTrace
.meta
- some meta information that the deserialized needs back from the
serialization process
.MatsTrace
.MatsSerializer.META_KEY_POSTFIX
public MatsSerializer.DeserializedMatsTrace<java.lang.String> deserializeMatsTrace(byte[] matsTraceBytes, int offset, int length, java.lang.String meta)
MatsSerializer
MatsTrace
- this includes offset and length.deserializeMatsTrace
in interface MatsSerializer<java.lang.String>
matsTraceBytes
- the byte array from which to reconstitute the MatsTrace
.offset
- from where to start in the byte array.length
- how many bytes to use of the byte array, from the offset.meta
- some meta information that the deserialized needs back from the
serialization process
.MatsTrace
.MatsSerializer.META_KEY_POSTFIX
public java.lang.String serializeObject(java.lang.Object object)
MatsSerializer
String
.
If null
is provided as the Object parameter, then null
shall be returned.
serializeObject
in interface MatsSerializer<java.lang.String>
object
- the object to serialize. If null
is provided, then null
shall be returned.null
if null was provided as 'object'.public int sizeOfSerialized(java.lang.String s)
sizeOfSerialized
in interface MatsSerializer<java.lang.String>
null
. This
is meant for metrics, NOT for determining an absolute byte size for a storage array or anything to this
effect.public <T> T deserializeObject(java.lang.String serialized, java.lang.Class<T> type)
MatsSerializer
String
) to STOs and DTOs.
If null
is provided as the 'Z serialized' parameter, then null
shall be returned.
deserializeObject
in interface MatsSerializer<java.lang.String>
serialized
- the value of type T that should be deserialized into an object of Class T. If null
is
provided, then null
shall be returned.type
- the Class that the supplied value of type Z is thought to represent (i.e. the STO or DTO class).null
if null was provided as 'serialized'.public <T> T newInstance(java.lang.Class<T> clazz)
MatsSerializer
newInstance
in interface MatsSerializer<java.lang.String>
T
- the type of that class.clazz
- Which class you want an object of.protected byte[] compress(byte[] data)
protected byte[] decompress(byte[] data, int offset, int length, int bestGuessDecompressedSize)