How to Configure SpringBootApp with a Mongo Production Database - mongodb

I am creating a Spring Boot App with Mongo DB and scratching my head a bit with how to set up the production database configuration.
With a SQL-based Database, I'd be used to setting up a data source bean like this
#Bean
public DataSource getDataSource()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:file:C:/temp/test");
dataSourceBuilder.username("sa");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
However,
It doesn't seem to be needed - my local app connects to a spun up instance of mongo db without any explicit configuration.
It doesn't seem to be a standard with mongo according to [this post][1]
I figured I'd give it a go to see if it would automagically configure in production, but I'm getting a DataAccessResourceFailureException. Info: heroku, did the mLab MongoDB add on.
I have no problem getting the url and I can certainly throw that in an environment variable, but I'm just not sure what I need to add to my app to configure it.

Set values in application.properties file like below
spring.data.mongodb.database = ${SPRING_DATA_MONGODB_DATABASE}
spring.data.mongodb.host = ${SPRING_DATA_MONGODB_HOST}
spring.data.mongodb.port = ${SPRING_DATA_MONGODB_PORT}
You can use the #Value annotation and access the property in whichever Spring bean you're using
#Value("${userBucket.path}")
private String userBucketPath;
The Externalized Configuration section of the Spring Boot docs, explains all the details that you might need.

Related

Hazelcast reactive support for WriteThrough in Hazelcast 4.2

We wanted to implement WriteThrough/write behind in Hazelcast using MapStore for Postgres DataStore using ReactiveClient. But could not succeed and we are also not getting any sample for reactive approach.
We are implementing MapStore Interface to achieve WriteThrough Caching Pattern.
we have to inject the Respository in Mapstore and we are trying inject using #Autowired Annotation.
But we are not able to do, we are getting error repository as null.
Can we get some working example for Hazelcast 4.2 with Postgress as Datastore in reactive way?
Thanks
Jeni Ambrose
We tried with Autowiring the Repositories in Mapstore implementation
Here's one way:
#Bean
public Config config(AccountRepository accountRepository) {
Config config = new ClasspathYamlConfig("hazelcast.yml");
MapStoreConfig accountMapStoreConfig = new MapStoreConfig();
accountMapStoreConfig.setInitialLoadMode(MapStoreConfig.InitialLoadMode.EAGER);
accountMapStoreConfig.setEnabled(true);
accountMapStoreConfig.setImplementation(new AccountMapLoader(accountRepository));
MapConfig accountMapConfig = new MapConfig();
accountMapConfig.setName("account");
accountMapConfig.setMapStoreConfig(accountMapStoreConfig);
config.getMapConfigs().put(accountMapConfig.getName(), accountMapConfig);
return config;
}
You can have most (or none!) of the config in a static file, load it, and amend it to add Spring managed bits.
Also, 4.2 is old, use 5.2.1 or whatever is newest when you get to doing this.

What is a schema manager in Spring's Hibernate and how I set it?

Some tables were dropped at development environment during a spring-data-jpa project test and the developer responsible for it said it only used spring.jpa.hibernate.ddl-auto=update. Checking here, I suspected he had it set as create-drop, but since he said he didn't use, I went for this piece of information:
Spring Boot chooses a default value for you based on whether it thinks your database is embedded.
It defaults to create-drop if no schema manager has been detected
Since his application actually managed to connect to our development environment PostgreSQL database (since it dropped some tables), I start to think he maybe could have forgotten to set hbm2ddl.auto and automatically it went as create-drop.
Is it possible to connect to PostgreSQL and don't have a valid schema manager defined? Which are the most common schema managers?
PS: at this application #DataSource is set this way:
#Bean
public DataSource dataSource() {
Class.forName("org.postgresql.Driver");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(someUrlConnectionStringFromApplicationDotPropertiesFile);
return dataSource;
}
like String someUrlConnectionStringFromApplicationDotPropertiesFile = "jdbc:postgresql://ipAddress:port/dbName?user=user&password=pass". I know spring-data-jpa sets everything with spring jpa properties automatically without this method, this is currently an unchangeable legacy code :(
Spring Boot said they are Higher-level Database Migration Tool (Flyway or Liquibase).
ref: https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-access.jpa-properties, https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-access.jpa-properties
You can also configure them through Spring Boot documentation or their own docs. ref: https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-initialization.migration-tool
For example, configure Flyway community version through maven (https://flywaydb.org/download/community):
<build>
...
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>9.12.0</version>
</plugin>
...
</build>

Having problems understanding Springboot and MongoDB

I'm developing an application with SpringBoot. I already have a RestController and a RabbitMQ component that depending on the message I receive I get some data from a MongoDB and do some logic.
I set up the database as:
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase db = mongoClient.getDatabase("databaseName");
MongoCollection<Document> collection = db.getCollection("collectionName");
Since I'm using SpringBoot I wanted to do it with Springboot and acess it in every SpringBoot component (the RestController and the RabbitMQ component).
I already understood that I have to put the settings on application.properties.
What I don't get is how do I acess the database afterwards.
Am I supposed to do a #Configuration class?
And how can I do, for example, collection.find(eq("id",userID)).first() everywhere?
Use the spring data JPA. You literally don't have to write any code.
Just follow this

Spring cloud config properties not honouring config properties

I wish to use consul strictly as a config source.
I am using spring-cloud-consul-config to get my config.
I am using git2consul to load files into consul and read them.
As per the spring cloud documentation I have added the following to my build.gradle
compile ("org.springframework.cloud:spring-cloud-starter-consul-config")
and have the following in my application.properties
spring.application.name=test-service
spring.cloud.consul.config.enabled=true
spring.cloud.consul.enabled=true
spring.cloud.consul.config.format=FILES
The problem I am facing is that the expected properties are not being loaded into the ConfigurationProperties beans. On further debugging in the ConsulPropertySourceLocator::locate(Environment environment) method, I see that the this.properties object is still loaded with KEY_VALUE enum.
This led me to ConsulConfigBootstrapConfiguration class, where the ConsulConfigProperties bean is being instantiated using a constructor.
Is this the problem or do I have something wrong in my setup.
If someone has a working setup of git2consul and spring cloud config, please can you point me to it for reference.
These values that you have in application.properties
spring.application.name=test-service
spring.cloud.consul.config.enabled=true
spring.cloud.consul.enabled=true
spring.cloud.consul.config.format=FILES
need to be in bootstrap.properties.

Binding to MongoDB service from Grails application deployed on Cloudfoundry

I'm currently writing a Grails app using Grails 2.2.2 and MySQL, and have been deploying it to Cloudfoundry.
Until recently I've just used a single MySQL datasource for my domain, which Cloudfoundry detects and automagically creates and binds a MySQL service instance to.
I now have a requirement to store potentially large files somewhere, so I figured I'd take a look at MongoDB's GridFS. Cloudfoundry supports MongoDB, so I'd assumed Cloudfoundry would do some more magic when I deployed my app and would provide me with a MongoDB datasource as well.
Unfortunately I'm not prompted to create/bind a MongoDB service when I deploy my app, and I think this may be down to the way I'm connecting to Mongo.
I'm not using the MongoDB plugin, as this conflicts with another plugin I'm using, and in any case I don't need to persist any of my domain to Mongo - just some large files - so I'm using the Mongo java driver directly (similar to this - http://jameswilliams.be/blog/entry/171).
I'm unsure how Cloudfoundry detects that your application requires a particular datasource, but I'd assumed it would figure this out somehow from DataSource.groovy.
Mine looks like this...
environments {
development {
dataSource {
driverClassName = "com.mysql.jdbc.Driver"
dbCreate = "create-drop"
...
}
dataSourceMongo {
host = "localhost"
port = 27017
dbName = "my_mongo_database_name"
...
}
}
}
Is there something I'm missing? Or do I need to manually bind the MongoDB service somehow?
Using answer instead of comments for better formatting. :)
I guess you have already followed step to create the MongoDB service in Cloudfoundry as mentioned here otherwise this has to be done. Plus, it will be lot easier if you use the Groovy wrapper of the Java Driver of MongoDB called GMongo. Refer the GitHUb Source and this Mongo blog for more details.