Spring – Multiple Spring Data modules found, entering strict repository configuration mode

Sorry for answering too late, but I think answers that present already does not explain the actual, deep reason why is it happening. Let me explain everything in order to let you understand the guts (be ready, it will be quite long and comprehensive). If you are looking for simple solution, go to the bottom of my answer:

First of all, the spring data, as a general module (forget about particular modules, like spring data jpa, or spring data redis), has an hierarcy of interfaces. It begins from Repository, then comes CrudRepository, and after that there is PagingAndSortingRepository. I will not get into details about the difference between them, this is not the point now. What is important – this interfaces are absolutely segregated from the particular persistence storage, just becuase they are technically resides within the separate JAR that shipps right away with any particular spring data implementation (it is called spring-data-commons, see official doc, if you are interested)

What do I mean – you can use Spring data module for MongoDB. In order to take advantage of spring data mongodb what would you typically do: right, extend the CrudRepository, or Repository or MongoRepository. It is very important – from the spring-data perspective, if you create your own interface by extending Repository, or CrudRepository and you did not marked the target repository entity anyhow (I will explain at the end of the answer), then Spring will basically try to find out by itself, how exactly this magical methods: findById, deleteById and e.t.c. must by implemented, becuase obviously thier implementation will be different in Mongo and in JPA. With this in mind, read on.

The question is – how exactly spring determines, the way you custom interfaces must be implemented? Well, there is an abstraction within the Spring guts, called RepositoryFactoryBeanSupport. This is the thing that actually participate in beans creation from your custom repositories. Lets make an experiment now: Try out add both spring data jdbc starter and spring data mongodb starter into your project. You will notice, that in your classpath there are 2 diffrenet implementations of RepositoryFactoryBeanSupport:

  1. JdbcRepositoryFactoryBean (comes from spring data jdbc starter)
  2. MongoRepositoryFactoryBean (comes from spring data mongo starter)

Then, lets assume, that I have an entity, like this:

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Customer {

    @Id
    private Long id;

    @Column("firstname")
    private String firstName;

    @Column("phone")
    private String phone;
}

Also note: the Id and the Column annotations are actually spring data annotations, not JPA.

Then lets define an interface (simple dao interface):

public interface CustomerCRUDRepository extends CrudRepository<Customer, Long> {
    int countByFirstName(String firstName);
}

And now, inject the bean of type CustomerCRUDRepository somewhere. Just try to bootstrap the application – you will fail. Why? Let`s investigate the logs together:

RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!

RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode

RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.example.springdatajdbc.repositories.CustomerCRUDRepository

The same exception as in your question, is not it? Let us finally break this down. Now let me finally answer the question.

So, why does this exception appear:

When you, having multiple spring-data modules within a project, try to create an interface for specific entity, that does not annotated with specific to persistence technology annotation (like @Entity in javax.persistence, or @Document in case of mongo, you name it), by extending the interface from spring-data-commons module (i.e. Repository or CrudRepository) – this will not work at all, becuase spring has basically no idea, to which exactly data storage you entity is assosiated. Is it MongoDb? or is it JPA? Or Cassandra? – it is impossible to determine in that way, see official doc. On the other hand, when there is only one spring data module in classpath – spring can conclude all by itself, becuase it is not ambiguous.

What can you do to solve it:

  1. Extend the techonogiy specific repository. For example, if you want entity A to be assosiated with PostgreSQL, then do not use CrudRepository – use JpaRepository. If you want entity B to be assosiated with Redis, the use RedisRepository and so on.

  2. Annotate your entity with annotation, that indicate it affiliation to the specific data storage. @Entity, @Document, @Table and so on.

I hope, this is clear now. I really did my best to explain it to you. Thanks for reading, have a nice day!

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)