1

I have an app with multiple mongo configurations. This is achieved through some @Configuration classes like so

public abstract class AbstractMongoConfig {
    private String database;
    private String uri;

    public void setUri(String uri) {
        this.uri = uri;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(new MongoClientURI(this.uri)), this.database);
    }

    abstract public MongoTemplate getMongoTemplate() throws Exception;
}

Config 1 -- app

@Configuration
@ConfigurationProperties(prefix="app.mongodb")
public class AppMongoConfig extends AbstractMongoConfig {
    @Primary
    @Override
    @Bean(name="appMongoTemplate")
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}

Config 2 -- test

@Configuration
@ConfigurationProperties(prefix="test.mongodb")
public class TestMongoConfig extends AbstractMongoConfig {
    @Override
    @Bean(name="testMongoTemplate")
    public MongoTemplate getMongoTemplate() throws Exception {
        return new MongoTemplate(mongoDbFactory());
    }
}

Then in my properties

test.mongodb.uri=mongodb://127.0.0.1/test
test.mongodb.database=test
app.mongodb.uri=mongodb://127.0.0.1/app
app.mongodb.database=app

So, two mongo configs wired up to an instance running locally but with different databases. I have tried it with different addresses also but it behaves the same.

Anyway, this then gets used via an Entity and MongoRepository

@Document(collection="collname")
public class TestObj {

    @Id
    private String id;

    private String username;
    private int age;
    // getters & setters
}

Repo

@Repository
public interface TestObjRepository extends MongoRepository<TestObj, String> {
    public TestObj findByUsername(String username);
}

However when I use this in some class somewhere

@Service
public class ThingDoer {

    @Autowired
    TestObjRepository toRepo;

    public void doStuff() {
        TestObj to = new TestObj("name", 123);
        toRepo.save(to);
    }
}    

This object gets written into the TestMongoConfig one not the AppMongoConfig as I would expect since that's the one annotated with @Primary. Further, if I add the @EnableMongoRepositories annotation on the ThingDoer like:

@EnableMongoRepositories(basePackages={"com.whatever.package"}, mongoTemplateRef="appMongoTemplate")

It still doesn't work. It still writes to the db referenced by "test".

If I @Autowire in the MongoTemplate directly and use that, it works as I expect. Things go to the "app" repo. How can I tell it which database that the TestObjRepository should be writing to and reading from?

MichaelB
  • 1,092
  • 2
  • 16
  • 32
  • 1
    Why are both configurations active at the same time? – chrylis -cautiouslyoptimistic- Jun 28 '18 at 23:46
  • Because both are used... some components interact with one database, some with the other... I guess calling one "test" in the example was probably a bad idea. Think of it as "app1" and "app2" – MichaelB Jun 28 '18 at 23:47
  • Try putting @ConfigurationProperties on the bean rather than configuration class. Because it is the bean that will fetch Configuration properties from properties file – deepansh2323 Jun 29 '18 at 06:24
  • @deepansh2323 I don't understand... I am not trying to tell the Component to use a particular configuration prefix, I am trying to tell the Repository which MongoTemplate to use – MichaelB Jun 29 '18 at 11:10

1 Answers1

0

So, if anyone else still has this problem, the solution is this:

@EnableMongoRepositories(basePackages={"com.whatever.package"}, mongoTemplateRef="appMongoTemplate")

You have to put it on your custom mongo properties. Where basePackages is the package path to your repo. You have to have one package for each mongo database, so it looks for the intended repository and model reference. And you also have to disable mongo auto configuration by spring, when using multiple DBs:

spring.autoconfigure.exclude:org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration

This is a great tutorial: https://dzone.com/articles/multiple-mongodb-connectors-with-spring-boot