Transaction support has been recently added to the Couchbase SDKs. Starting in Spring Data Couchbase 5.0.0-M5, support for transactions has been added to Spring Data Couchbase. In this blog, we will describe using the Spring Data @Transactional annotation to leverage Couchbase Transactions.

The spring-data-couchbase repository contains a spring-data-testapp which exercises transactions. It relies on the travel-sample bucket on a local Couchbase server. (any bucket with a primary index will suffice).

Beans supporting transaction management have been added to AbstractCouchbaseConfiguration. To allow the built-in transaction interceptor class to be overridden with the CouchbaseTransactionInterceptor, ensure the following line is in the application.properties file:

application.properties

The transaction configuration can be modified by overriding the configureEnvironment() method in your class which extends AbstractCouchbaseConfiguration.  Here we set the durabilityLevel to NONE so we can work in our single-node cluster.

Config.java

In the class which will use them, we need to define the template as usual and a reference to the service object. It’s important to note that the @Autowired annotation  populates a variable with a proxy object. This is an important detail as the proxy objects perform processing before and after calling the actual method. Directly creating the service object from its constructor will result in the @Transactional annotation having no effect.

CmdRunner.java

The service is defined with an @Service annotation. The constructor takes arguments which are @Bean objects, such that the infrastructure can create a proxy object for @Autowired.

AirlineGateService.java

AirlineGateService.java (cont’d)

Now use everything we have constructed:

  1. save two AirlineGates documents, each of which indicates 200 gates
  2. verify they have been saved.
  3. execute the transferGates() method of the service to transfer 50 gates from one airline to the other in a transaction.
  4. verify that the transfer has taken place.
  5. attempt to execute transferGates() again, this time with an exception occurring after the first document has been saved.

    CmdRunner.java

How it works:

  • The TransactionInterceptor @Bean in AbstractCouchbaseConfiguration overrides the built-in TransactionInterceptor for @Transactional annotated methods.  
  • The @Transactional annotation causes the proxy for AirportGatesService to use the TransactionInterceptor to call the annotated method using the CouchbaseCallbackTransactionManager.  
  • The CouchbaseCallbackTransactionManager initializes a transaction and then calls the actual service method in the context of the transaction. 
  • If the method call is successful, the CouchbaseCallbackTransactionManager commits the transaction. 
  • If the commit is successful, the call returns. 
  • If the commit fails with a retryable exception, the CouchbaseCallbackTransactionManger will retry the complete process of initializing a new transaction, executing the actual service method and then committing the transaction. 

The CouchbaseCallbackTransactionManager will repeat this until either the commit succeeds, or the maximum number of retries has been reached.

Options for next steps

Author

Posted by Michael Reiche, Sr. Software Engineer

5 Comments

  1. Hi Folks – the couchbase/transactions project has not yet been merged into spring-data-examples. It will be available shortly.
    – Mike

  2. The couchbase/transactions project is now available in the boot-3 branch

    https://github.com/spring-projects/spring-data-examples/tree/boot-3/couchbase/transactions

  3. The transaction sample needs spring-boot-starter-data-couchbase 3.0.0-RC2 to run due to an incompatibility with reactor in other 3.0.0* versions.

  4. Hi Michael, Thanks for implementing built-in couchbase transaction support. It works very well when I use “couchbase transaction” using the single bucket, but I have an error in transactions using with multiple buckets.

    I implemented this link https://github.com/spring-projects/spring-data-couchbase/issues/878. This implementation is not working with transactions. Do you have any idea?

  5. Michael Reiche April 3, 2023 at 12:45 pm

    Spring Data Couchbase Transactions will not work with multi-buckets as multi-buckets in Spring Data Couchbase requires multiple connections to Couchbase and the transaction must be on a single connection.
    – Mike

Leave a reply