Skip to content
Snippets Groups Projects
Cihat Topsakal's avatar
Cihat Topsakal authored
Project upgrade

See merge request !2
5821e57a
History
Name Last commit Last update
img
setup
solution
README.md

Service Discovery & Communication

  1. Generate a new stand-alone Spring application using Spring Initialzr. (Can find the setup folder)

  2. Fill up the necessary fields (Group, Artifact and Dependencies) as shown below.

spring-initializr

Gruop: com.eteration
Artifact: discovery-server
Project: maven
Dependicies: Spring Web, Eureka Server
  1. Then click the generate button(ctrl+enter) project will be downloaded as a compressed file, extract it to a suitable directory

  2. Launch Eclipse EE and click the import project.

  3. The generated project as an Existing Maven Project as shown below.

existing-maven

  1. Click the browse and select the extracted file(config-server).

import-discovery-server

  1. If everything is done correctly, one should have a similar folder structure as displayed below.

check-discovery

  1. Let's use customer-service, product-service, order-service example, config-server(We can find the setup folder).

  2. Import the projects in Eclipse.

  3. After importing the downloaded project to Eclipse, make the following modifications in DiscoveryServerApplication.java to enable the discovery server by using the annotation @EnableEurekaServer at class level. Finally like this.

package com.eteration.discoveryserver;

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

@EnableEurekaServer
@SpringBootApplication
public class DiscoveryServerApplication {

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

}
  1. Now we have a discovery-server, we need to register other services as discovery-client, to do this add the following dependency to each pom.xml files of all corresponding services (customer, product and order):
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. After this addition one should “refresh” all Maven Projects so that the dependency manager will download the dependency added. Right-click on any project, and from the menu hover, select all on Maven and from there click on Update Project.

  2. After dependencies are downloaded, add @EnableDiscoveryClient annotation to CustomerServiceApplication.java, ProductServiceApplication.java, OrderServiceApplication.java at class level as below:

package com.eteration.customerservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class CustomerServiceApplication {

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

}
  1. If you run discovery-server with default properties it will complain. Because by default it will try to register itself. To deal with this situation, create an application.yaml under src/main/resources as shown below:
server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
  server:
    enableSelfPreservation: false

Start Feign Client Implementation

  1. Add the following dependency to pom.xml file of order-service to begin Feign Client implementation:
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-openfeign</artifactId>
	</dependency>
  1. After refreshing the project as explained before, add @EnableFeignClients annotations to OrderServiceApplication.java at class level. These annotations do what they say they do. Like this:
package com.eteration.orderservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {

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

}
  1. Now it is time to implement Feign Clients in order-service, to do this follow the instructions below and in case of difficulty see the implemented versions below:

  2. Create the client package: com.example.demo.orderservice.client

order-service-create-client

order-service-project-explorer

  • Create a class : CustomerDTO.java

customerDTO-create

  • Modify this class as below:
package com.eteration.orderservice.client;

public class CustomerDTO {
	
	private int id;
	private String name;
	private String address;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
}
  1. Create an interface: CustomerServiceClient.java

customer-interface

  • Modify this class as below:
package com.eteration.orderservice.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("customer-service")
public interface CustomerServiceClient {
	
	
	@GetMapping("/customers/{customerId}")
	public CustomerDTO  readCustomerById(@PathVariable("customerId")long id);
	

}
  1. Create a class: ProductDTO.java

productdto-create

  • Modify this class as below:
package com.eteration.orderservice.client;

public class ProductDTO {

	private long id;
	private String name;
	private int price;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

}
  1. Create a inteface: ProductServiceClient.java

ProductServiceClient

  • Modify this class as below:
package com.eteration.orderservice.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("product-service")
public interface ProductServiceClient {
	
	@GetMapping("/products/{productId}")
	public ProductDTO readProduct(@PathVariable("productId") long id);
}
  1. Modify OrderService.java, OrderServiceApplication.java and as shown below:
package com.eteration.orderservice.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import com.eteration.orderservice.client.CustomerDTO;
import com.eteration.orderservice.client.CustomerServiceClient;
import com.eteration.orderservice.client.ProductDTO;
import com.eteration.orderservice.client.ProductServiceClient;
import com.eteration.orderservice.controller.OrderController;
import com.eteration.orderservice.dto.OrderRequestDTO;
import com.eteration.orderservice.dto.OrderResponseDTO;

@Service
public class OrderService {

	
	@Autowired
	private ProductServiceClient  productServiceClient;
	
	@Autowired
	private  CustomerServiceClient customerServiceClient;
	
	private static Logger logger  = LoggerFactory.getLogger(OrderService.class);
	
	public OrderResponseDTO createOrder(@RequestBody OrderRequestDTO orderRequest)
	{
		
		logger.info(orderRequest.toString());
		OrderResponseDTO   orderResponseDTO = new OrderResponseDTO();
		ProductDTO product = productServiceClient.readProduct(orderRequest.getProductId());
		CustomerDTO customer = customerServiceClient.readCustomerById(orderRequest.getCustomerId());
		orderResponseDTO.setOrderId(orderRequest.getCustomerId() +"_"+orderRequest.getProductId() );
		orderResponseDTO.setTotalAmount(product.getPrice()*orderRequest.getCount());
		orderResponseDTO.setMessage("Customer information: "+customer.getName()  +",Customer address: "+customer.getAddress());

		return orderResponseDTO;
	}

}
  • OrderServiceApplication.java
package com.eteration.orderservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {

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

}
  • OrderRequestDTO.java
package com.eteration.orderservice.dto;

public class OrderRequestDTO {
	
	private long customerId;
	private long productId;
	private int count;
	
	
	@Override
	public String toString() {
		return "OrderRequestDTO [CustomerId: " + customerId + ", ProductId: " + productId + ", Order count: " + count + "]";
	}

	public long getCustomerId() {
		return customerId;
	}
	public void setCustomerId(long customerId) {
		this.customerId = customerId;
	}
	public long getProductId() {
		return productId;
	}
	public void setProductId(long productId) {
		this.productId = productId;
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	
}
  1. So let's add logger to product-service.
  • ProductDTO.java add to toString() method using right-click -> source -> generate toString()..
package com.eteration.productservice.dto;

public class ProductDTO {
	
	private String productId;
	private String name;
	private double price;
	
	
	@Override
	public String toString() {
		return "ProductDTO [productId=" + productId + ", name=" + name + ", price=" + price + "]";
	}
	
	public String getProductId() {
		return productId;
	}
	public void setProductId(String productId) {
		this.productId = productId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
}
  • ProductService.java add to logger.
package com.eteration.productservice.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import com.eteration.productservice.controller.ProductServiceController;
import com.eteration.productservice.dto.ProductDTO;

@Service
public class ProductService {

	@Value("${kdv}")
	private int kdv;
	
	private static Logger logger  = LoggerFactory.getLogger(ProductServiceController.class);
	
	public ProductDTO readProduct(@PathVariable("productId") String productId) {
		ProductDTO product = new ProductDTO();
		product.setProductId(productId);
		product.setName("Product" + productId);
		product.setPrice(Math.random() * 100 * kdv);
		
		logger.info(product.toString());
		return product;
	}
}
  1. So let's add logger to customer-service.
  • CustomerDTO.java add to toString() method using right-click -> source -> generate toString()..
package com.eteration.customerservice.dto;

public class CustomerDTO {

	private String id;
	private String name;
	private String surname;
	private String address;
	private String cardNumber;
	
	@Override
	public String toString() {
		return "CustomerDTO [id=" + id + ", name=" + name + ", surname=" + surname + ", address=" + address
				+ ", cardNumber=" + cardNumber + "]";
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSurname() {
		return surname;
	}
	public void setSurname(String surname) {
		this.surname = surname;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getCardNumber() {
		return cardNumber;
	}
	public void setCardNumber(String cardNumber) {
		this.cardNumber = cardNumber;
	}
}
  • CustomerService.java add to logger.
package com.eteration.customerservice.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.eteration.customerservice.dto.CustomerDTO;
import com.eteration.customerservice.controller.CustomerController;

@Service
public class CustomerService {
	
	private static Logger logger  = LoggerFactory.getLogger(CustomerController.class);
	
	public CustomerDTO readCustomer(String id) {
		CustomerDTO customer = new CustomerDTO();
		customer.setId(id);
		customer.setAddress("İstanbul/Bahcelievler");
		customer.setName("Murat");
		customer.setSurname("Karakas");
		customer.setCardNumber("1234-4545-4545-2325");

		logger.info(customer.toString());
		return customer;
	}
}
  1. Now start running all services as a Java Application with the following order and go to the port where discovery-server is started on a browser to check results:
  • config-server
  • discovery-server
  • product-service / customer-service
  • order-service
  1. Check the Result http://localhost:8761

discovery-server-res

  1. Open a tool that is able to make HTTP requests Postman after running OrderServiceApplication.java, start constructing the response body as below and
  • Follow the red circles postman-orders
  • make the request:
{
"customerId": 4,
"productId": 2,
"count":"3"
}
  • excpected output like this:
{
    "orderId": "4_2",
    "message": "Customer information: Murat,Customer address: İstanbul/Bahcelievler",
    "totalAmount": 1479.0
}
  1. So let's check eclipse log in customer-service

customer-log-eclipse

  1. And also check using eclipse in product-service

product-log-eclipse