• Skip to main content
  • Skip to secondary menu
  • Skip to primary sidebar
  • Skip to footer
  • Home
  • Contact Us

All about code

  • Java
    • Spring
      • Spring Boot
      • Spring Cloud
    • Java Miscellaneous Tips
    • Java Design Patterns
  • Data Structures and Algorithms
    • Algorithms
    • Data Structures
  • Thoughts and Stories
  • AI

Spring Cloud: How to Deal with Microservice Configuration (Part I)

coding programming css 1853305

Introduction

Configuring a software system in a monolithic approach does not pose particular problems. To make the configuration properties available to the system, we can store them in a file inside an application folder, in some place in the filesystem, or as OS environment variables. Microservice Configuration is a more complex subject. We have to deal with a number, which can be huge, of totally independent services, each with its own configuration. We could even face a scenario in which several instances of the same service need different configuration values.

In such a situation, a way to centralize and simplify configuration management would be of great importance. Spring Cloud has its own module to solve these problems, named Spring Cloud Config. This module provides an implementation of a server that exposes an API to retrieve the configuration information, usually stored in some remote repository like Git, and at the same time, it gives us the means to implement the client side meant to consume the services of that API.

In the first part of this article, we will discuss the basic features of this Spring Cloud module, storing the configuration in the configuration server classpath, and in the next part, we will show how to use other, more effective, repository options, like Git, and also how to refresh the configuration without restarting the services. Then, in later posts, we will show how the centralized configuration can be coupled with service discovery features to set a solid base for the whole microservice system.

Microservice Configuration: Spring Cloud Config Server Side

The first component we need in a distributed configuration scenario is a server meant to provide the configuration information for the services. To implement such a server component by Spring Cloud Config we have to use the right Spring Boot “starter” dependency, like in the following configuration fragment:

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

Then we have to annotate the Spring Boot main class with the @EnableConfigServer annotation:

@SpringBootApplication
@EnableConfigServer
public class AppMain {

	public static void main(String[] args) {
		new SpringApplicationBuilder(Config.class).run(args);
	}
}

The Spring Cloud Config server, according to the auto-configuration features of Spring Boot, would run on the default 8080 port, as all Spring Boot applications. If we want to customize it, we can do it by the application.properties or application.yaml file:

server:  
  port: ${PORT:8888}
    
spring:
  application:
    name: config-server

If we run the application with the above configuration, it will use the 8888 port as the default. We can override the default by launching the application with a different port, by the PORT placeholder:

java -jar -DPORT=8889 sample-server-1.0-SNAPSHOT.jar 

In any case, if we launch the application with the spring.config.name=configserver argument instead, the default port will be 8888. This is due to a configserver.yml default file embedded in the spring-cloud-config-server library. As a matter of fact, it would be very convenient to launch the server config application on the 8888 port, either by explicitly configuring it on the server.port parameter, like in the example above, or passing spring.config.name=configserver in the startup Java command, because 8888 happens to be the default port used by the client side.

Important note: the spring.config.name=configserver option only works if passed in the startup command, and seems to be ignored for some reason if set in the configuration file. We can see below an example of how to start the config server with a Java command:

java -jar -Dspring.config.name=configserver spring-cloud-config-native-server-1.0-SNAPSHOT.jar

By default, the Spring Cloud Config server uses Git as a remote repository to store the configuration data. In this article, to simplify the discussion, we will focus on a more basic approach based on files stored on the application classpath. We will describe this option in the next section. It must be stressed that in a real scenario, this would be far from ideal, and Git would surely be a better choice.

Enforcing Basic Authentication on the Server Side

We can provide the server with a basic security layer, in the form of an authentication mechanism based on user and password. To do that, we must first add the following security starter to the POM:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

And then add the following piece of configuration in the application.yml file:

  security:
    user:
      name: myusername
      password: mypassword

With the above, the client side should be configured accordingly to be able to connect to the server, as we will see in the section related to the client side. We will discuss more advanced security mechanisms in later articles.

Spring Cloud Config Backend Storing Options

The Spring Cloud Config server can store the configuration data in several ways:

  • By a remote Git system. This is the default.
  • Other Version Control Systems (VCS) like SVN.
  • VAULT: It is a tool by HashiCorp that specializes in storing passwords, certificates, or other entities as secrets.
  • By storing it in some place in the filesystem or in the classpath.

In this article, we will describe the filesystem/classpath option. Spring Cloud Config has a profile named native that covers this scenario. In order to run the config server with a filesystem/classpath backend storage, we have to start it with the spring.profiles.active=native option.

In the native scenario, the config server will search by default in the following places:

  • classpath:/
  • classpath:/config
  • file:./
  • file:./ config

So, we can simply store the configuration files inside the application jar file. If we want to use an external filesystem directory instead of or customize the above classpath options, we can set the spring.cloud.config.server.native.searchLocations property accordingly.

Config Server API

The Config Server can expose the configuration properties of a specific application by an HTTP API with the following endpoints:

  • /{ application}/{ profile}[/{ label}]: this returns the configuration data as JSON, with the specific application, profile, and an optional label parameter.
  • /{ label}/{ application}-{ profile}.yml: This returns the configuration data in YAML format, with the specific application, profile, and an optional label parameter.
  • /{ label}/{ application}-{ profile}. Properties: this returns the configuration data as raw text, with the specific application, profile, and an optional label parameter.

The application part represents the name of the application, configured by the spring.application.name property and the profile part represent the active profile. A profile is a feature to segregate a set of configurations related to specific environments, such as development, test, and production. The label part is optional and is used when using Git as a backend repository to identify a specific branch.

Microservice Configuration: Spring Cloud Config Client Side

If we want our services to obtain their own configuration from the server, we must provide them with a dependency named spring-cloud-starter-config:

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>

Clearly, the configuration must be obtained as the first step during its startup. To deal with this requirement, Spring Cloud introduces a bootstrap context. The bootstrap context can be seen as the parent of the application context. It serves the purpose of loading configuration data retrieved from some external source and making it available to the application context.

In earlier versions of Spring Cloud, we could provide the configuration properties for the bootstrap context by a bootstrap.yml file. This is deprecated in the new versions. Now, we have to simply provide a config.import property=optional:configserver: property in the standard application.yml:

  config:
    import: "optional:configserver:"

With the “optional:configserver:” value, the config client service will use the default http://localhost:8888 address to contact the config server. If we exclude the optional part, an error will be raised during startup if the server is unreachable.

If we want to set a specific address and port, we can add the address part to the value, like this:

  config:
    import: "optional:configserver:http://myhost:myport"

Configuring Security on the Client Side

If we have secured the server with basic authentication, we must provide the necessary configuration to the client. Adding the following piece of configuration to the application.yml will be enough:

  security:
    user:
      name: myusername
      password: mypassword

Putting the Pieces Together in a Simple Demo

Using the notions described above, we can realize a simple demo with a configuration server and a single client service, as in the picture below:

A simple configuration with a Configuration Server in native mode and a single Client Service
Config Server and Client Service

Server Side Implementation

To implement the server side, we create a Spring Boot application with the required Spring Cloud release train and Spring Cloud Config starter:

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>2021.0.5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>
	</dependencies>

Then we write the application.yml file, setting the port to the conventional 8888 value, the active profile as native, and finally the application name:

server:  
  port: ${PORT:8888}
  
spring:
  profiles:
     active: native
  application:
    name: config-server

Since we have set the spring.profiles.active equal to the native value, this config server application storage will be based on filesystem/classpath. In our example, we choose to store the configuration file of the client service in the classpath, in a config subdirectory of the /resources folder. We name the client service application file as client-service.yml, and we fill it with the following content:

server:  
  port: ${PORT:8081}

myproperty: value  

myproperties:
   properties:
      - value1
      - value2

The myproperty and myproperties parts will be used to test this minimal demo: we will expose them by some REST service on the client, and if all works as expected, the above values will be returned.

Client Side Implementation

We configure the client application with the same release train as the server. As dependencies, with have a spring-cloud-starter-config starter, and also a spring-boot-starter-web, because we want our application to expose some HTTP REST services:

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>2021.0.5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

The application.yml properties will be consumed by a specific component class by the @Value and @ConfigurationProperties annotations:

@Component
@ConfigurationProperties(prefix = "myproperties")
public class DemoClient {
	private List<String> properties = new ArrayList<String>();

	public List<String> getProperties() {
		return properties;
	}

	@Value("${myproperty}")
	private String myproperty;

	public String getMyproperty() {
		return myproperty;
	}
}

Then, a controller class will implement two REST services, /getProperties and /getProperty, returning the above class properties:

@RestController
public class ConfigClientController {
	private static final Logger LOG = LoggerFactory.getLogger(ConfigClientController.class);
	
	@Autowired
	private DemoClient demoClient;
	
	@GetMapping("/getProperties")
	public List<String> getProperties() {
		LOG.info("Properties: " + demoClient.getProperties().toString());
		return demoClient.getProperties();
	}
	
	@GetMapping("/getProperty")
	public String getProperty() {
		LOG.info("Property: " + demoClient.getMyproperty().toString());
		return demoClient.getMyproperty();
	}
}

Compiling and running the Config Server and the Client Service

After compiling the two applications by Maven, we can take the resulting jars and run first the server part and then the client from the command line:

java -jar spring-cloud-config-native-server-1.0-SNAPSHOT.jar
...
java -jar spring-cloud-config-native-client-1.0-SNAPSHOT.jar

We can test the correct behavior by executing a call with the following address in the browser:

http://localhost:8081/getProperties

If all works as expected, we will have the following values printed on the screen:

[
"value1",
"value2"
]

The Maven projects related to the demo described above are available on GitHub at the following addresses:

  • Client Service
  • Config Server

Conclusion

In this article, we have covered the basic notions required to configure a microservice system based on remote configuration. We have used the native approach, using the classpath as a storage repository. In the next part, we will show how to use a remote Git repository, and also how to refresh the configuration at runtime without restarting the services.

Primary Sidebar

Social

  • Facebook
  • LinkedIn
  • Twitter

Archives

  • May 2026
  • April 2026
  • March 2026
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • September 2023
  • May 2023
  • March 2023
  • January 2023
  • November 2022
  • September 2022
  • August 2022

Recent Posts

  • Better Avoid Spring Boot Lazy-initialization @PostConstruct Trap
  • How To Handle Large Datasets in Spring Boot
  • How to Log HTTP Incoming Requests in Spring Boot
  • How to Reliably Implement Post-Commit Actions in Spring
  • Brief and Easy Explanation of HATEOAS

TAGS

Algorithms Apache POI Backtracking Date Structures Dynamic Programming engineering Graphs Greedy Horror Stories HSSF Java Java New Features Java Principles Java tips real life Sorting Spring Boot Spring Cloud Strings Trees

Footer

Privacy Policy Cookie Policy Terms and Conditions