Distributed Transactions Migration Guide
For those transitioning from using the Couchbase Transactions library for Java.
Couchbase transactions for Java were originally introduced as a library separate from the Couchbase Java SDK.
We subsequently chose to integrate transactions directly into the SDKs with the release of Java SDK 3.3.0, to make it easier for users to get started.
This document details the small changes that existing users of the legacy transactions library need to make, to migrate to the SDK-integrated version.
The legacy transactions library will continue to be supported with bugfixes for some time, but new transaction features will only be added to the SDK and it is recommended that all users migrate.
Accessing transactions
This is now done via a Cluster
object.
There is no longer any need to create a Transactions
object.
var transactions = Transactions.create(cluster);
transactions.run((ctx) -> {
// Your transaction logic.
});
cluster.transactions().run((ctx) -> {
// Your transaction logic.
});
Configuration
Configuration used to be performed when creating the Transactions
object, and is now performed when creating the Cluster
object.
var transactions =
Transactions.create(cluster,
TransactionConfigBuilder.
.durabilityLevel(TransactionDurabilityLevel.MAJORITY)
.metadataCollection(collection));
var keyspace = TransactionKeyspace.create("bucketName", "scopeName", "collectionName");
var cluster = Cluster.connect("localhost", ClusterOptions.clusterOptions("username", "password")
.environment(env -> env.transactionsConfig(TransactionsConfig
.durabilityLevel(DurabilityLevel.PERSIST_TO_MAJORITY)
.metadataCollection(keyspace))));
A few details of configuration change:
-
TransactionsConfig::metadataCollection
takes aTransactionKeyspace
instead of aCollection
(since aCollection
cannot be created at this point). -
keyValueTimeout
has been removed fromTransactionsConfig
andTransactionOptions
. -
TransactionDurabilityLevel
has been dropped in favour of using the SDK’sDurabilityLevel
. -
TransactionOptions
now allows ametadataCollection
parameter.
And certain classes have been renamed to be compliant with the Java SDK:
Before | After | |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
Cleanup configuration
Cleanup configuration options have been encapsulated into their own class:
var transactions =
Transactions.create(cluster,
TransactionConfigBuilder.create()
.cleanupClientAttempts(false)
.cleanupLostAttempts(false)
.cleanupWindow(Duration.ofSeconds(30)));
var cluster = Cluster.connect("localhost", ClusterOptions.clusterOptions("username", "password")
.environment(env -> env.transactionsConfig(TransactionsConfig
.cleanupConfig(TransactionsCleanupConfig
.cleanupClientAttempts(true)
.cleanupLostAttempts(true)
.cleanupWindow(Duration.ofSeconds(30))))));
Lambda
ctx.commit()
has been removed, as it is redundant: commit automatically happens when the lambda successfully reaches the end.
ctx.rollback()
has been removed, as it too is redundant: the application can throw any exception from the lambda to trigger a rollback.
ctx.getOptional()
has been replaced with ctx.get()
throwing a DocumentExistsException
.
This may be caught, allowing the transaction to continue.
Package changes
All classes have changed packages to be compatible with the Java SDK conventions.
The simplest way to convert many of the classes to their new locations is to search for import com.couchbase.transactions.
and replace it with import com.couchbase.client.java.transactions.
.
Some additional manual conversion after this may be required.
Single query transactions
These are now integrated with the existing SDK QueryOptions
.
SingleQueryTransactionResult sqr = transactions.query("INSERT...");
QueryResult qr = cluster.query("INSERT...", queryOptions().asTransaction());
Or with configuration:
SingleQueryTransactionResult sqr = transactions.query("INSERT...",
SingleQueryTransactionConfigBuilder.create()
.durabilityLevel(TransactionDurabilityLevel.MAJORITY));
QueryResult qr = sqr.queryResult();
QueryResult qr = cluster.query("INSERT...",
queryOptions().asTransaction(
singleQueryTransactionOptions()
.durabilityLevel(DurabilityLevel.MAJORITY)));
Cleanup
This doesn’t impact the API, but it is useful to know that lost cleanup has changed.
Previously, lost cleanup would look for expired transactions on the default collections of all buckets in the cluster. Unless a metadata collection was specified, in which case only that collection would be cleaned up.
Now, cleanup is dynamic. As transactions are run, the collection where metadata is created for that collection, is added to what we call the 'cleanup set'. This is just the set of collections where cleanup, for this application, is looking for expired transactions.
The intent has always been that users without complex requirements should never need to think about or configure transaction cleanup, and this new dynamic cleanup allows us to be closer still to that goal.
Naming
All exceptions and events have been renamed to be compliant with the SDK.
For example, TransactionFailed
is now TransactionFailedException
, and TransactionCleanupAttempt
is now TransactionCleanupAttemptEvent
.
Logging
TransactionFailedException
now exposes the logs directly, rather than containing a nested TransactionResult
.
catch (TransactionFailedException err) {
err.result().log().logs().forEach(msg -> logger.warning(msg.toString()));
}
catch (TransactionFailedException err) {
err.logs().forEach(msg -> logger.warning(msg.toString()));
}
Further Reading
-
There’s plenty of explanation about how Transactions work in Couchbase in our Transactions documentation.