# Object Storage

An `ObjectStore` provides the protocol for reactively persisting and reconstituting objects. Storing objects has the advantage of searching for given instances by any number of their attributes/properties, effectively as if the objects are living in memory with only the need to ask for them by means of partial state characteristics. The objects stored are typically state types of Entity/Aggregate instances, which have unique identities. These state types are extenders of the `StateObject` abstract base class.

```java
import io.vlingo.xoom.symbio.store.object.StateObject;

public final class ProductState extends StateObject {
  private String name;
  private SKU sku;
  private RFID rfid;
  private Money price;
  ...
  
  public ProductState(long id, String name, SKU sku, RFID rfid, Money price) {
    super(id);
    
    this.name = name;
    this.sku = sku;
    this.rfid = rfid;
    this.price = price;
  }
}
```

Typically this `ProductState` would be held by the Aggregate `ProductActor`, where the actor implements the `Product` protocol.

```java
public ProductActor extends Actor implements Product {
  private ProductState state;
  
  public ProductActor(long id, String name, SKU sku, RFID rfid, Money price) {
    this.state = new ProductState(id, name, sku, rfid, price);
  }
  
  ...
}
```

In recent years object storage has been managed by a technique known as object-relational mapping (ORM), where objects are disassembled to fit into the relational table, row, and column structures. In such cases SQL expressions are used to create, read, update, and delete such objects. Using Java means that the SQL operations will be managed using JDBC, but will often employ a mapping layer on top of that. Some well-known ORM tools are TopLink/EclipseLink, Hibernate, various implementations of JPA, and others, such as Cayenne. There are other abstractions, such as Jdbi, that are not classified as an ORM, but provide worthy querying and mapping techniques that are much less invasive than ORM tools. All of these are or can be supported by a XOOM Symbio `ObjectStore` implementation.

Additionally, there is a XOOM Symbio `ObjectStore` implementation for Apache Geode. Apache Geode is an in-memory data fabric, compute grid, and distributed cache, which can hold object states.

{% hint style="info" %}
An important point to consider is, if you use the XOOM Lattice entity type `ObjectEntity`, there is no need to learn the operations of the `ObjectStore`. You get all storage persistence for free when you use the `ObjectEntity` abstract base types. Yet, you must still set up your backing database mechanism, including your chosen ORM configurations. We do not cover ORM details here.
{% endhint %}

## Object Persistence Protocols

The `ObjectStore` protocol extends `ObjectStoreReader` and `ObjectStoreWriter`, defining a single message type in addition: `close()`.

```java
public interface ObjectStore extends ObjectStoreReader, ObjectStoreWriter {
  void close();
}
```

First consider the `ObjectStoreWriter`. It is composed of a number of variations of `persist()` and `persistAll()` message types, with differences being in the number of parameters supported in each. The richest form of the two message types follow.

```java
<T extends PersistentObject, E> void persist(
  final T persistentObject,
  final List<Source<E>> sources,
  final Metadata metadata,
  final long updateId,
  final PersistResultInterest interest,
  final Object object);

<T extends PersistentObject, E> void persistAll(
  final Collection<T> persistentObjects,
  final List<Source<E>> sources,
  final Metadata metadata,
  final long updateId,
  final PersistResultInterest interest,
  final Object object);
```

As noted, there are variations of these two message types that have less parameters, providing defaults to the richer message types in their implementations. The full complement of parameters and types are described next.

| Parameter                         | Description                                                                                                                                                                                                                                                                                                                                                    |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `T persistentObject`              | `T` is a subclass of `PersistentObject`, which has two attributes: `long persistenceId` and `long version`, and serves as the means to persist the corresponding object with a primary key of `persistenceId`and a `version` indicating how many times the object has be modified.                                                                             |
| `Collection<T> persistentObjects` | The same as `T persistentObject`, but as a collection of one or more.                                                                                                                                                                                                                                                                                          |
| `List<Source<E>> sources`         | The `List` of `Source` instances, which are concrete subclasses of `DomainEvent`,  `Command`, or `ProcessMessage` (see [XOOM Lattice](https://docs.vlingo.io/xoom-lattice) for details).                                                                                                                                                                       |
| `Metadata metadata`               | The metadata to associate with the stored data.                                                                                                                                                                                                                                                                                                                |
| `long updateId`                   | The identity indicating that this persistence operation is considered an update of one or more previously read objects, or `-1L` if it is a creation, not an update, operation. A non-negative `updateId` will have been provided with the result of a read query. See `QueryExpression` and its `QueryMode`, which will be either `ReadOnly` or `ReadUpdate`. |
| `PersistResultInterest interest`  | A protocol backed by an `Actor` that will receive indication of the results following the persistence operation. During tests this protocol may be mocked as a plain object, but must be designed for concurrent access (see [`AccessSafely`](https://docs.vlingo.io/xoom-actors#testing-actors)). See below for the definition of this protocol.              |
| `Object object`                   | An object that will be sent along with the `PersistResultInterest`. It may be `null`or a valid instance of any application (or service) defined type.                                                                                                                                                                                                          |

When using `ObjectStoreWriter`, the sender must provide an `Actor` or mocked test object that implements the `PersistResultInterest`protocol.

```java
public static interface PersistResultInterest {
  void persistResultedIn(final Outcome<StorageException,Result> outcome, final Object persistentObject, final int possible, final int actual, final Object object);
}
```

Next consider the `ObjectStoreReader` protocol. It provides a number of query methods, with variations on required and optional parameters.

```java
void queryAll(
  final QueryExpression expression,
  final QueryResultInterest interest,
  final Object object);
  
void queryObject(
  final QueryExpression expression,
  final QueryResultInterest interest,
  final Object object);
```

The difference between the two types of methods is the number of objects that should be included in the query results, either one or a one-or-more result.

| Parameter                      | Description                                                                                                                                                                                                                                                                                                                                 |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `QueryExpression expression`   | The expression used to resolve the query. See below for the definition of this protocol.                                                                                                                                                                                                                                                    |
| `QueryResultInterest interest` | A protocol backed by an `Actor` that will receive indication of the results following the query operation. During tests this protocol may be mocked as a plain object, but must be designed for concurrent access (see [`AccessSafely`](https://docs.vlingo.io/xoom-actors#testing-actors)). See below for the definition of this protocol. |
| `Object object`                | An object that will be sent along with the `QueryResultInterest`. It may be `null`or a valid instance of any application (or service) defined type.                                                                                                                                                                                         |

The `QueryExpression` is defined as follows. There are two extensions of the basic `QueryExpression`, which are `ListQueryExpression` and `MapQueryExpression`.

```java
public class QueryExpression {
  public final QueryMode mode;
  public final String query;
  public final Class<?> type;
  ...
}

public class ListQueryExpression extends QueryExpression {
  public final List<?> parameters;
  ...
}

public class MapQueryExpression extends QueryExpression {
  public final Map<String,?> parameters;
  ...
}
```

These class definitions include a number of factory methods for conveniently and expressively creating new instances of each.

The difference between these three query expression types is how parameters are supplied at runtime. The plain `QueryExpression` is a single parameterless expression. The parameters of a `ListQueryExpression` are ordered for setting as positional parameters 1, 2, 3, etc., or as a list of comma delimited parameters. The `MapQueryExpression` parameters are named using the `String` map keys, with the corresponding values to be set in the query expression, such as expression target `:id` matched with key `"id"` and value `"8d8acfe97a"`.

When using `ObjectStoreReader`, the sender must provide an `Actor` or mocked test object that implements the `QueryResultInterest`protocol.

```java
public static interface QueryResultInterest {
  void queryAllResultedIn(final Outcome<StorageException,Result> outcome, final QueryMultiResults results, final Object object);
  void queryObjectResultedIn(final Outcome<StorageException,Result> outcome, final QuerySingleResult result, final Object object);
}
```

When the receiver is informed of a query result, it is expressed as either a multiple *All* result or a single *Object* result. Note that the `Outcome` may be a `StorageException` or a successful `Result`. The `QueryMultiResults` holds a collection of resulting objects and `QuerySingleResult` holds a single object result.

## ObjectStore Implementations

There are a number of implementations of the `ObjectStore`.

### Component: `xoom-symbio`

You may use the in-memory implementation for testing.

```java
import io.vlingo.xoom.symbio.store.object.inmemory.InMemoryObjectStoreActor;
```

### Component: `xoom-symbio-geode`

This is the implementation of the `ObjectStore` for Apache Geode.

```java
import io.vlingo.xoom.symbio.store.object.geode.GeodeObjectStoreActor;
```

### Component: `xoom-symbio-jdbc`

These depend on specific database mechanisms, such as PostgreSQL, MySQL, MariaDB, and HSQLDB.

```java
// for Jdbi
import io.vlingo.xoom.symbio.store.object.jdbc.JDBCObjectStoreActor;
import io.vlingo.xoom.symbio.store.object.jdbc.jdbi.JdbiObjectStoreDelegate;

// for JPA
import io.vlingo.xoom.symbio.store.object.jdbc.jpa.JPAObjectStoreActor;
import io.vlingo.xoom.symbio.store.object.jdbc.jpa.JPAObjectStoreDelegate;
```
