conditional repository injection - Spring Boot

Viewed 1718

I Have two repository interfaces that connect MongoDB and CouchBase :

public interface UserRepositoryMongo extends MongoRepository<User, Long> {
}
public interface UserRepositoryCouch extends  CouchbasePagingAndSortingRepository<User, Long> {
}

Is there a way to interchangeably @Autowire these repositories into UserService on condition? The condition will be inside property file : application.properties.



**Note :**

*These repositories can have custom methods too.*
2 Answers

We can use either ConditionalOnProperty or ConditionalOnExpression to switch between two different repository implementation.

  1. If we want to control the autowiring with simple property presence/absence or property value, then ConditionalOnProperty can be used.

  2. If complex evaluation is required, then we can use ConditionalOnExpression.

ConditionalOnProperty (presence/absence of a property)

@Qualifier("specificRepo")
@ConditionalOnProperty("mongo.url")
public interface UserRepositoryMongo extends MongoRepository<User, Long>{
}

@Qualifier("specificRepo")   
@ConditionalOnProperty("couch.url")
public interface UserRepositoryCouch extends  CouchbasePagingAndSortingRepository<User, Long>{
}

ConditionalOnProperty (based on value)

@ConditionalOnProperty("repo.url", havingValue="mongo", matchIfMissing = true) //this will be default implementation if no value is matching
public interface UserRepositoryMongo extends MongoRepository<User, Long> {
}

@ConditionalOnProperty("repo.url", havingValue="couch")
public interface UserRepositoryCouch extends  CouchbasePagingAndSortingRepository<User, Long> {
}

ConditionalOnExpression

@ConditionalOnExpression("#{'${repository.url}'.contains('couch')}")
public interface UserRepositoryCouch extends  CouchbasePagingAndSortingRepository<User, Long> {
}

UPDATE

Use CrudRepository/Repository type to inject based on your requirement.

public class DemoService {

    @Autowired
    @Qualifier("specificRepo")
    private CrudRepository repository;
}

Based on bean created, either UserRepositoryMongo or UserRepositoryCouch will be autowired. Make sure only one bean is instantiated to avoid ambiguity error.

Another attempt to solve this problem.

Based on the property, the autowired customRepository will be an instance of SimpleMongoRepository or SimpleCouchRepository.

    public interface CustomRepository extends CrudRepository<User, Long> {
        User findByLastName(String lastName); //custom methods
    }

    @Qualifier("specificRepo")
    @ConditionalOnProperty("mongo.url")
    public interface UserRepositoryMongo extends MongoRepository<User, Long>, CustomRepository{
    }

    @Qualifier("specificRepo")   
    @ConditionalOnProperty("couch.url")
    public interface UserRepositoryCouch extends  CouchbasePagingAndSortingRepository<User, Long>, CustomRepository{
    }

    public class UserService {

        @Autowired
        @Qualifier("specificRepo")
        private CustomRepository repository;
    }
Related