'Springboot Mongo db methods doesnt rollback transactions
Hi i am using 2 mongo template in my codebase and my code saves data in mongo db using both mongo template and Spring repository class.save() .In methods which has @Transactional doesnt rollback DB changes even if some error occurs in code execution. Below is the snippet of my mongoconfig configurations
@Configuration
@EnableMongoAuditing
@EnableMongoRepositories
public class MongoConfig extends AbstractMongoClientConfiguration {
@Value("${common.db.name}")
private String dbName;
@Value("${SPRING_DATA_MONGODB_URI}")
private String dbUrl;
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
@Override
protected String getDatabaseName() {
return dbName;
}
/**
* Below bean is created as we want to make our code transactional.
* @param dbFactory
* @return
*/
@Bean(name="primaryTransactionManager")
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
MongoTransactionManager transactionManager = new MongoTransactionManager(dbFactory);
transactionManager.setRollbackOnCommitFailure(true);
return transactionManager;
}
@Override
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString(dbUrl);
MongoClientSettings mongoClientSettings = MongoClientSettings.builder().applyConnectionString(connectionString).build();
return MongoClients.create(mongoClientSettings);
}
@Bean(name="primaryMongoTemplate")
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoClient(), getDbName());
}
}
@Configuration
@EnableMongoRepositories
public class SecondaryMongoConfig {
@Value("${common.secondary.db.name}")
private String dbName;
@Value("${COMMON_SECONDARY_SPRING_DATA_MONGODB_URI}")
private String mongoDBURI;
public String getMongoDBURI() {
return mongoDBURI;
}
public void setMongoDBURI(String mongoDBURI) {
this.mongoDBURI = mongoDBURI;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
/**
* Below bean is created as we want to make our code transactional.
* @param dbFactory
* @return
*/
@Bean(name="secondaryTransactionManager")
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
MongoTransactionManager transactionManager = new MongoTransactionManager(dbFactory);
transactionManager.setRollbackOnCommitFailure(true);
return new MongoTransactionManager(dbFactory);
}
@Bean(name="secondaryMongoClient")
public MongoClient secondaryMongoClient() {
ConnectionString connectionString = new ConnectionString(getMongoDBURI());
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
@Bean(name="secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() {
return new MongoTemplate(secondaryMongoClient(), getDbName());
}
}
Below is my sample code snippet of method annoted with @Transactional
@Override
@Transactional(transactionManager = "primaryTransactionManager",rollbackFor = {Exception.class})
public String addNewRecipe() throws Exception{
RecipesDAO recipesDao = new RecipesDAO();
recipesDao.setResourceId(UUID.randomUUID().toString());
recipeRepository.save(recipesDao);
throw new Exception();
// return "dummy";
}
Solution 1:[1]
I got solution after checking each and every method of classes used in my class MongoConfig.java.Below is the snippet of code which i had to use in order to rollback transactions when exceptions occured in code execution flow
@Bean(name="primaryMongoTemplate")
public MongoTemplate mongoTemplate() {
MongoTemplate primaryMongoTemplate = new MongoTemplate(mongoClient(), getDbName());
primaryMongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS);
return primaryMongoTemplate;
}
@Bean(name="secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() {
MongoTemplate secondaryMongoTemplate = new MongoTemplate(secondaryMongoClient(), getDbName());
secondaryMongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS);
return secondaryMongoTemplate;
}
Earlier wherever code of creating new or modifying mongodb docs was there like say somerepository.save(s) code used to create or modify documents immedialtely but by adding primaryMongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS); and secondaryMongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS); code waits for complete execution flow and checks if any exception occured in this execution flow.It creates or modifies documents only after checking no exception occured in execution flow.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Sanjay Naik |
