Introduction
In the ecosystem of microservices, establishing a common foundation(template) for all services not only promotes uniformity but also significantly enhances development efficiency and system maintainability. Spring Boot, known for its "convention over configuration" approach, provides an ideal platform for implementing such a foundation through a template configuration. This blog will explore how to create a comprehensive microservice template in Spring Boot, integrating various functionalities that are commonly required across multiple services, such as security, messaging, and monitoring.
A template configuration in Spring Boot serves as a central point to define and manage shared behaviors and service components. This centralized configuration approach ensures that all microservices built on top of it inherit consistent settings and behaviors, which simplifies the development process and reduces the chances of discrepancies in essential service functionalities.
Base Configuration Setup
Let’s create template configuration that includes a variety of shared functionalities beneficial for a microservices architecture:
// BaseConfiguration.java
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.kafka.core.KafkaTemplate;
@Configuration
public class BaseConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "MY_MICROSERVICE");
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(/* KafkaProducerFactory goes here */);
}
}
Description of features
- RestTemplate: Facilitates HTTP communications between microservices or with external APIs.
- MeterRegistryCustomizer: Standardizes application metrics for consistent monitoring.
- KafkaTemplate: Enables asynchronous messaging and event-driven integrations with Kafka.
Base SpringBootApplication class
We import the above BaseConfiguration
in the Application
class which will be the main class for our spring boot applications.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import com.example.springboot.config.BaseConfiguration;
@SpringBootApplication
@Import(BaseConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The above two classes are part of the main-app
module here
Implementing and Extending the Base Configuration
Microservices can utilize this base configuration either directly or with modifications tailored to their specific needs.
Using the Base Configuration Directly
This just requires ensuring that main-app
and spring-boot-base-service
are present as dependencies
spring-boot-default-service
module provides an example of this implementation here
Customizing the Configuration
In this example, we are implementing a service that uses the template but overrides some of the configuration.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ProductConfiguration
{
@Bean
public RestTemplate customRestTemplate() {
System.out.println("custom rest template");
RestTemplate restTemplate = new RestTemplate();
// Additional custom configurations for RestTemplate
restTemplate.getInterceptors().add(new CustomClientHttpRequestInterceptor());
return restTemplate;
}
}
spring-boot-product-service
module implements the same here
All the code for this can be referred from here
You can start the individual services in Intellij using the run configurations that have been checked-in in the github repo
For reference, the configurations look like below. As can be seen all the services have the same spring boot class com.example.springboot.Application