Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, March 30, 2021

Create Spring Boot Application With Centralized Configuration

Create Spring Boot Application With Centralized Configuration

We will see how to create a spring boot application with centralized configuration.

Pre-requisites for below tutorial:

  • JDK 1.8 or later
  • Maven
  • Git

This requires two applications:

  1. a configuration service application (config-server)
  2. a configuration client application (config-client)
1. Create a configuration service application - Config Server

For the service application, visit the Spring Initializr to generate a new project with the required dependency (Config Server).

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.4</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn</groupId>
	<artifactId>config-server</artifactId>
	<name>config-server</name>
	<description>Configuration Server</description>

	<properties>
		<java.version>8</java.version>
		<spring-cloud.version>2020.0.2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>



You first need a Config Server to act as a sort of intermediary between your Spring applications and a version-controlled repository of configuration files. You can use Spring Cloud’s @EnableConfigServer to standup a config server that can communicate with other applications. This is a regular Spring Boot application with one annotation added to enable the config server.
ConfigServerApplication.java
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}

}
  
  



The Config Server needs to know which repository to manage. There are several choices here, but start with a Git-based file system repository. You could as easily point the Config Server to a Github or GitLab repository.

On the file system, create a new directory and run git init in it. Then add below files in the directory. 

  • config-client.properties
  • config-client-staging.properties
  • config-client-production.properties
Then run git commit in it.

Later, you will connect to the Config Server with a Spring Boot application whose spring.application.name property identifies it as config-client to the Config Server. This is how the Config Server knows which set of configuration to send to a specific client. It also sends all the values from any file named application.properties or application.yml in the Git repository. Property keys in more specifically named files (such as config-client.properties) override those in application.properties or application.yml.

Add a simple property and value with different message related to specific environment (eg.welcome.message = Welcome to config client) to the newly created config-client-<label>.properties files and then  commit the changes using git commit .

config-client.properties

    server.port=8080
    
config-client-staging.properties

    welcome.message=Welcome To Config Client Application - staging
    
config-client-production.properties

    welcome.message=Welcome To Config Client Application - production

Specify the path to the Git repository by specifying the spring.cloud.config.server.git.uri property in configuration-service/src/main/resources/application.properties. You must also specify a different server.port value to avoid port conflicts when you run both this server and another Spring Boot application on the same machine. The following listing (from configuration-service/src/main/resources/application.properties) shows such an application.properties file:


server.port=8888
spring.cloud.config.server.git.uri=${HOME}/Desktop/config-files

2. Create a configuration client application - Config Client
Now we need to create a client application which loads property files from config server. We need to add the org.springframework.cloud:spring-cloud-starter-config  dependency, to connect to the Config Server.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.4</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn</groupId>
	<artifactId>config-client</artifactId>
	<name>config-client</name>
	<description>Configuration Client</description>
	
	<properties>
		<java.version>8</java.version>
		<spring-cloud.version>2020.0.2</spring-cloud.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>


Specify the client’s  spring.application.nameas  config-clientand the location of the Config Server spring.config.importin config-client/src/main/resources/application.properties.
config-client/src/main/resources/application.properties
spring.application.name=config-client
spring.config.import=optional:configserver:http://localhost:8888/
management.endpoints.web.exposure.include=*

The client can access any value in the Config Server by using the traditional mechanisms (such as @ConfigurationProperties or @Value("${…​}") or through the Environment abstraction).

Create a rest controller that returns the resolved message property’s value.

ConfigClientApplication.java

package info.code2learn.configclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;

@RefreshScope
@SpringBootApplication
public class ConfigClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}

}

ConfigClientController.java

package info.code2learn.configclient.controller;

import org.springframework.beans.factory.annotatioTest the Applicationn.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConfigClientController {
	
	@Value("${welcome.message}")
	private String message;
	
	@RequestMapping("/message")
	public ResponseEntity<String> message(String name) {
		return new ResponseEntity<String>(message, HttpStatus.OK);
	}
	
}

Test the application

Start the Config Server first and then, once it is running, start the client using profile 'staging' or 'production' (eg. mvn spring-boot:run -Dspring-boot.run.profiles=staging). Open the client app in the browser using url http://localhost:8080/message . There, you should see Welcome message in the response specific to the profile.






You can also see the configuration details for a particular client application using  http://localhost:8888/config-client/staging


Click here for github link

Spring Boot HTTPS Rest Call with Rest Template

We will see how to call an application which is HTTPS enabled using Spring Boot RestTemplate in a client application. Prerequisites:  1) M...