0

Currently, I am using the following code:-

(I have marked the two important lines in the code. Between these lines are just some operations on existing documents)

clientSession.startTransaction();  // Important Line 1.
Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", to + "Backup");
Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", from + "Backup");
Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
assert foundWalletDetailDoc1 != null;
assert foundWalletDetailDoc2 != null;
assert foundWalletDetailDoc3 != null;
Bson updateWalletDoc = walletDetailDoc;
Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
walletDistributionCollection.updateOne(foundWalletDetailDoc1, updateWalletDocOperation);
updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
        .append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
        .append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
        .append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
        .append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
updateWalletDocOperation = new Document("$set", updateWalletDoc);

//////// TEMPORARY... TO BE REMOVED
Thread.sleep(5000);
clientSession.abortTransaction();  // Important Line 2
boolean abc = true;
if(abc) {
    return;
}
////////

Now, I excepted that once I call abortTransaction(), the collection would revert back to it's previous state as it was before //Important Line 1. But that doesn't happend. As I keep making operations, they get saved in MonogDB and do not get reverted when // Important line 2 completes execution.

(Just in case, everything is in try catch and there are no errors between any lines. The code successfully reaches the return statement.)

Also, if required, I am using the following maven dependency:-

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>4.2.0</version>
</dependency>

How to do this operation properly such that everything gets done, or nothing gets done (i.e. rollback/abort).

2 Answers 2

2

You need to include the write operations inside the session transaction , example:

original state of collection:

 mongos> db.tra.find()
 { "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
 { "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
 mongos> 

1 Now you start session:

 session = db.getMongo().startSession()

2 Now you start transaction in the started session:

 mongos> session.startTransaction()

3 You insert test document to the collection in the transaction:

 mongos> session.getDatabase("test").tra.insert({a:"this will be aborted",today : new Date()})
 WriteResult({ "nInserted" : 1 })

4 Check the collection now , there is no inserted document(transaction is yet not commited):

 mongos> db.tra.find()
 { "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
 { "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }

5 Now abort the transaction:

 mongos> session.abortTransaction()

6 As you can see nothing is inserted(transaction was aborted):

 mongos> db.tra.find()
{ "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
{ "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
mongos> 

Afcourse if you replace step 5 with session.commitTransaction() the transaction will be commited and you will see the operations applied to the collection.

There is nice java example here : https://www.mongodb.com/blog/post/java-and-mongodb-40-support-for-multidocument-acid-transactions

Sign up to request clarification or add additional context in comments.

1 Comment

This example uses the mongoshell, and does not demonstrate how to use the Java driver features of mongodb sessions and transactions, not to mention the auto-close try.
1

Correct answer was pretty simple...

(Found by referring to the link at the very bottom of @R2D2 's answer.)

(TL;DR :- Add clientSession as the first parameter in updateOne method).

All we had to do is this :-

        clientSession.startTransaction();  // Important Line 1.
        Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
        Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        walletDetailDoc = new Document("identifier", to + "Backup");
        Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        walletDetailDoc = new Document("identifier", from + "Backup");
        Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
        assert foundWalletDetailDoc1 != null;
        assert foundWalletDetailDoc2 != null;
        assert foundWalletDetailDoc3 != null;


        Bson updateWalletDoc = walletDetailDoc;
        Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
        walletDistributionCollection.updateOne(clientSession, foundWalletDetailDoc1, updateWalletDocOperation);
        updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
                .append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
                .append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
                .append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
                .append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
        updateWalletDocOperation = new Document("$set", updateWalletDoc);
        
        //////// TEMPORARY... TO BE REMOVED
        Thread.sleep(5000);
        clientSession.abortTransaction();  // Important Line 2
        boolean abc = true;
        if(abc) {
            return;
        }
        ////////

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.