Spring rollback transaction from 2 Separate Databases - spring-boot

I have a Spring Boot server that collects 2 gRPC microservices - one of them works with the DynamoDB and another CockrachDB database. I need to make sure the commit works fine in both of the DB's and if not need to roll back from both of them.
The issue is if this is successful in the first DB and has an exception into the 2nd, it may not be possible normally to rollback from the 1st DB.
How can I achieve so the commit is either successful or failed in both of the DB's together?

For distributed transaction management frameworks or architectures, you can refer to these links:
https://seata.io/en-us/
https://microservices.io/patterns/data/saga.html
https://medium.com/#dongfuye/the-seven-most-classic-solutions-for-distributed-transaction-management-3f915f331e15
https://dba.stackexchange.com/questions/18435/cap-theorem-vs-base-nosql#:~:text=1%20Answer&text=CAP%20is%20Consistency%2C%20Availability%2C%20and,throws%20consistency%20out%20the%20window.
Hope these links can help.

Related

Multiple databases (Postgresql in RDS) but same spring repository and entity

I have a use case where I need to create exact same postgresql database in two different regions. Everything is same in these two databases i.e same schema and same tables and same data.
I have a use to achieve distributed transaction. So if a request land in region-a and write to region-a database to let's say Person table, then exact same record must be either written in Person table in both these database or if there is any error, write attempt should be rolled back.
I am trying to figure out if I can attach two different datasources with same Person Entity and CRUD repository in spring so the respoistory.save() method can write to Person table in both the databases.
So far, I have come across AbstractRoutingDataSource but that is for achieving multi tenancy in the databases. Other solutions are found are slightly different where use case is to write different records in different database (mostly sharding based on various data points).
Does spring provide any out of the box solution so I can achieve transactional write to same table in two different databases.
Does spring provide any out of the box solution so I can achieve transactional write to same table in two different databases.
Depends on your definition of "out of the box" - it doesn't itself implement distributed transactions, but does have support for using libraries that do. It is however relatively complicated to get everything working correctly, and requires additional components to be carefully configured in your runtime environment.
Spring Boot 2.x documentation on distributed transactions is here: https://docs.spring.io/spring-boot/docs/2.7.x/reference/htmlsingle/#io.jta
The Spring Boot 3.x documentation is here: https://docs.spring.io/spring-boot/docs/current/reference/html/io.html#io.jta but it's also worth noting that for 3.x, the Spring Boot team have changed direction and decided that integrated support should be provided by the relevant JTA provider (cf. https://github.com/spring-projects/spring-boot/issues/28589 ), and so there's projects like https://github.com/snowdrop/narayana-spring-boot

How to call database on multiple environments using Springboot JPA

I am new to Springboot and trying to build a small rest-service. We have a DB deployed on different environments (e.g. DEV, TEST). The rest-service will make a call to the appropriate database based on the received query param (e.g. ?env=TEST). The schemas of the deployed database are the same, the difference is only in connection string. I have some questions related to this task.
I read a few articles how to work with multiple databases using Spring JPA (for example this one: https://www.baeldung.com/spring-data-jpa-multiple-databases). It did work, but in the given example they get different entites from different databases using different queries, in my case the entity and the query is the same, but I still have to duplicate repositories, transactionManagers, entityManagers etc because of different datasources. And this is just two environments and I have more of them.
I have another thought that I might need to recreate the repository each time I process a request (to make the repository non-singleton). I am not sure if it is a good practice.
Maybe it worth to use JDBCTemplate instead of Spring JPA in this case?
Could you please suggest something how to approach such a task?

What are the ways to listen to the success or failure of transactions when working with Spring (spring boot, spring data)

When working with transactions, sometimes there is a need to do an audit of working with a business object (crud operations when working with tables). At the same time, you need to do this in real time and enter this record in the database :
the name of the user,
the business object with which the work is performed,
the success or rollback of the transaction with the fixing of the reason,
the time of the event occurrence.
Share ways to solve this problem, as you do when working with Spring data.
Do you create your own custom aspects ?
Give examples, if you don't mind .

How to do database schema testing across distinct applications that share the same schema

I have a situation where I have two SpringBoot microservices which share the same database schema. The schema is maintained by a liquibase changelog file. One service reads from the database, and the other service is responsible for writing to the database.
Right the Writing Service owns the liquibase changelog file, which means the Writing service owns the schema. And the way I validate the Reading Service is to deploy the Writing service first into a test environment followed by the Reading Service, and then execute end-to-end tests against the Reading Service.
Is there a way for both services (two separate apps, two separate repos) to share the liquibase changelog file? I feel this is similar to a contract test as the changelog file will be the contract for both services, but wasn't sure if there was something provided by Liquibase, Spring, Pact, etc that supported this idea.
Thanks for your time!
I think it won't count as a legit answer, but two solutions come to mind:
since your second service reads from the database, I suppose you have a full set of entities there, and entities are supposed to match your database schema. And since you're using Spring, I suppose you can add spring.jpa.hibernate.ddl-auto=validate to the application.properties file. This will validate your database schema against the entities.
You can create a separate library which will contain all the changeLogs. After that you can include this library to both services, so liquibase will validate that all changeSets are executed during application's deployment. But you should make sure that all your changeSets have preConditions, so your deployment won't fail and there won't be any duplicates in the DB schema.

Transaction management in database when two spring boot application trying to access the same record

Two spring boot applications are connected to the common database.
I just wanted to know, how to handle the transaction if both the application try to update the record at the same time?
Since you seem to use JPA (via Spring Data JPA) there isn't much to handle.
The database itself will prevent two transactions to update the record at the same time. So one will always be first.
If you use optimistic locking (which is the default with JPA) the second transaction will notice the modified row and rollback.
Without that the second transaction will simply overwrite the changes with it's own changes.

Resources