JaVers Repository Configuration

If you’re going to use JaVers as a data audit framework you should configure JaversRepository.

The purpose of JaversRepository is to store JaVers commits in your database,
alongside your domain data. JSON format is used for serializing your data.
This approach significantly simplifies the construction of JaversRepository.
The hardest work — mapping domain objects to persistent format (JSON) —
is done by javers-core.
This common JSON format is used by many JaversRepository implementations.

In runtime, JaVers commit holds a list of domain object snapshots and a list of changes (a diff).
Only snapshots are persisted in a database.
When JaVers commit is being read from a database, snapshots are deserialized from JSON
and the diff is re-calculated by comparing snapshot pairs.

By default, JaVers comes with in-memory repository implementation. It’s perfect for testing,
but for production environment you need something real.

Choose JaversRepository

In JaVers 5.2.4, we have added experimental support for Amazon DocumentDB which claims to be
almost fully compatible with MongoDB.

Hint. If you are using Spring Boot, just add one of our
Spring Boot starters for Spring Data
and let them automatically configure and boot a JaVers instance with proper JaversRepository implementation.

Usage
The idea of configuring MongoRepository is simple,
just provide a working Mongo client.

importorg.javers.repository.mongo.MongoRepository;importcom.mongodb.MongoClient;importcom.mongodb.client.MongoDatabase;...//by default, use the same database connection//which you are using for your primary databaseMongoDatabasemongoDb=newMongoClient("localhost").getDatabase("test");MongoRepositorymongoRepository=newMongoRepository(mongoDb);Javersjavers=JaversBuilder.javers().registerJaversRepository(mongoRepository).build();

importorg.javers.repository.sql.JaversSqlRepository;importjava.sql.Connection;importjava.sql.DriverManager;...//finalConnectiondbConnection=DriverManager.getConnection("jdbc:h2:mem:test");ConnectionProviderconnectionProvider=newConnectionProvider(){@OverridepublicConnectiongetConnection(){//suitable only for testing!returndbConnection;}};JaversSqlRepositorysqlRepository=SqlRepositoryBuilder.sqlRepository().withSchema("my_schema")//optionally, provide the schame name.withConnectionProvider(connectionProvider).withDialect(DialectName.H2).build();Javersjavers=JaversBuilder.javers().registerJaversRepository(sqlRepository).build();

To setup JaversSqlRepository you need to provide three things: an SQL dialect name,
a ConnectionProvider implementation and a JDBC driver on your classpath.

In the following table, there is a summary of all supported SQL databases with corresponding
dialect names.

You should provide a proper JDBC driver version on your classpath, which works bests for you
(these versions are only a suggestion, we use them in JaVers integration tests)
.
Probably it would be the same version which you already use for your application’s database.

ConnectionProvider

ConnectionProvider serves as the source of live JDBC connections for your JaversSQLRepository.
JaversSqlRepository works in passive mode, which means:

JaVers doesn’t create JDBC connections on its own and uses connections provided by an application
(via ConnectionProvider.getConnection()).

JaVers philosophy is to use application’s transactions
and never to call SQL commit or rollback commands on its own.

Thanks to this approach, data managed by an application (domain objects) and data managed by JaVers (object snapshots)
can be saved to SQL database in one transaction.

If you’re using a transaction manager, implement a ConnectionProvider to integrate with it.
For Spring users, we have out-of-the-box implementation: JpaHibernateConnectionProvider from javers-spring module.
Choose this, if you’re using Spring/JPA/Hibernate stack (see JPA EntityManager integration).

If you’re not using any kind of transaction manager, implement a ConnectionProvider to return
the current connection (thread-safely).

Schema

JaVers creates four tables in SQL database:

jv_global_id — domain object identifiers,

jv_commit — JaVers commits metadata,

jv_commit_property — commit properties,

jv_snapshot — domain object snapshots.

JaVers has a basic schema-create implementation.
If a table is missing, JaVers simply creates it, together with a sequence and indexes.
There’s no schema-update, so if you drop a column, index or sequence, it wouldn’t be recreated automatically.

Custom JSON serialization

JaVers is meant to support various persistence stores for
any kind of client’s data. Hence we use JSON format to serialize client’s domain objects.

JaVers uses the Gson library which provides neat
and pretty JSON representation for well known Java types.

But sometimes Gson’s default JSON representation isn’t what you like.
This happens when dealing with Values like Date, Money or ObjectId.

JSON TypeAdapters

You can easily customize JaVers serialization/deserialization behavior
by providing TypeAdapters for your Value types.
See TypeAdapter example for ObjectId.

JaVers supports two families of TypeAdapters.

JaVers family, specified by the
JsonTypeAdapter interface.
It’s a thin abstraction over Gson native type adapters.
We recommend using this family in most cases
as it has a nice API and isolates you (to some extent) from low level Gson API.

BasicStringTypeAdapter
is a convenient scaffolding implementation of the JsonTypeAdapter interface.
Extend it if you want to represent your Value type as atomic String
(and when you don’t want to deal with JSON API).