Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Transaction support is being added for ESR Microservices. Transactions apply to RabbitMQ message sending and MongoDB inserts/updates.

Transactions in RabbitMQ

Nothing needs to be done on the RabbitMQ side to use transactions. The configuration and setup that’s required is all done within our Microservices.

There are 3 basic requirements to enable RabbitMQ transactions:

  1. setChannelTransacted(true) on the RabbitTemplate

  2. register a org.springframework.amqp.rabbit.transaction.RabbitTransactionManager Spring Bean.

  3. add the ‘org.springframework.transaction.annotation.Transactional' annotations to the code which we want to wrap in a rabbit transaction.

Transactions in MongoDB

Transactions are a relatively new feature of MongoDB (since v4.0)

https://docs.mongodb.com/manual/core/write-operations-atomicity/

To use MongoDB transactions - we have to have the MongoDB setup in ReplicSet mode AND we have to make configuration/setup changes with our Microservices.

In the code, there are 3 steps required to use MongoDB transactions.

  1. register a org.springframework.data.mongo.MongoTransactionManager Spring Bean.

  2. add the ‘org.springframework.transaction.annotation.Transactional' annotations to the code which we want to wrap in a MongoDB transaction.

  3. make sure any Mongo collections you need to use within a transaction are created outside of the transaction in advance. When using Mongo Transactions - you can no longer create a collection within a transaction by inserting into it. To work around this there is a class com.hee.tis.esr.common.transactions.MongoCollectionInitializerConfig which looks for instances of Spring Data Repositories and creates any Mongo Collections required on application startup. This is a temporary solution until we are using something like mongobee to make sure collections are created as part of the installation process.

The MongoTransactionManager works with inserts/updates to mongo through Spring Mongo Data repositories.

There are not a great number of examples showing how Spring works with MongoDB transactions. The example here is a bit limited.
https://github.com/spring-projects/spring-data-examples/tree/master/mongodb/transactions

It relies on custom embeddedMongoDb for testing and seems to suggest you need to use mongoTemplate when updating Mongo within a transaction. This is misleading - you can use Spring Data Mongo Repositories which are easier to use than mongoTemplates.

Global Transaction Manager

We want to link the RabbitMQ and MongoDB transaction managers so that they work together. To do this we create a parent/global transaction manager which delegates its commit/rollback calls to its child (mongo and rabbit) transaction managers. We can use the built in Spring ChainedTransactionManager which can have 1 or more child transaction managers. The ChainedTransactionManager is registered as a Primary TransactionManager so Spring knows which of the Transaction Managers to use when there is more than 1.

We create a RabbitTransactionManager if required based on a boolean property app.transactions.rabbit.enabled having value ‘true’.

We create a MongoTransactionManager if required based on a boolean propertyapp.transactions.mongo.enabled having value 'true’.

If have at least 1 Rabbit or Mongo Transaction Manager, then we create a ‘parent' transaction manager.

If we have neither Rabbit or Mongo transaction manager - we register a dummy/NoOp - TransactionManager. If we have code annotated with ‘@Transactional’, Spring demands that we have a Transaction Manager - so we register a dummy, NoOp TransactionManager to keep it happy. We cannot switch off the ‘@Transactional' annotation, so we just use a dummy Transaction Manager.

We have created our own class for this
com.hee.tis.esr.common.transaction.NoopTransactionManager.

based on the abstract library class org.springframework.transaction.support.AbstractPlatformTransactionManager

Common Classes in the com.hee.tis.esr.common.transactions package, used to support Rabbit and Mongo transactions

Class Name

Description

ImportTransactionConfig

A Spring annotation used to pull in the transaction support.

Microservices wanting to pull in TransactionSupport should add ‘@ImportTransactionConfig’ to their Spring Boot Application class.

MongoCollectionInitializerConfig

Looks for Spring Data Mongo Repositories on startup and creates the required Collections in MongoDB if they don’t already exist.

NoopTransactionManager

Noop/Dummy Transaction Manager class. SeeTxConfigNoop

TxConfig

On application startup, logs the actual TransactionManager being used.

TxConfigGlobal

Creates a ChainedTransactionManager parent to wrap the Rabbit and/or Mongo Transaction Managers if required. If created, this Spring Bean is named txManagerGlobal.

TxConfigMongo

Creates a MongoTransactionManager Spring Bean if the property app.transactions.mongo.enabled has value 'true’.

If created, this spring bean is named txManagerMongo

TxConfigNoop

Creates a Spring bean using NoopTransactionManager if there is no bean named txManagerGlobal. If created, this spring bean is named txManagerNoop

TxConfigRabbit

If the property app.transactions.rabbit.enabled has value 'true’ do the following:

  • Create the RabbitTransactionManager Spring Bean namedtxManagerRabbit

  • call setChannelTransacted(true) on the RabbitTemplate.

  • No labels