Wait, didn’t we already do another Hibernate Validator release earlier this month?
That’s right, indeed we pushed out the first Alpha of the 5.3 family a couple of days ago.
And normally, that’d mean that there would be no further releases of earlier version families.

But in this case we decided to do an exception from the rule as we noticed that Hibernate Validator couldn’t be used with Java 9
(check out issue HV-1048 if you are interested in the details).
As we don’t want to keep integrators and users of Hibernate Validator from testing their own software on Java 9, we decided to fix that issue on the current stable release line
(in fact we strongly encourage you to test your applications on Java 9 to learn as early as possible about any potential changes you might need to make).

Where do I get it?

Use the GAV coordinates org.hibernate:{hibernate-validator|hibernate-validator-cdi|hibernate-validator-annotation-processor}:5.2.3.Final to fetch the release with Maven, Gradle etc.
Alternatively, you can find distribution bundles containing all the bits on SourceForge (TAR.GZ, ZIP).

Found a bug? Have a feature request? Then let us know through the following channels:

It’s my pleasure to announce the first release of Hibernate Validator 5.3!

The overarching idea for the 5.3 timeline is to prototype several features which may potentially be standardized in the Bean Validation 2.0 specification.
For instance we’ll work on a solution for the long-standing request for sorting the constraints on single properties.

If you’d like to see any specific features addressed in that prototyping work (and eventually included in BV 2.0),
then please get in touch and let us know which are the most important things you are missing from the spec.
We’ve compiled a first list of issues we are considering for inclusion in BV 2.0.
For sure we cannot address all of them, so it’ll greatly help if you tell us what would be most helpful to you.

Dynamic payloads for constraints

To get things rolling, the Alpha 1 allows to you to enrich custom constraint violations with additional context data.
Code examining constraint violations can access and interpret this data in a safer way than by parsing string-based constraint violation messages.
Think of it as a dynamic variant of the existing Bean Validation payload feature.

As an example, let’s assume we have a constraint @Matches for making sure a long property matches a given value with some tolerance:

If the annotated value is invalid, the resulting constraint violation should have a specific severity, depending on whether the value lies within the given tolerance or not.
That severity value could then for instance be used for formatting the error specifically in a UI.

The definition of the @Matches constraint is nothing new, it’s just a regular custom constraint annotation:

In isValid() the severity object is set via HibernateConstraintValidatorContext#withDynamicPayload().
Note that the payload object must be serializable in case constraint violations are sent to remote clients, e.g. via RMI.

You can find the complete list of all addressed issues in the change log.
To get the release with Maven, Gradle etc. use the GAV coordinates org.hibernate:{hibernate-validator|hibernate-validator-cdi|hibernate-validator-annotation-processor}:5.3.0.Alpha1.
Alternatively, a distribution bundle containing all the bits is provided on on SourceForge (TAR.GZ, ZIP).

Please refer to the change log for the complete list of all issues.
You can get the release with Maven, Gradle etc. using the GAV coordinates org.hibernate:hibernate-validator::5.2.2.Final.
Alternatively, a distribution bundle is provided on on SourceForge (TAR.GZ, ZIP).

As of Lucene 5 (which is what Hibernate Search 5.5 is based on), there is a big performance gain if the fields to sort on are known up front.
In this case these fields can be stored as so-called "doc value fields", which is much faster and less memory-consuming than the traditional approach of index un-inverting.

For that purpose, Hibernate Search provides the new annotation@SortableField (and it’s multi-valued companion, @SortableFields)
for tagging those fields that should be available for sorting. The following example shows how do it:

@SortableField is used next to the known @Field annotation. In case a single field exists for a given property (e.g. publicationDate) just specifying the @SortableField annotation
is enough to make that field sortable. If several fields exist (see the title property), specify the field name via @SortableField#forField().

Note that sort fields must not be analyzed. In case you want to index a given property analyzed for searching purposes,
just add another, un-analyzed field for sorting as it is shown for the title property.
If the field is only needed for sorting and nothing else, you may configure it as un-indexed and un-stored, thus avoid unnecessary index growth.

For using the configured sort fields when querying nothing has changed. Just specify a Sort with the required field(s):

Now what happens if you sort on fields which you have not explicitly declared as sortable, e.g. when migrating an existing application over to Hibernate Search 5.5?
The good news is that the sort will be applied as expected from a functional perspective. Hibernate Search detects the missing sort fields and transparently falls back to
index-univerting.

But be aware that this comes with a performance penalty (also it is quite memory-intensive as uninverting is RAM-only operation) and it even might happen that this
functionality will be removed from Lucene in a future version altogether. Thus watch out for messages like the following in your log files and follow the advice to declare the missing sort fields:

It’s my pleasure to announce the first Alpha release of Hibernate OGM 5!

This release is based on Hibernate ORM 5.0 Final which we released just last week.
The update should be smooth in general, but you should be prepared for some changes if you are bootstrapping Hibernate OGM manually through the Hibernate API and not via JPA.
If you are using Hibernate OGM on WildFly, you need to adapt your application to the changed module/slot name of the Hibernate OGM core module which has changed from org.hibernate:ogm to org.hibernate.ogm:main.

Check out the Hibernate OGM migration notes to learn more about migrating from earlier versions of Hibernate OGM to 5.x.
Also the Hibernate ORM migration guide is a recommended read.

Experimental support for Redis

Hibernate OGM 5 brings tech preview support for Redis which is a high-performance key/value store with many interesting features.

A huge thank you goes out to community member Mark Paluch for this fantastic contribution!
Originally started by Seiya Kawashima, Mark took up the work on this backend and delivered a great piece of work in no time.
Looking forward to many more of his contributions to come!

The general mapping approach is to store JSON documents as values in Redis. For instance consider the following entity and embeddables:

Refer to the Redis chapter of the reference guide to learn more about this new dialect and its capabilities.
It is quite powerful already (almost all tests of the Hibernate OGM backend TCK pass) and there is support for using it in WildFly, too.

While JSON is a popular choice for storing structured data amongst Redis users, we will investigate alternative mapping approaches, too.
Specifically, one interesting approach would be to store entity properties using Redis hashes.
This poses some interesting challenges, though, e.g. regarding type conversion (only String values are supported in hashes) as well as handling of embedded objects and associations.

So if you are faced with the challenge of persisting object models into Redis, give this new backend a try and let us know what you think, open feature requests etc.

Improved mapping of Map properties

Map-typed entity properties are persisted in a more natural format now in MongoDB (and also with the new Redis backend). The following shows an example:

This is not what one would expect from a document store mapping, though. Therefore Hibernate OGM 5 will create the following, more natural representation instead:

{
"id" : 123,
"addresses" : {
"home" : 456,
"work" : 789
}
}

This representation is more concise and should improve interoperability with other clients working on the same database.
If needed - e.g. for migration purposes - you can enforce the previous mapping through the hibernate.ogm.datastore.document.map_storage property.
Check out the reference guide for the details.

The optimized mapping is currently only applied if the map key comprises a single column which is of type String.
For other types, e.g. Long or composite map keys the previous mapping is used since JSON/BSON only supports field names which are strings.

An open question for us is whether other key column types should be converted into a string or not.
If for instance the addresses map was of type Map<Long, Address> one could think of storing the map keys using field names such as "1", "2" etc.
Let us know whether that’s something you’d find helpful or not.

Support for multi-get operations

One of the many optimizations in Hibernate ORM is batch fetching of lazily loaded entities.
This is controlled using the @BatchSize annotation.
So far, Hibernate OGM did not support batch fetching, resulting in more round trips to the datastore than actually needed.

This situation has been improved by introducing MultigetGridDialect
which is an optional "capability interface" that Hibernate OGM backends can implement. If a backend happens to support this contract, the Hibernate OGM engine will take advantage of it
and fetch entities configured for lazy loading in batches, resulting in a better performance.

At the moment the new Redis backend makes use of this, with the MongoDB and Neo4j backends following soon.

Upgrade to MongoDB driver 3.0

We have upgraded to version 3.0 of the MongoDB driver.
Most users of Hibernate OGM should not be affected by this but down the road this will allow us for some nice performance optimizations and support of some new functionality.

Together with the driver update we have reorganized the connection-level options of the MongoDB backend.
All String, int and boolean MongoDB client options can be configured now through the hibernate.ogm.mongodb.driver.* namespace:

The other day I came across an interesting mapping challenge which I thought may be worth sharing. If you are a seasoned JPA user, it will probably be nothing new to you, but those not as experienced may find it helpful :)

TL;DR - JPA let’s you override database columns for embedded objects but also for collections of embedded objects; @AttributeOverride and @AssocationOverride can be used for that.

Let’s assume the following entity model representing a person and their home and business address:

The interesting part is that Person has two associations with Address, one with the "homeAddress" role and another one with the "businessAddress" role. Address in turn has one ore more address lines.

When mapping these types with JPA, Person naturally becomes an entity. As there is a composition relationship between Person and Address, the latter is mapped with @Embeddable. The same goes for AddressLine, which also is an @Embeddable, contained within an element collection owned by Address.

Of course this makes sense; As Address is embedded twice within Person, its properties must be mapped to unique column names within the Person table. The @AttributeOverride annotation can be used for that:

@AssociationOverride

The Person table looks alright, but there is only a single table for the address lines. That’s a problem as it means there is no way to tell apart the lines of the business address from the lines of the home address when reading back a person from the database.

So what to do? @AttributeOverride is of no help this time, as it’s not a single column which needs to be re-defined but an entire table. But luckily, @AttributeOverride has a companion, @AssociationOverride. This annotation can be used to configure the required tables in this case:

In this part you will learn how to use Hibernate OGM from within a Java EE application running on the WildFly server. Using the entity model you already know from the previous parts of this tutorial, we will build a small REST-based application for managing hikes. In case you haven’t read the first two installments of this series, you can find them here:

In the following you will learn how to prepare WildFly for using it with Hibernate OGM, configure a JPA persistence unit, create repository classes for accessing your data and providing REST resources on top of these. In this post we will primarily focus on the aspects related to persistence, so some basic experience with REST/JAX-RS may help. The complete source code of this tutorial is hosted on GitHub.

The WildFly server runtime is based on the JBoss Modules system. This provides a modular class-loading environment where each library (such as Hibernate OGM) is its own module, declaring the list of other modules it depends on and only “seeing” classes from those other dependencies. This isolation provides an escape from the dreaded “classpath hell”.

Unzip the archive corresponding to your WildFly version into the modules directory of the application server. If you prefer that the original WildFly directories remain unchanged, you also can unzip the Hibernate OGM modules archive to any other folder and configure this as the “module path” to be used by the server. To do so, export the following two environment variables, matching your specific environment:

This makes sure you get matching versions of Hibernate OGM’s modules and any (optional) dependencies. Then add the dependency to the Java EE 7 API and one of the Hibernate OGM backend modules, e.g. Infinispan, JBoss’ high-performance, distributed key/value data grid (any other such as hibernate-ogm-mongodb or the brand-new hibernate-ogm-cassandra module would work as well):

The provided scope makes these dependencies available for compilation but prevents them from being added to the resulting WAR file. That it because the Java EE API is part of WildFly already, and Hibernate OGM will be contributed through the modules you unzipped before.

Just adding these modules to the server doesn’t cut it, though. They also need to be registered as a module dependency with the application. To do so, add the file src/main/webapp/WEB-INF/jboss-web.xml with the following contents:

With the basic project infrastructure in place, it’s time to add the entity classes and repository classes for accessing them. The entity types are basically the same as seen in part 1, only now they are annotated with @Indexed in order to allow them to be queried via Hibernate Search and Lucene:

Here we define a persistence unit named “hike-PU”. Infinispan is a fully transactional datastore, and using JTA as transaction type allows the persistence unit to participate in container-managed transactions. Specifying HibernateOgmPersistence as the provider class enables Hibernate OGM (instead of Hibernate ORM), which is configured with some properties for the setting backend (INFINISPAN in this case), database name etc.

Note that it actually should not be required to specify the entity types in persistence.xml when running in a Java EE container such as WildFly. Instead they should be picked up automatically. When using Hibernate OGM this unfortunately is needed at the moment. This a known limitation (see OGM-828) which we hope to fix soon.

The next step is to implement repository classes for accessing hike and organizer data. As an example, the following shows the PersonRepository class:

The implementation is straight-forward; by means of the @ApplicationScoped annotation, the class is marked as application-scoped CDI bean (i.e. one single instance of this bean exists throughout the lifecycle of the application). It obtains a JPA entity manager through dependency injection and uses the same to implement some simple CRUD methods (Create, Read, Update, Delete).

Note how the getAll() method uses a JP-QL query to return all person objects. Upon execution this query will be transformed into an equivalent Lucene index query which will be run through Hibernate Search.

The hike repository looks very similar, so it’s omitted here for the sake of brevity. You can find its source code on GitHub.

JAX-RS makes building REST-ful web services a breeze. It defines a declarative programming model where you annotate plain old Java classes to provide implementations for the GET, POST, PUT etc. operations of an HTTP endpoint.

Describing JAX-RS in depth is beyond the scope of this tutorial, e.g. refer to the Java EE 7 tutorial if you would like to learn more. Let’s just have a look at the some methods of a resource class for managing persons as an example:

The @Path, @Produces and @Consumes annotations are defined by JAX-RS. They bind the resource methods to specific URLs, expecting and creating JSON based messages. @GET, @POST, @PUT and @DELETE configure for which HTTP verb each method is responsible.

The @Stateless annotation defines this POJO as a stateless session bean. Dependencies such as the PersonRepository can be obtained via @Inject-based dependency injection. Implementing a session bean gives you the comfort of transparent transaction management by the container. Invocations of the methods of Persons will automatically be wrapped in a transaction, and all the interactions of Hibernate OGM with the datastore will participate in the same. This means that any changes you do to managed entities - e.g. by persisting a new person via PersonRepository#create() or by modifying a Person object retrieved from the entity manager - will be committed to the datastore after the method call returns.

The reasoning for that is to represent the elements of associations (Person#organizedHikes, Hike#organizer) in form of URIs, which enables a client to fetch these linked resources as required. E.g. a GET call to http://myserver/ogm-demo-part3/hike-manager/persons/123 may return a JSON structure like the following:

The mapping between the internal model (e.g. entity Person) and the external one (e.g. PersonDocument) can quickly become a tedious and boring task, so some tool-based support for this is desirable. Several tools exist for this job, most of which use reflection or runtime byte code generation for propagating state between different models.

Another approach for this is pursued by MapStruct, which is a spare time project of mine and generates bean mapper implementations at compile time (e.g. with Maven or in your IDE) via a Java annotation processor. The code it generates is type-safe, fast (it's using plain method calls, no reflection) and dependency-free. You just need to declare Java interfaces with mapping methods for the source and target types you need and MapStruct will generate an implementation as part of the compilation process:

The generated implementation can then be used in the Persons REST resource to map from the internal to the external model and vice versa. If you would like to learn more about this approach for model mappings, check out the complete mapper interface on GitHub or the MapStruct reference documentation.

In this part of our tutorial series you learned how to add Hibernate OGM to the WildFly application server and use it to access Infinispan as the data storage for a small REST application.

WildFly is a great runtime environment for applications using Hibernate OGM, as it provides most of the required building blocks out of the box (e.g. JPA/Hibernate ORM, JTA, transaction management etc.), tightly integrated and ready to use. Our module ZIP allows to put the Hibernate OGM modules into the mix very easily, without the need for re-deploying them each time with your application. With WildFly Swarm there is also support for the micro-services architectural style, but we’ll leave it for another time to show how to use Hibernate OGM with Wildfly Swarm (currently JPA support is still lacking from WildFly Swarm).

You can find the sources of the project on GitHub. To build the project run mvn clean install (which executes an integration test for the REST services using Arquillian, an exciting topic on its own). Alternatively, the Maven WildFly plug-in can be used to fire up a WildFly instance and deploy the application via mvn wildfly:run, which is great for manual testing e.g. by sending HTTP requests through curl or wget.

If you have any questions, let us know in the comments below or send us a Tweet to @Hibernate. Also your wishes for future parts of this tutorial are welcome. Stay tuned!

Cassandra is a highly performant and scalable datastore of the BigTable family. The request for supporting it dates back to the early days of Hibernate OGM. So it’s a great pleasure to finally have this puppy out. Many thanks to all that worked on this journey: Michaël Figuière, Khanh Maudoux, John Worrell and Jonathan Halliday!

To use the Cassandra backend, add the hibernate-ogm-cassandra module to your classpath and specify the following properties for your persistence unit:

The Cassandra backend is in “tech preview” state at this moment. We still have lots of work left on our plates (e.g. clustering support, alternative association persistence options, queries, documentation), but we think we have the right foundation now. Be warned that mapping details still may change. Still this is the right time for you to give this new backend a first try and let us know about your experiences with it.

Any feature requests, error reports and other feedback are very welcome. Especially any thoughts on the proposed mapping of domain model elements to Cassandra structures are of great interest for us.

This release fixes a bug related to the mapping of nested embeddables stored within element collections. This affects the supported document stores as well as Neo4j. E.g. consider the following entity model:

This is the mapping applied as of this new release. Note that you need to take care of existing records should have been working with such a model. Also please check out the migration notes for the details.

We don’t take such mapping changes lightly and try to avoid them as much as we can. As this really was a mapping error, we decided to fix it as soon as possible; in the future we also may provide compatibility options or some sort of migration tooling in similar situations.

We now also support MongoDB 3. In particular the new SCRAM-SHA-1 authentication strategy is working now. Migration should be smooth.

But the biggest improvement is support for replica sets. To quote MongoDB’s documentation, a replica set “is a group of mongod processes that maintain the same data set”. By using replica sets, your data is stored redundantly and protected against node failures through automatic fail-over between replica set members.

To support the notion of replica sets, Hibernate OGM’s “host” configuration option has been enhanced and now allows to specify a comma-separated list of hosts and host:port tuples:

Requested by a user in our forum, we now support all the boolean mapping types known from Hibernate ORM: YesNoType (maps to character/String “Y” or “N”), TrueFalseType (maps to “T” or “F”) and NumericBooleanType (maps to 1 or 0).

I am happy to announce the release of Hibernate OGM 4.1.3 Final and 4.2.0.Beta1!

The former brings several usability improvements, bug fixes and component upgrades, whereas the latter comes with new query features, an error handling API for non-transactional datastores and more.

The releases can be obtained as ZIP or TAR.GZ from SourceForge (4.1.3.Final, 4.2.0.Beta1) or via Maven, Gradle etc., using the following GAV coordinates:

org.hibernate.ogm:hibernate-ogm-core:4.1.3.Final or org.hibernate.ogm:hibernate-ogm-core:4.2.0.Beta1 for the Hibernate OGM engine and

org.hibernate.ogm:hibernate-ogm-<%DATASTORE%>:4.1.3.Final or org.hibernate.ogm:hibernate-ogm-<%DATASTORE%>:4.2.0.Beta1, depending on the backend you want to use.

Note that from 4.2 onwards, Hibernate OGM requires Java 7. We aimed at Java 6 compatibility for as long as possible, but with more and more of our backends and components requiring Java 7 (e.g. Neo4j and Lucene), we felt that it was time to move on and take advantage of the Java 7 goodies for the Hibernate OGM code base as well.

Let's dive into some of the new functionality of the 4.2 Beta1 release.

We continued our quest for extensive query capabilities and enabled more JP-QL constructs, namely queries on element collections. For example consider the following entity Order which contains an element collection of its order lines:

As with other JP-QL queries, Hibernate OGM will convert the query string into a native query for MongoDB and Neo4j. For the other backends a Lucene-based full-text query will be created.

Note that the JOIN syntax at this point is only supported for element collections, i.e. you cannot create join queries for arbitrary associations to other entities. The reason is that most NoSQL stores don't support joins between different tables/collections, therefore such query can't be translated in a sensible way. An exception are graph databases such as Neo4j where joins can be converted into queries based on relationships (which is what actually happens for the element collection case), but we are not quite there yet :)

Hibernate ORM collects all write operations internally and propagates them to the database in most cases only upon transaction commit (in addition, changes will also be flushed prior to query execution or upon explicite flush() calls). This enables many optimizations such as batched inserts. Hibernate OGM follows this approach and also uses transaction boundaries for demarcating units of work and triggering writes to the datastore.

While this naturally works great with transactional NoSQL stores such as Infinispan or Neo4j, it poses some challenges on non-transactional datastores. The 4.2 release therefore provides the initial draft of an API which notifies you upon failed datastore operations, letting you take appropriate action such as e.g. logging all previously applied operations or retrying a failed operation.

In order to not let this release announcement grow too big, there is a separate post just dedicated to this new API.

Fongo ("Fake Mongo") is a very nice tool when it comes to testing MongoDB applications. It provides a pure in-memory implementation of the MongoDB Java API which allows to test MongoDB-based applications without starting up an actual MongoDB instance.

Thanks to community member Alex Soto, you can use Fongo now also for testing your Hibernate OGM based application. To do so, simply add the following dependencies to your project (assuming you work with Maven and have added the Hibernate OGM BOM to the dependencyManagement block of your POM file):

Hibernate OGM will now use Fongo rather than a real MongoDB server as the backend. As said, this can be quite handy when testing your application, just do not forget to switch to a real datastore when deploying to production ;-)

Finally, let's take a quick look at two nice usability improvements which you already get with the update to 4.1.3.

The first is a better support for the RESOURCE_LOCAL transaction type when working with stores such as MongoDB under Java SE. As described above, Hibernate OGM relies on transaction demarcation to gather data changes and write them to the datastore in an optimized way. This used to require a JTA implementation on the classpath, also if the underlying datastore actually is not transactional. This is obsolete now, i.e. you can work with RESOURCE_LOCAL and MongoDB, CouchDB etc. without any further dependencies.

If you work with Hibernate OGM and Hibernate Search, you will be happy to learn that the creation of full-text queries became easier. It is not necessary any longer to configure the database retrieval method for each and every FullTextQuery, instead this happens automatically on a global level now when bootstrapping the Hibernate OGM engine.

One of the fundamental principles of Hibernate/JPA is that any writes done through the Session/EntityManager APIs are collected in the persistence context and are only written to the database upon transaction commit. If needed, you can enforce the flushing of changes by explicitly invoking the flush() method. Also Hibernate may trigger a flush automatically, e.g. prior to executing a query. This strategy allows to perform many optimizations, e.g. only persisting the final state of an entity changed several times, make use of batched inserts and others.

Hibernate OGM follows this approach and uses transaction boundaries for demarcating units of work and triggering writes to the datastore. Naturally, this works just fine on transactional NoSQL stores such as Infinispan or Neo4j, but it poses some challenges on stores without full transactional semantics.

For instance consider a method of a stateless EJB (which automatically runs within a container-managed transaction) which inserts three entities. If an error occurs when inserting the last entity, the other two will already have been written. When using a non-transactional datastore, there is no way to rollback these already applied changes. Depending on the specific use case, this may be acceptable; But in other cases it is desirable to take some action, for example retrying the failed insertion or performing compensating writes for the succeeded insertions, effectively undoing them.

This is where our new error handling API comes in. It allows you to get notified upon failed datastore operations or transaction rollback attempts, providing you with the executed and failed operation(s). This e.g. enables you to:

log all applied operations

retry a failed operation (e.g. after timeouts)

make an attempt to compensate applied changes (by executing an inverse operation)

The onRollback() method - which is called when the transaction (or unit of work) is rolled back (either by the user or by the container) - shows how to iterate over all datastore operations applied prior to the rollback attempt, examine their specific type and e.g. write them to a log file.

The onFailedGridDialectOperation() method is called for each specific datastore operation failing. It lets you decide whether to continue - ignoring the failure - or abort the operation. If ABORT is returned, the causing exception will be re-thrown, eventually causing the current transaction to be rolled back. If CONTINUE is returned, that exception will be ignored, causing the current transaction to continue.

The decision whether to abort or continue can be based on the specific exception type or on the grid dialect operation which caused the failure. In the example all exceptions of type TupleAlreadyExistsException are ignored (meaning we don't care about duplicate records being inserted into the datastore), whereas all other exceptions cause the current unit of work to be aborted. You also could react to datastore-specific exceptions such as MongoDB’s MongoTimeoutException, if needed.

Having created the ErrorHandler implementation, it needs to be registered with Hibernate OGM. You can do so for instance using a persistence unit property in META-INF/persistence.xml:

In its current form the API lays the ground for manually performing tasks such as retrying, logging and similar. But we envision a more automated approach in future versions, e.g. for automatic retries of failed operations.

Of course this API can and will not bring transactional guarantees to datastores which don't support them natively. If you find yourself frequently in a situation where you wish for transactional "all or nothing" semantics, you might consider to move to a datastore which actually provides this functionality. But you also may look into more suitable mapping approaches. For instance embeddables and element collections are a great way for ensuring atomicity of an entity and dependent structures on document stores such as MongoDB or CouchDB, as they will be mapped to a single, hierarchically structured document which can updated with a single datastore call.

At this point, the API is considered experimental and will evolve in future releases. For this, your input is very important to us! Let us know what you would like to do with such an API and what functionality should be added. Just tweet to @Hibernate or send a mail to our development list. If you like, you also may add comments to the JIRA issues addressing further development of the API: OGM-775 ("Introduce RETRY error handling strategy"), OGM-776 ("Provide means for executing compensating actions") and OGM-777 ("Expose more context information via error handler contexts").