Search code examples
springmongodbspring-boottransactionsspring-transactions

Spring Boot Transaction support using @transactional annotation not working with mongoDB, anyone have solution for this?


Spring Boot version - 2.4.4, mongodb version - 4.4.4

In my project, I want to do entry in 2 different document of mongodb, but if one fails than it should do rollback. mongodb supports transaction after version 4.0 but only if you have at least one replica set.

In my case I don't have replica set and also cannot create it according to my project structure. I can't use transaction support of mongodb because no replica-set. So, I am using Spring Transaction.

According to spring docs, to use transaction in Spring Boot, you only need to use @transactional annotation and everything will work(i.e. rollback or commit). I tried many things from many sources but it is not rollbacking transaction if one fail.

Demo code is here, This is demo code, not actual project. This is my service class.

@Service
public class UserService {
  @Autowired
  UserRepository userRepository;

  @Autowired
  UserDetailRepository userDetailRepository;

  @Transactional(rollbackFor = Exception.class)
  public ResponseEntity<JsonNode> createUser(SaveUserDetailRequest saveUserDetailRequest) {

   try {
       User _user = userRepository.save(new User(saveUserDetailRequest.getId(), saveUserDetailRequest.getFirstName(), saveUserDetailRequest.getLastName()));

       UserDetail _user_detail = userDetailRepository.save(new UserDetail(saveUserDetailRequest.getPhone(), saveUserDetailRequest.getAddress()));

       } catch (Exception m) {
      System.out.print("Mongo Exception");
  }
    return new ResponseEntity<>(HttpStatus.OK); 

 }
}

Also tried below code but still not working,

@EnableTransactionManagement
@Configuration
@EnableMongoRepositories({ "com.test.transaction.repository" })
@ComponentScan({"com.test.transaction.service"})
public class Config extends AbstractMongoClientConfiguration{

  private com.mongodb.MongoClient mongoClient;

  @Bean
   MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
       return new MongoTransactionManager(dbFactory);
   }
  @Bean
  public com.mongodb.MongoClient mongodbClient() {
    mongoClient = new com.mongodb.MongoClient("mongodb://localhost:27017");
    return mongoClient;
}

@Override
protected String getDatabaseName() {
    return "test";
    }
}

Solution

  • The transaction support in Spring is only there to make things easier, it doesn't replace the transaction support for the underlying datastore being used.

    In this case, it will simply delegate the starting/committing of a transaction to MongoDB. WHen using a database it will eventually delegate to the database etc.

    As this is the case, the pre-requisites for MongoDB still need to be honoured and you will still need a replica.