[[data_encoding]]
= Data Encoding and MediaTypes
Encoding is the data conversion operation done by {brandname} caches before storing data, and when reading back from storage.

== Overview
Encoding allows dealing with a certain data format during API calls (map, listeners, stream, etc) while the format effectively stored
is different.

The data conversions are handled by instances of _org.infinispan.commons.dataconversion.Encoder_ :

[source,java]
----
include::code_examples/Encoder.java[]
----

== Default encoders

{brandname} automatically picks the Encoder depending on the cache configuration. The table below shows which internal Encoder is used for several configurations:

[options="header",cols="4"]
|===
| Mode | Configuration | Encoder | Description
| Embedded/Server
| Default
| IdentityEncoder
| Passthrough encoder, no conversion done

| Embedded
| StorageType.OFF_HEAP
| GlobalMarshallerEncoder
| Use the {brandname} internal marshaller to convert to byte[]. May delegate to the configured marshaller in the cache manager.

| Embedded
| StorageType.BINARY
| BinaryEncoder
| Use the {brandname} internal marshaller to convert to byte[], except for primitives and String.

| Server
| StorageType.OFF_HEAP
| IdentityEncoder
| Store byte[]s directly as received by remote clients
|===

== Overriding programmatically

It is possible to override programmatically the encoding used for both keys and values, by calling the _.withEncoding()_ method variants from _AdvancedCache_.

Example, consider the following cache configured as OFF_HEAP:

[source,java]
----
include::code_examples/EncoderOverride.java[]
----

The override can be useful if any operation in the cache does not require decoding, such as counting number of entries,
or calculating the size of byte[] of an OFF_HEAP cache.

== Defining custom Encoders

A custom encoder can be registered in the _EncoderRegistry_.

CAUTION: Ensure that the registration is done in every node of the cluster, before starting the caches.

Consider a custom encoder used to compress/decompress with gzip:

[source,java]
----
include::code_examples/EncoderCustomGzip.java[]
----

It can be registered by:

[source,java]
----
include::code_examples/EncoderCustomGzipRegister.java[]
----

And then be used to write and read data from a cache:

[source,java]
----
include::code_examples/EncoderCustomExample.java[]
----

[[encoding_media_type]]
== MediaType

A Cache can optionally be configured with a `org.infinispan.commons.dataconversion.MediaType` for keys and values. By describing the data format of the cache, {brandname} is able to convert data on the fly during cache operations.

NOTE: The MediaType configuration is more suitable when storing binary data. When using server mode, it's common to have a MediaType configured and clients such as REST or Hot Rod reading and writing in different formats.

The data conversion between MediaType formats are handled by instances of `org.infinispan.commons.dataconversion.Transcoder`

[source,java]
----
include::code_examples/Transcoder.java[]
----

=== Configuration

Declarative:

[source,xml,options="nowrap",subs=attributes+]
----
include::config_examples/encoding_media_type.xml[]
----

Programmatic:

[source,java]
----
include::code_examples/EncoderMediaType.java[]
----

[[mediatype_override]]
=== Overriding the MediaType Programmatically

It's possible to decorate the Cache with a different MediaType, allowing cache operations to be executed sending and receiving different data formats.

Example:

[source,java]
----
include::code_examples/EncodeMediaTypeOverride.java[]
----

Will return the value in JSON format:

[source,json]
----
{
   "_type":"org.infinispan.sample.Person",
   "name":"John",
   "surname":"Doe"
}
----

CAUTION: Most Transcoders are installed when server mode is used; when using library mode, an extra dependency, _org.infinispan:infinispan-server-core_ should be added to the project.

=== Transcoders and Encoders

Usually there will be none or only one data conversion involved in a cache operation:

 * No conversion by default on caches using in embedded or server mode;
 * _Encoder_ based conversion for embedded caches without MediaType configured, but using OFF_HEAP or BINARY;
 * _Transcoder_ based conversion for caches used in server mode with multiple REST and Hot Rod clients sending
and receiving data in different formats. Those caches will have MediaType configured describing the storage.

But it's possible to have both encoders and transcoders being used simultaneously for advanced use cases.

Consider an example, a cache that stores marshalled objects (with jboss marshaller) content but for security reasons a transparent encryption layer should be added in order to avoid storing "plain" data to an external store.
Clients should be able to read and write data in multiple formats.

This can be achieved by configuring the cache with the the MediaType that describes the storage regardless of the encoding layer:

[source,java]
----
include::code_examples/EncodeConfigMediaType.java[]
----

The transparent encryption can be added by decorating the cache with a special _Encoder_ that encrypts/decrypts with storing/retrieving, for example:

[source,java]
----
include::code_examples/EncoderScrambler.java[]
----

To make sure all data written to the cache will be stored encrypted, it's necessary to decorate the cache with the Encoder above and perform all cache operations in this decorated cache:

[source,java]
----
include::code_examples/EncoderScramblerDecorateCache.java[]
----

The capability of reading data in multiple formats can be added by decorating the cache with the desired MediaType:

[source,java]
----
include::code_examples/EncoderMediaTypeDecorateCache.java[]
----

Internally, {brandname} will first apply the encoder _fromStorage_ operation to obtain the entries, that will be in "application/x-jboss-marshalling" format and then apply a successive conversion to "application/xml" by using the adequate Transcoder.
