Monday, June 7, 2021

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) Maven 
2) Java 1.8+ 

We need a sample HTTPS server application which we need to call from a client application. 

1) Create a 'Sample Server' Spring Boot application

Use https://start.spring.io/ to create a sample server application.




  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.6</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn.springboot</groupId>
	<artifactId>sample-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Sample Server</name>
	<description>Spring boot sample server application</description>
	<properties>
		<java.version>11</java.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-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>



SampleServerApplication.java
  
  package info.code2learn.springboot.sampleserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleServerApplication {

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

}

  
  
  SampleServerController.java
  
  package info.code2learn.springboot.sampleserver.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sampleserver")
public class SampleServerController {

    @GetMapping("/message")
    public ResponseEntity<String> message() {
        return new ResponseEntity<>("Message from https server.", HttpStatus.OK);
    }
}

  
  
Generate Key Store of type PKCS12 using below command. This is required for making the application as HTTPS/SSL enabled.
  
  $ keytool -genkey -alias sampleserver -keyalg RSA -keystore sampleserver.keystore -validity 3650 -storetype PKCS12 -dname "CN=localhost, OU=Spring, O=Pivotal, L=Holualoa, ST=HI, C=US" -keypass changeit -storepass changeit
  
  
  application.yml
  
  server:
  port: 8443
  ssl:
    enabled: true
    key-alias: sampleserver
    key-password: changeit
    key-store: classpath:sampleserver.keystore
    key-store-password: changeit
    key-store-type: PKCS12
  
  
2) Create a 'Sample Client' Spring Boot application

Use https://start.spring.io/ to create a sample client application.





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.6</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn.springboot</groupId>
	<artifactId>sample-client</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Sample Client</name>
	<description>Spring boot sample client application</description>

	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<url>http://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<url>http://repo.spring.io/milestone</url>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<url>http://repo.spring.io/snapshot</url>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<url>http://repo.spring.io/milestone</url>
		</pluginRepository>
	</pluginRepositories>

	<properties>
		<java.version>11</java.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-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>


		<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpcore</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>


SampleClientApplication.java

package info.code2learn.springboot.sampleclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleClientApplication {

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

}


SampleClientConfig.java

package info.code2learn.springboot.sampleclient.config;

import java.io.InputStream;
import java.security.KeyStore;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class SampleClientConfig {
	
	@Value("${app.key-store-type}")
	private String keyStoreType;
	
	@Value("${app.key-store-password}")
	private String keyStorePassword;
	
	@Value("${app.key-store}")
	private String keyStoreFile;

	@Bean
	public RestTemplate restTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		
		KeyStore keyStore;
		HttpComponentsClientHttpRequestFactory requestFactory = null;
		
		try {
			keyStore = KeyStore.getInstance(keyStoreType);
			ClassPathResource classPathResource = new ClassPathResource(keyStoreFile);
			InputStream inputStream = classPathResource.getInputStream();
			keyStore.load(inputStream, keyStorePassword.toCharArray());

			SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(new SSLContextBuilder()
					.loadTrustMaterial(null, new TrustSelfSignedStrategy())
					.loadKeyMaterial(keyStore, keyStorePassword.toCharArray()).build(),
					NoopHostnameVerifier.INSTANCE);

			HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
					.setMaxConnTotal(Integer.valueOf(5))
					.setMaxConnPerRoute(Integer.valueOf(5))
					.build();

			requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
			requestFactory.setReadTimeout(Integer.valueOf(10000));
			requestFactory.setConnectTimeout(Integer.valueOf(10000));
			
			restTemplate.setRequestFactory(requestFactory);
		} catch (Exception exception) {
			System.out.println("Exception Occured while creating restTemplate "+exception);
			exception.printStackTrace();
		}
		return restTemplate;
	}
}

SampleClientController.java

package info.code2learn.springboot.sampleclient.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/sampleclient")
public class SampleClientController {
	
	@Autowired
	private RestTemplate restTemplate;
	
	@Value("${sampleserver.url}")
	private String sampleServerUrl;

	@GetMapping("/welcome")
	public ResponseEntity<String> welcome() {
		ResponseEntity<String> responseEntity = restTemplate.getForEntity(sampleServerUrl + "/sampleserver/message", String.class);
		return new ResponseEntity<>(responseEntity.getBody(), HttpStatus.OK);
	}
	
}


application.yml

server:
  port: 9090
  
sampleserver:
  url: https://localhost:8443/

app:
  key-alias: sampleserver
  key-password: changeit
  key-store: sampleclient.truststore
  key-store-password: changeit
  key-store-type: JKS 

Run Sample Server application and Import Server application certificate into client application truststore

Click certificate icon next to the sample server application URL on browser.



Click Details



Select DER format and save as sampleserver.cer and save it in client application resources folder.


Run the below command to import above exported sample server certificate into sample client application trust store.

$ keytool -importcert -keystore sampleclient.truststore -alias sampleserver -storepass changeit -file sampleserver.cer -noprompt


Start the Sample Client application and access the endpoint at http://localhost:9090/sampleclient/welcome






Sunday, May 16, 2021

Kafka Producer and Consumer Example using Spring Boot

Kafka Producer and Consumer Example using Spring Boot

In this post, we will see how to create a Kafka Producer application which publishes messages to a kafka topic and a Kafka Consumer application which subscribes and consumes messages from the kafka topic.

Pre-requisites for below tutorial:

  • JDK 1.8 or later
  • Maven
  • Git

This example requires below two applications.
  1. Kafka Producer
  2. Kafka Consumer

1. Create Kafka Producer application

Visit the Spring Initializr to generate new project with required dependencies.

Below kafka producer application produces a message to kafka topic every 1 sec.

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.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn</groupId>
	<artifactId>kafka-producer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>kafka-producer</name>
	<description>Kafka Producer Example</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</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.kafka</groupId>
			<artifactId>spring-kafka-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

</project>



KafkaProducerApplication.java

package info.code2learn.kafkaproducer;

import org.apache.kafka.clients.admin.NewTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.config.TopicBuilder;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@SpringBootApplication
@EnableScheduling
public class KafkaProducerApplication {
	
	private static final Logger log = LoggerFactory.getLogger(KafkaProducerApplication.class);
	private static final String TOPIC = "topic1";
	
	private Integer counter = 0;
	
	@Autowired
	KafkaTemplate<String, String> kafkaTemplate;

	public static void main(String[] args) {
		SpringApplication.run(KafkaProducerApplication.class, args);
	}
	
	@Bean
    public NewTopic topic() {
        return TopicBuilder.name(TOPIC)
                .partitions(10)
                .replicas(1)
                .build();
    }
	
	@Scheduled(fixedDelay = 1000)
	public void produce() {
		String message = "Hello " + counter++;
		log.info("Sending message to topic : {}, message: {}", TOPIC, message);
		kafkaTemplate.send(TOPIC, String.valueOf(message.hashCode()), message);
	}

}




application.yml

server:
  port: 8081
  
spring:
  kafka:
    producer:
      acks: 1
      bootstrap-servers:
      - localhost:9092
      client-id: kafka-producer
      key-serializer:
        org.apache.kafka.common.serialization.StringSerializer
      value-serializer:
        org.apache.kafka.common.serialization.StringSerializer




2. Create Kafka Consumer application

Visit the Spring Initializr to generate new project with required dependencies.
This application consumes the messages from the kafka topic.


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.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>info.code2learn</groupId>
	<artifactId>kafka-consumer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>kafka-consumer</name>
	<description>Kafka Consumer Example</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</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.kafka</groupId>
			<artifactId>spring-kafka-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

</project> 

KafkaConsumerApplication.java

package info.code2learn.kafkaconsumer;

import org.apache.kafka.clients.admin.NewTopic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.config.TopicBuilder;

@SpringBootApplication
@EnableKafka
public class KafkaConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(KafkaConsumerApplication.class, args);
	}
	
	@Bean
    public NewTopic topic() {
        return TopicBuilder.name("topic1")
                .partitions(10)
                .replicas(1)
                .build();
    }
	
	@KafkaListener(id = "kafkaConsumer", topics = { "topic1" })
	public void listen(String message) {
		System.out.println(message);
	}
	
}   
application.yml
    
server:
  port: 8082

spring:
  kafka:
    consumer:
      group-id: kafka-consumer-group
      bootstrap-servers:
      - localhost:9092
      client-id: kafka-consumer
      key-deserializer:
        org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer:
        org.apache.kafka.common.serialization.StringDeserializer
    
    
Start both producer and consumer applications.

Output:



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...