spring boot multiple mongodb datasource - spring

We are using spring boot and we have multiple mongodbs within the system. We are able to configure "one" mongodb in application.properties files, as per the spring boot documents. Now we have a need to write to multiple mongodbs. How can we configure this?
Hope someone can help and any code examples would be helpful.
Thanks
GM

Use multiple #Bean methods, where you create and configure your datasources, and specify the bean name to distinguish them.
Example:
#Bean("primary")
public Mongo primaryMongo() throws UnknownHostException {
Mongo mongo = new Mongo();
// configure the client ...
return mongo;
}
#Bean("secondary")
public Mongo secondaryMongo() throws UnknownHostException {
Mongo mongo = new Mongo();
// configure the client ...
return mongo;
}
When you want to access the datasource, use the #Qualifier annotation on the field to specify the datasource with the bean name:
#Autowired
#Qualifier("primary")
private Mongo mongo;

Related

Custom DataSource Spring boot

spring works well when we use the default datasource and ways we can use in-build spring jpa.
So currently what we do is the following
specify the config for DB in the application.properties
myapp.datasource.url=jdbc:mysql:thin:#localhost:1521:myschema
myapp.datasource.username=user
myapp.datasource.password=password
myapp.datasource.driver-class=com.mysql.cj.jdbc.Driver
Custom datasource
#ConfigurationProperties(prefix = "myapp.datasource")
#Bean
public DataSource mySqlDataSource()
{
return DataSourceBuilder.create().build();
}
We have the same application running for multiple clients. Problem is each client has their own DB schema.
So, the problem now is that we need to be able to serve each client but in order to do this, we need to create multiple datasources
for instance:
#ConfigurationProperties(prefix = "myapp.partner1.datasource")
#Bean
public DataSource mySqlDataSourcePartner1()
{
return DataSourceBuilder.create().build();
}
#ConfigurationProperties(prefix = "myapp.partner2.datasource")
#Bean
public DataSource mySqlDataSourcePartner2()
{
return DataSourceBuilder.create().build();
}
#ConfigurationProperties(prefix = "myapp.partner3.datasource")
#Bean
public DataSource mySqlDataSourcePartner3()
{
return DataSourceBuilder.create().build();
}
and so on...
Is there a generic and more efficient way of doing this? where if in future when a new partner is added we can just specify the config in application properties and get that working?
You can use Spring Boot Multi-tenancy model using a separate database for each client. You can save the database configuration in config-properties or database then depending upon the ClientId you can you the Datasource. You need to add Interceptor to intercept the Request and identify the tenant. Please refer to the below example
https://tech.asimio.net/2017/01/17/Multitenant-applications-using-Spring-Boot-JPA-Hibernate-and-Postgres.html
please check
https://github.com/sumanentc/multitenant

Setting up in-memory H2 database without Spring Boot

I am working in a spring 5 (Not Sprig Boot) project. I need to test my application with in-memory H2 database. I am using Spring with Java Config on maven build tool. Is there any way I can configure in-memory H2 DB?
Usually I use this in my #Config class:
#Bean
public DataSource h2TestDataSource(){
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
So I use Spring Embedded DB in my spring projects (I don't use spring boot)
I hope it's useful.
You can add the DataSource bean using the EmbeddedDatabaseBuilder as follows:
#Bean
public DataSource dataSource(
#Value("${datasource.dbname}") String dbname,
#Value("${datasource.script}") String script) {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.setName(dbname)
.addScript(script)
.build();
}
application.properties
datasource.dbname=users
datasource.script=classpath:resources/users.sql
Also you can register h2-console servlet in the application configuration class as follows:
#Configuration
public class WebAppConfig implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) {
. . .
servletContext
.addServlet("H2Console", WebServlet.class)
.addMapping("/console/*");
. . .
}
}
Then you can open http://localhost:8080/console and connect to the jdbc:h2:mem:users database as follows:
See also How to enable h2-console in spring-webmvc without spring-boot?

Warning: Not loading a JDBC driver as driverClassName property is null, in springboot working with two datasources

I have currently configured spring boot to work with two different datasources. The application is working fine, however when I start the spring boot application I get an warning repeated 10 times like below:
2018-06-05 10:28:15.897 WARN 8496 --- [r://myScheduler] o.a.tomcat.jdbc.pool.PooledConnection : Not loading a JDBC driver as driverClassName property is null.
As I mentioned this is not affecting my application, but I would like to know why I am having this kind of warning and if there is any way to fix it.
When using two or more datasources you need to configure them yourself. In that case Spring Boot's DataSourceAutoConfiguration (and also DataSourceProperties) won't be used.
You most probably have the related DB details like the name of the JDBC driver class name in application.properties file as follows:
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
primary.datasource.url=jdbc:sqlserver://xxx.yyy.zzz.www:1433;databaseName=primaryDB
primary.datasource.username=username
primary.datasource.password=password
other.datasource.url=jdbc:sqlserver://xxx.yyy.zzz.www:1433;databaseName=otherDb
other.datasource.username=otheruser
other.datasource.password=otherpassword
Thus, to set the driver class name for the datasource just say:
#Value("${spring.datasource.driver-class-name}")
String driverClassName;
#Primary
#Bean(name = "primaryDb")
#ConfigurationProperties(prefix = "primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().driverClassName(driverClassName).build();
}
#Bean(name = "otherDb")
#ConfigurationProperties(prefix = "other.datasource")
public DataSource otherDataSource() {
return DataSourceBuilder.create().driverClassName(driverClassName).build();
}

Spring Data MongoDB Configure Database bean

How to I configure the Mongo database bean? The bean is initialized by the MongoDB driver somehow with somethings pre-configured. I can't get the bean using mongoClient.getDatabase() because the database name either comes from the connection uri or just the standard property. And I can't define a new bean to update the old one like this public MongoDatabase mongoDatabase(MongoDatabase database) because that causes a ban definition cycle loop. What do I do?
Not entirely relevant to the question, but here's my intention:
What I trying to do is add custom Conventions introduced in MongoDB Driver version 3.6.
http://mongodb.github.io/mongo-java-driver/3.6/bson/pojos/
I know that spring data mongodb uses an older version, so I just replaced it with the newer one.
You need to take care of couple of things if you wish to configure MongoTemplate Or MongoDatabase yourself.
You need to disable spring boot's Mongo Auto Configuration. You can achieve this as show below.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
You have to create MongoTemplate or MongoDatabase bean and register it with Spring application context(using #Bean).
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
ServerAddress server = new ServerAddress(host,port);
MongoClientOptions.Builder builder = MongoClientOptions.builder();
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new XYZCodec(..)),
MongoClient.getDefaultCodecRegistry());
builder.codecRegistry(codecRegistry).build();
MongoClientOptions options = builder.build();
MongoClient mongoClient = new MongoClient(server,options);
return new SimpleMongoDbFactory(mongoClient, mongoDataBase);
}
Replace XYZCodec with the codec you want.

Spring Solr connection with Zookeeper using jaas.conf

I am migrating an existing java project to Spring Boot. It connects to Solr via Zookeeper.
It is throwing following error on startup.
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /clusterstate.json
This following configuration works on local, but on other environments Zookeeper requires some authentication (jaas.conf). How do I pass the jaas.conf to Spring Boot such that it can initialize SolrClient correctly?
#Configuration
#EnableSolrRepositories(basePackages = "com.search", multicoreSupport = true)
public class SolrConfig {
#Value("${spring.data.solr.zk-host}")
private String zkHost;
#Bean
public SolrClient solrClient() {
return new CloudSolrClient(zkHost);
}
#Bean
public SolrTemplate solrTemplate(SolrClient solrClient) throws Exception {
return new SolrTemplate(solrClient);
}
}
jaas.conf
Client {
org.apache.zookeeper.server.auth.DigestLoginModule required
username="some_username"
password="some_password";
};
I tried passing credentials as environment properties of zkDigestUsername and zkDigestPassword. In this case there was no exception during Spring Boot startup, but subsequent inserts/reads to Solr is not working.
Any help would be appreciated. Thanks much!
I was able to fix the issue by providing jaas config using the following JVM parameter.
-Djava.security.auth.login.config=/etc/zookeeper/conf/jaas.conf

Resources