# Adapters

Use XOOM Symbio adapters to translate object state within a service or application to serialized states that are suitable for network-based messaging and long-term database storage. To explain the details within this topic we refer to the following components.

| Type                      | Description                                                                                                                                                                                                                                                                                      |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `StateAdapter<S,RS>`      | The interface defining the behaviors of an adapter for application and serialized states.                                                                                                                                                                                                        |
| `DefaultTextStateAdapter` | The default `StateAdapter` used when no type-specific adapter is registered with the `StateAdapterProvider`.                                                                                                                                                                                     |
| `StateAdapterProvider`    | The registry and provider of `StateAdapter` instances by state type, as well as adapter behaviors using type lookups.                                                                                                                                                                            |
| `State<T>`                | The abstract base type that supports binary, object, and text serialization states.                                                                                                                                                                                                              |
| `BinaryState`             | The concrete type that supports `State<byte[]>`.                                                                                                                                                                                                                                                 |
| `ObjectState`             | The concrete type that supports `State<Object>`.                                                                                                                                                                                                                                                 |
| `TextState`               | The concrete type that supports `State<String>`.                                                                                                                                                                                                                                                 |
| `EntryAdapter<S,E>`       | The interface defining the behaviors of an adapter for application sources and serialized entries.                                                                                                                                                                                               |
| `DefaultTextEntryAdapter` | The default `EntryAdapter` used when no type-specific adapter is registered with the `EntryAdapterProvider`.                                                                                                                                                                                     |
| `EntryAdapterProvider`    | The registry and provider of `EntryAdapter` instances by source type, as well as adapter behaviors using type lookups.                                                                                                                                                                           |
| `Entry<T>`                | The interface that defines a serialized state persisted to a `Journal<T>`. A journal entry may be a serialized `Source<T>` concrete implementation such as those defined in [XOOM Lattice](https://docs.vlingo.io/xoom-lattice)**:** `Command`, `DomainEvent`, and `ProcessMessage`, and others. |
| `BaseEntry<T>`            | The abstract base type that supports entry binary, object, and text serialization.                                                                                                                                                                                                               |
| `BinaryEntry`             | The concrete type that supports `Entry<byte[]>`.                                                                                                                                                                                                                                                 |
| `ObjectEntry`             | The concrete type that supports `Entry<Object>`.                                                                                                                                                                                                                                                 |
| `TextEntry`               | The concrete type that supports `Entry<String>`.                                                                                                                                                                                                                                                 |
| `NullEntry`               | The concrete type that implements the *Null Object* pattern for `Entry<byte[]>`, `Entry<Object>`, and `Entry<String>`.                                                                                                                                                                           |

## Using Adapters

There are a few ways to use adapters. You may use the default adapters or implement your own. The use of the default adapters may be good enough to get your service or application up and running quickly. As time passes and your `DomainEvent` and/or `Command` types change, you will need to replace the defaults with your own implementations.

### Default Adapters

The XOOM Symbio tooling provides default `StateAdapter` and `EntryAdapter` types for both `State` and `Entry`. These default adapters will be used automatically when the service or application has not registered a custom adapter for a given state or source type. This means that you do not need to register these default adapters with the `StateAdapterProvider` or the `EntryAdapterProvider`.

The current default adapters are the `DefaultTextStateAdapter` and the `DefaultTextEntryAdapter`. Because these are default adapters you will not need to import them into your main code, although the import statements are shown here for clarity.

```java
import io.vlingo.xoom.symbio.DefaultTextEntryAdapter;
import io.vlingo.xoom.symbio.DefaultTextStateAdapter;
```

Both of these serialize from service and application object state to JSON text where the `State` and `Entry` types are `TextState` and `TextEntry`, respectively. They also deserialize from `TextState` and `TextEntry` back to service and application object state.

If you use a different text format other than JSON, or if you use binary, you must provide your own custom adapters. We may provide other default adapter types in the future depending on demand.

### Implementing Custom Type Adapters

The following is an example of the implementation of a `StateAdapter`.

```java
import io.vlingo.xoom.common.serialization.JsonSerialization;
import io.vlingo.xoom.symbio.Metadata;
import io.vlingo.xoom.symbio.State;
import io.vlingo.xoom.symbio.State.TextState;
import io.vlingo.xoom.symbio.StateAdapter;

public class ProductStateAdapter implements StateAdapter<ProductState,State<String>> {
  @Override public int typeVersion() { return 1; }

  @Override
  public Product fromRawState(final State<String> raw) {
    return JsonSerialization.deserialized(raw.data, ProductState.class);
  }

  @Override
  public <ST> ST fromRawState(final State<String> raw, final Class<ST> stateType) {
    return JsonSerialization.deserialized(raw.data, stateType);
  }

  @Override
  public State<String> toRawState(final ProductState state, final int stateVersion) {
    return toRawState(state.id, state, stateVersion, Metadata.nullMetadata());
  }

  @Override
  public State<String> toRawState(final String id, final ProductState state, final int stateVersion, final Metadata metadata) {
    final String serialization = JsonSerialization.serialized(state);
    return new TextState(id, ProductState.class, typeVersion(), serialization, stateVersion);
  }
}
```

This `ProductStateAdapter` is responsible for adapting from the `Product` service/application object state to what is called the *raw state* and back again from raw state to the `Product` service/application state.

The raw state is suitable for traveling across a network and being persisted into database storage. This is handled by the two methods named `toRawState()`.

The service/application state is, as the name indicates, used as operational state. Adapting from raw state back to service/application state is handled by the two methods named `fromRawState()`.

There is another method, `typeVersion()`, that provides the current version of the operational state type. This specific implementation indicates version `1`.  This version may also be encoded as a [`SemanticVersion`](https://docs.vlingo.io/vlingo-common#semantic-versions), as is provided with [XOOM Common](https://docs.vlingo.io/xoom-common)*.*

The current type version is automatically encoded into the raw state. When adapting back from the raw state to the operational state, you must check the raw state's type version to determine if it must be upgraded to the current operational state type version. This is available via the variable `public final int typeVersion` in `State<T>`. (This is an immutable variable and does not require an accessor method.)

Next is an example of an `EntryAdapter` for the `CartInitialized` event.

```java
public class CartInitializedAdapter implements EntryAdapter<CartInitialized, TextEntry> {
  @Override
  public CartInitialized fromEntry(final TextEntry entry) {
    return JsonSerialization.deserialized(entry.entryData(), CartInitialized.class);
  }

  @Override
  public TextEntry toEntry(final CartInitialized source, final Metadata metadata) {
    final String serialization = JsonSerialization.serialized(source);
    return new TextEntry(CartInitialized.class, 1, serialization, metadata);
  }

  @Override
  public TextEntry toEntry(final CartInitialized source, final String id, final Metadata metadata) {
    final String serialization = JsonSerialization.serialized(source);
    return new TextEntry(id, CartInitialized.class, 1, serialization, metadata);
  }

  @Override
  public TextEntry toEntry(final CartInitialized source, final int version, final String id, final Metadata metadata) {
    final String serialization = JsonSerialization.serialized(source);
    return new TextEntry(id, CartInitialized.class, 1, serialization, version, metadata);
  }
}
```

The same design guidance applies for `EntryAdapter` implementations as for `StateAdapter`.

#### Registering Custom Type Adapters

Custom type adapters are registered with adapter providers. When the adapter provider is created it is registered with an associated unique identity in the `World`. The registration is a means to avoid the use of static variables to hold the adapter providers. It also makes it convenient for the various XOOM Symbio storage mechanisms to access the adapters when moving data into and out of the underlying databases.

To register a custom type adapter you first must allocate adapter providers, and then register each custom type adapter with a given adapter provider. The first example demonstrates registering state adapters.

```java
World world = World.startWithDefaults("my-service");

StateAdapterProvider stateAdapterProvider =
    StateAdapterProvider.instance(world);

stateAdapterProvider.registerAdapter(
    ProductState.class, new ProductStateAdapter());

stateAdapterProvider.registerAdapter(
    CartState.class, new CartStateAdapter());
```

The second example demonstrates registering entry adapters.

```java
World world = World.startWithDefaults("my-service");

EntryAdapterProvider entryAdapterProvider =
    EntryAdapterProvider.instance(world);

entryAdapterProvider.registerAdapter(
    CartInitialized.class, new CartInitializedEntryAdapter());

entryAdapterProvider.registerAdapter(
    ProductPlacedInCart.class, new ProductPlacedInCartEntryAdapter());
```

You should determine which states and sources (e.g. `DomainEvent` and `Command` types) must be exchanged **across** collaborating services and establish their schemas in the [XOOM Schemata](https://docs.vlingo.io/xoom-schemata) schema registry.
