Spring-Cloud config with MongoDB
Spring Cloud config has brought the externalisation of configuration to a new level. With a lot of distributed systems and micro-services being hosted , it makes sense for a dedicated configuration server for different environments.
If we see the 12-Factor app recommendation, it also recommends to keep application configuration completely separate from the application. It also suggests that application environments can not just be limited to dev.qa or prod. We need to scale it to multiple levels.
Also, now we have just a single place to manage all the configrations for all the environments.
The default implementation uses GIT as a source for configuration repository. Iam not really a keen fan of putting critical configuration in GIT and besides this we need to maintain another data-source now(GIT).
I normally prefer to choose MongoDB to keep all the application configuration and decided to stick to that for Spring-cloud configuration too.
So, in this article we are going to see how can we use MongoDB as configuration repository.
Firstly, we will establish a configuration server-
You need to create a Spring-Boot application.
Following is the maven pom.xml-
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version>
<relativePath />
</parent><dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId
<artifactId>spring-cloud-config-server</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server-mongodb</artifactId>
<version>0.0.3.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>
Following is the main Application class-
@SpringBootApplication
@EnableMongoConfigServer
public class AppConfigApplication
{
public static void main(String[] args) {
SpringApplication.run(AppConfigApplication.class, args);
}
}
In application.properties-
Make the following entries-server.port=8100
spring.data.mongodb.uri: mongodb://localhost:27017/appconfigdata
Now comes the MongoDB entries for any application properties-
In a small use-case where I want to make entries for cassandra as a data-source.
Make a collection with name app_search and make the following entry-
{
“label” : “config”,
“profile” : “dev”,
“source” : {
“spring” :
{
"data" :
{
"cassandra" :
{
"keyspace-name" : "appkeyspace",
"contact-points" : "localhost",
"port" : "9042",
"schema-action" : "CREATE_IF_NOT_EXISTS"
}
}
}
}
}
In a nutshell all “.” are converted into nested JSON objects in MongoDB.
Here
label — Any version you want to keep for the properties
profile — Application environment dev/qa/prod
So, there lies the benefit of having a single configuration server catering to all the environments and a single place to manage all the configurations-
Refer to the URL-
http://localhost:8100/app_search/dev/config
You should be able to see all the configurations now-
Client Application configuration
Now, we are going to look at client-side configuration. This application is going to consume the configuration which we have set in the Spring-Cloud config server application.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId
<version>2.1.4.RELEASE</version>
<relativePath /> <! — lookup parent from repository →
</parent><properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties><dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies><dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId
<artifactId>spring-cloud-dependencies</artifactId
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Now, we will config-server location url in application configuration.
Put up a file with name bootstrap.properties in classpath /src/main/resources
spring.application.name=app_search
spring.cloud.config.uri=http://localhost:8100
spring.cloud.config.label=config
server.port=8102
Here, is the mapping of bootstrap.properties with respect to server configuration-
spring.application.name - <<maps to name of the mongo collection containg nconfig>>
label - <<Maps to the label key in configuration>>
profile - <<Maps to profile key declared in collection>>
The application configuration can be located with a combination of label and environment.
So, you can keep multiple labels for the same environment and hence multiple configurations for same environment.
Once you start your server you should get following entry in logs-
2019-06-23 15:13:56.492 INFO 5636 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8100
2019-06-23 15:13:56.867 INFO 5636 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=app_search, profiles=[dev], label=config, version=null, state=null
2019-06-23 15:13:56.867 INFO 5636 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='app_search-dev-config'}]}
2019-06-23 15:13:56.953 INFO 5636 --- [ main] c.g.app.AppSearchApplication : The following profiles are active: dev
This indicates that you application successfully integrated with Spring cloud config server.