			 	                "Welcome To Ashok IT"				
			                    "Spring Boot and MicroServices"
                                             Topic : MicroServices Communication
                                             Date  : 02/07/2025
                                                (Session - 79)                               
_____________________________________________________________________________________________________________________________ 
Service Discovery
=================
* Typically in microservice development we do have multiple microservices as programmer it is very hard to remember everything about      Microservice.
    
* To overcome the problem the service registry will maintain all microservices related information i.e.,API URL's,How many Instances are           running for that service,Information about Service,Service is up or down and also used for communicating from  one microservice to another        Microservices using Service Names instead of Hard coded URL's.

* Spring cloud provides the multiple Service discovery API's such as Eureka,ZooKeeper,Consul,Cloud foundry etc.,

* As part of this ServiceDiscovery we will creating three spring boot applications

    1) Service Registry Application : To Track all the Microservices in our project i.e.,Eureka Server Application

    2) Customer-Service : This Application need to be registered as one of Eureka Client

    3) Address-Service  : This Application need to be registered as one of Eureka Client.

Developing the Service Registry Application(40_MicroServices_ServiceDiscovery_App)
==================================================================================
1) Create the Spring Boot Application with Below straters

     * Spring Web 

     * Eureka Server

2) Add the following annotation i.e.,@EnableEurekaServer top of main class 

Application.java
================
package com.ashokit;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

//Activates the Eureka Server and its configuration
@EnableEurekaServer 
@SpringBootApplication
public class Application {

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

3) Add the eureka server configuration entries in application.yml/application.properties

application.properties
======================
#Default Port number for Eureka Server
server.port=8761

#Disabling the Registration of this project with Eureka Server
eureka.client.register-with-eureka=false

#Disabling the Discovery operation of this project with Eureka Server
eureka.client.fetch-registry=false

NOTE: 
=====
**** By Default Eureka Server always run on port number is 8761

4) Run the Spring Boot Applcation and open your browser and hit below URL
 
    http://localhost:8761  >>>>>>>>>>>>>>> We can see the Eureka Server Dashboard Screen

Changes Required for Eureka Client for Customer-MicroService Application(38_Microservices_Customer)
====================================================================================================
1) Add the New Starter for existing starters i..e., Eureka Client.

2) Add the following annotation on top of main class for this Application i.e.,@EnableDiscoveryClient

3) Add the following changes in CustomerServiceImpl.java 
 
CustomerServiceImpl.java
========================
package com.ashokit.service;

import java.util.List;
import java.util.Optional;

import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;

import com.ashokit.dao.CustomerRespoistory;
import com.ashokit.entity.Customer;
import com.ashokit.feign.clients.AddressClient;
import com.ashokit.requests.CustomerRequest;
import com.ashokit.responses.AddressResponse;
import com.ashokit.responses.CustomerResponse;

@Service
public class CustomerServiceImpl implements CustomerService {
	
	@Autowired
	private CustomerRespoistory customerRespoistory;
	
	@Autowired
	private ModelMapper modelMapper;
	
	@Autowired
	private RestTemplate restTemplate;
	
	@Autowired
	private WebClient webClient;
	
	@Value("${services.address-service-url}")
	private String addressServiceURL;
	
	@Autowired
	private AddressClient addressClient;
	
	@Autowired
	private DiscoveryClient discoveryClient;
	
	@Override
	public CustomerResponse createCustomer(CustomerRequest customerRequest) {
		
		//converting the Request object into entity object
		Customer customerObj = modelMapper.map(customerRequest, Customer.class);
		//saving the entity object
		Customer savedCustomerInfo = customerRespoistory.save(customerObj);
		//converting the entity object into response object
		CustomerResponse custResponse = modelMapper.map(savedCustomerInfo, CustomerResponse.class);
		
		return custResponse;
	}
	
	@Override
	public CustomerResponse getCustomerDetailsById(int customerId) {
		System.out.println("Base URL Of Address:::::" + addressServiceURL);
	      
		Optional<Customer> custDetails = customerRespoistory.findById(customerId);
		if(custDetails.isPresent()) {
			Customer customerDetails = custDetails.get();
			CustomerResponse customerResponse = modelMapper.map(customerDetails, CustomerResponse.class);
			
			//setting the address Details by calling RestTemplate or WebClient
			AddressResponse addressResponse = callAddressServiceByUsingDiscoveryClient(customerId);
		  	customerResponse.setAddressDetails(addressResponse);
			return customerResponse;

		}else {
			return null;
		}
	}
	
	private AddressResponse callAddressServiceByUsingDiscoveryClient(int customerId) {
		List<ServiceInstance> allInstances = discoveryClient.getInstances("ADDRESS-SERVICE");
		ServiceInstance currentInstance = allInstances.get(0);
		String apiUrl = currentInstance.getUri()+"/api/address/customer/{customerId}";
		
		ResponseEntity<AddressResponse> addressEntity = 
				   restTemplate.exchange(apiUrl, 
						         HttpMethod.GET,null,
						         AddressResponse.class,
						         customerId);   
		   //checking the API Status is 200 or not
		  if (addressEntity.getStatusCode() == HttpStatus.OK) {
			   //API having Response body or not
			 	if (addressEntity.hasBody()) {
			 		return addressEntity.getBody();
				}
		  }
		 return null;
	}
	
	
	private AddressResponse callAddressServiceByUsingFeignClient(int customerId) {
		 ResponseEntity<AddressResponse> addressResponse = addressClient.getAddressByCustomerId(customerId);
		 return addressResponse.getBody();
	}
}

NOTE
====
 * If our Eureka Server is running on 8761 by default means this Eureka Client applicaton gets registered automatically with     Eureka    server

Changes Required for Eureka Client for Address-Service Application(39_Microservices_Addresses)
==============================================================================================
1) Add the New Starter for existing starters i..e.,Eureka Client.

2) Add the following annotation on top of main class for this Application i.e.,@EnableEurekaClient.

NOTE
====
 * If our Eureka Server is running on 8761 by default means this Eureka Client applicaton gets registered automatically with  
   Eureka server

Running Application
===================
 * We need to run all the three applications and following applications are registered with Eureka Server Automatically and we can       see that in Eureka Dashboard for this please go through the class Recording.

 * Open the POSTMAN tool and test the following API Endpoint to verify customer & Address information or not

   http://localhost:9797/api/customers/1052

OUTPUT
======
{
    "customerDetails": {
        "id": 1052,
        "name": "Ramesh",
        "location": "Hyderabad",
        "gender": "Male",
        "emailId": "Ramesh.ashokit@gmail.com",
        "contactNo": "12345",
        "createdDate": "2025-06-27T08:13:47.466333"
    },
    "addressDetails": {
        "id": 102,
        "doorNo": "11-22-33",
        "cityName": "Chennai",
        "pincode": "12323",
        "created_dt": "2025-06-27T08:18:04.500836",
        "customerId": 1052
    }
}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++