Creating the Cart Service Project
In the Eclipse IDE, go to File -> New -> Spring Starter Project . This will open the Spring Starter Project dialogue box below.
Enter the project metadata details, giving any name to your project that you choose and click on Next.
Choose the dependencies below to be added to your project and click on Next:
- Spring Web
- Eureka Discovery Client
Click on Next and then finish, this will generate the Cart Service project.
Starting with developing the code base for the User Service
Java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication. class , args); } } |
In the above code snippet:
- @SpringBootApplication annotation is used to set up the auto configuration feature of Spring Boot along with invoking the component scanning mechanism for the respective components to be scanned.
- @EnableEurekaClient annotation specifying that this service is a client service that will be registered with the Eureka Server for the service discovery process.
- @EnableFeignClients annotation is used here to have the provision of calling another microservice’s endpoint which is registered with the respective Eureka Server.
Creating the Controller class
Java
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import com.elkstack.feign.Feign; @RestController public class UserController { @Autowired Feign feign; @GetMapping ( "/add/{item_id}" ) public String addUsersItem( @PathVariable ( "item_id" ) String item_id) { feign.addToCart(item_id); return "Item with id: " + item_id + " selected to add in cart" ; } } |
In the above code snippet:
- @RestController annotation to denote that the Java objects returned as the output by the respective endpoints of this class will be automatically serialized and deserialized into JSON format.
- @Autowired annotation here is used to initialize the object of the Feign Interface, for enabling the call to another microservice registered with the Eureka Server.
- The Feign interface is used to make a call to the respective endpoints of the service that would be invoked.
- The endpoint /add/{item_id} will take an item_id as an input in the form of the @PathVariable annotation
- The addToCart() method is the method that belongs to the Cart Service which is responsible for taking the input item_id and then placing an order request for it in the sample user cart.
Creating the Feign Interface
Java
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient (name= "CartService" ) public interface Feign { @GetMapping ( "/addToCart/{item_id}" ) public String addToCart( @PathVariable ( "item_id" ) String item_id); } |
In the above code snippet:
- @FeignClient annotation is used to annotate this Feign interface as the interface that will be used to provide the functionality of calling the Cart Service’s addToCart() method through its endpoint /addToCart/{item_id}
- The Cart Service then takes that input item_id and places that item_id request made by the user in an inventory.
The application.properties file:
spring.application.name=UserService
server.port=8090
eureka.instance.preferIpAddress = true
eureka.client.registerWithEureka = true
eureka.client.fetchRegistry = true
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka
In the above properties file:
- The property eureka.client.serviceUrl.defaultZone property contains the eureka server URL where all the remaining micro services are registered
- The User service is registered with the Eureka Server through the property eureka.client.registerWithEureka property
The pom.xml file for the User Service
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.7.16</ version > < relativePath /> <!-- lookup parent from repository --> </ parent > < groupId >elkstackmumbai</ groupId > < artifactId >UserService</ artifactId > < version >0.0.1-SNAPSHOT</ version > < name >UserService</ name > < description >User Service MicroService</ description > < properties > < java.version >17</ java.version > < spring-cloud.version >2021.0.8</ spring-cloud.version > </ properties > < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-netflix-eureka-client</ artifactId > </ dependency > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-openfeign</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-devtools</ artifactId > < scope >runtime</ scope > < optional >true</ optional > </ 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 > |
The main Maven dependencies to be added are:
- Spring Web
- Spring Netflix Eureka Client
- OpenFeign
Now, Creating the Cart Service
Java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class CartServiceApplication { public static void main(String[] args) { SpringApplication.run(CartServiceApplication. class , args); } } |
In the above code snippet:
- @SpringBootApplication annotation is used to set up the auto configuration feature of Spring Boot along with invoking the component scanning mechanism for the respective components to be scanned.
- @EnableEurekaClient annotation specifying that this service is a client service that will be registered with the Eureka Server for the service discovery process.
Creating the Controller Class
Java
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class CartServiceController { @GetMapping ( "/addToCart/{item_id}" ) public String addToCart( @PathVariable ( "item_id" ) String item_id) { return "Item with id : " + item_id+ "added to cart" ; } } |
In the above code snippet:
- @RestController annotation to denote that the Java objects returned as the output by the respective endpoints of this class will be automatically serialized and deserialized into JSON format.
- The endpoint /addToCart/{item_id} takes the item_id received as an input in the form of the @PathVariable annotation from the User Service via the OpenFeign mechanism.
- addToCart() method simply takes that input item_id and returns it back as an output after which it displays the message of that respective item_id being successfully added to the cart.
The application.properties file for the Cart Service:
server.port=8095
spring.application.name=CartService
eureka.instance.preferIpAddress = true
eureka.client.registerWithEureka = true
eureka.client.fetchRegistry = true
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka
In the above properties file:
- The property eureka.client.serviceUrl.defaultZone property contains the eureka server URL where all the remaining micro services are registered.
- The User service is registered with the Eureka Server through the eureka.client.registerWithEureka property.
The pom.xml file for the Cart Service
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.7.16</ version > < relativePath /> <!-- lookup parent from repository --> </ parent > < groupId >elkstackmumbai</ groupId > < artifactId >cartservice</ artifactId > < version >0.0.1-SNAPSHOT</ version > < name >CartService</ name > < description >Cart Service App</ description > < properties > < java.version >17</ java.version > < spring-cloud.version >2021.0.8</ spring-cloud.version > </ properties > < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-netflix-eureka-client</ 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-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 > |
The main Maven dependencies to be added into the pom.xml file:
- Spring Web
- Spring Netflix Eureka Client
Now Creating the Eureka Server
Java
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication. class , args); } } |
In the above code snippet:
- @SpringBootApplication annotation is used to set up the auto configuration feature of Spring Boot along with invoking the component scanning mechanism for the respective components to be scanned.
- @EnableEurekaServer annotation specifying that this service is the Eureka server into which all the other microservices will be registered for the process of service discovery acting as the central registry
The application.properties file for the Eureka Server:
spring.application.name=Eureka
server.port=8761
eureka.instance.hostname=localhost
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
In the application.properties file:
- The property eureka.client.serviceUrl.defaultZone property contains the value of the Eureka Server URL along with the port number onto which this Eureka Server has been setup.
- The remaining services get registered with this Eureka Server and this service now becomes the central point of registry for all the other microservices.
The pom.xml file for the Eureka Server:
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.7.16</ version > < relativePath /> <!-- lookup parent from repository --> </ parent > < groupId >elkstackmumbai</ groupId > < artifactId >EurekaService</ artifactId > < version >0.0.1-SNAPSHOT</ version > < name >Eureka</ name > < description >Eureka Central Registry Service</ description > < properties > < java.version >17</ java.version > < spring-cloud.version >2021.0.8</ spring-cloud.version > </ properties > < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-netflix-eureka-server</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-devtools</ artifactId > < scope >runtime</ scope > < optional >true</ optional > </ 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 > |
The main Maven dependency to be added in the pom.xml file is:
- Spring Netflix Eureka Server
After we have created these Spring Boot projects, we can now hit the endpoint: http://localhost:8090/add/2 through Postman:
As seen in the above image, the item_id: 2 is provided as the input to the given endpoint. The respective User Service then calls the Cart Service which adds the requested item_id: 2 in the cart.
Viewing Registered Services through the Central Registry Eureka Server
Hit the endpoint: http://localhost:8761/
This will open the Eureka server dashboard below:
Below we can see the Services registered with the Eureka Server:
As seen from the above image, the 2 services that are User Service, Cart Service that are registered with the Eureka Server are displayed along with their port numbers on which they are currently up and running. The Cart Service is running on port number: 8095. While, the User Service is running on port number: 8090.
In this way, we can accurately identify which of the services have not yet been registered with the Eureka server due to any failures that may prevent the given services from being up and running at the application start up time.
Implementation of Spring Cloud Netflix – Eureka
In this article, we will learn about server-side and client-side service discovery in Spring Cloud Netflix Eureka. By using the central registry service, we can discover all of the microservices that are catering to our web application along with the respective port numbers they have occupied on startup. This central registry service is what is termed as Spring Cloud Netflix Eureka Server. This Eureka server fulfills the sole purpose of service discovery. Each of the microservices that register themselves with the Eureka server sends their respective status updates at regular intervals of time to the Eureka server.
In this way, the Eureka server is continuously updated about the status of each service (whether the service is up and running). It also keeps track of the number of requests being handled by each instance of those respective services, which plays an important role in the load-balancing aspect of microservices.