cassandracassandra-3.0gemfilespring-data-cassandraspring-data-gemfire

Global Transaction in GemFire


I am using GemFire for in-memory and Cassandra to act as the source of truth and finding it difficult to implement the global transaction manager for below scenario.

Using CacheWriter to insert/update the data in Cassandra and GemFire Repository for inserting/updating records in GemFire. In case of any failure in either GemFire or Cassandra, I need to rollback the data.


Solution

  • This seems like a question I have answered before (recently too). Anyway, I could not find it.

    I have built a Global Transaction example using Pivotal GemFire combined with an HSQLDB DataSource using SD JPA.

    NOTE: This example is part of my Contacts Application Reference implementation (RI) for both Spring Data Geode (for Apache Geode) and Spring Data GemFire (for Pivotal GemFire) showcasing the many capabilities features of Pivotal GemFire/Apache Geode, Spring Data GemFire/Geode and Spring in general. This repository-example focuses on using Spring Data Commons's Repository Infrastructure and extensions to apply the Repository Data Access patterns from SD Commons to Pivotal GemFire/Apache Geode in a Spring context. Of the many things this example shows (e.g. CRUD, Querying, custom Repository methods, etc) both Local (Cache) and Global (JTA) based transaction are part of the repository-example. Unfortunately, the documentation is still largely a WIP. But I do plan to keep this RI and examples up-to-date as I also use the code as a basis for my conference talks. Anyway...

    While this example combines Pivotal GemFire with a RDBMS (i.e. HSQLDB), it would be possible to swap out HSQLDB for say, Apache Cassandra. All that is required is that the data source/store be JTA compliant.

    The configuration of this example/test is here, and relies rather extensively on Spring Boot "auto-configuration" support. That is, when Atomikos (open source JTA Transaction Manager) is on the CLASSPATH (or any JTA Transaction Manager supported by Spring Boot), Spring Boot will auto-configure JTA-based transactions. You can, of course, use other JTA Transaction Manager providers not supported, but then you are left to configure them manually, yourself. You can even manually configure Atomikos if you like, but Spring Boot's auto-configuration support is highly convenient and recommended.

    The only other thing required is to make each data source aware of the JTA Transaction.

    For Pivotal GemFire, this entailed setting up a Naming context (i.e javax.naming.InitialContext) that GemFire itself uses in order to "lookup" (by name) and find the existing JTA Transaction. Essentially, this bean definition associates the JTA "TransactionManager" used with the proper "name" as expected by GemFire in its lookup process.

    NOTE: the artificial Naming context would not be required if you were in a managed environment, such as an application server, or even Tomcat, since it provides a Naming context service for your applications. Of course, then you would need to register the JTA Transaction with that environment instead. However, since this is a standalone (Spring Boot) app not in a app container, I used Spring's mock/test Naming context support in my NamingContextBuilderFactoryBean class.

    All that is left is for you to review Apache Cassandra/DataStax's Documentation on getting Apache Cassandra to participate in the JTA Transaction. Then you do not need any Pivotal GemFire specific classes (e.g. CacheWriter) to update Cassandra from GemFire. With JTA, either all JTA-compliant data store persist correctly, or don't.

    More information on Pivotal GemFire's Global JTA Transaction support can be found here, and specifically, related material here.

    More on Cassandra Transactions can be found starting here. Hope this helps.

    Cheers, John