Sunday, July 30, 2017

Working with Ribbon with out Eureka

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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)RibbonWithoutEureka(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)RibbonWithoutEureka(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(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.cloud(/groupId)
(artifactId)spring-cloud-starter-ribbon(/artifactId)
(/dependency)

(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)


application.properties:
================
testApp.ribbon.listOfServers=http://localhost:8081,http://localhost:8082
testApp.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.WeightedResponseTimeRule
testApp.ribbon.serverRefreshInterval=15000
testApp.ribbon.eureka.enabled=false
server.port=8083


SpringBootHelloWorldApplication.java
=============================

package com.javainuse;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;

import com.javainuse.controllers.ConsumerControllerClient;
import com.spring.TestAppConfiguration;

@SpringBootApplication
@RibbonClient(name="testApp",configuration=TestAppConfiguration.class)
public class SpringBootHelloWorldApplication {

public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(
SpringBootHelloWorldApplication.class, args);
ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
consumerControllerClient.getEmployee();
}
@Bean
public  ConsumerControllerClient  consumerControllerClient()
{
return  new ConsumerControllerClient();
}
}


ConsumerControllerClient.java
======================

package com.javainuse.controllers;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerControllerClient {
@Autowired
private LoadBalancerClient loadBalancer;
@RequestMapping(value = "/employee", method = RequestMethod.GET)
public void getEmployee() throws RestClientException, IOException {
ServiceInstance serviceInstance=loadBalancer.choose("testApp");
System.out.println(serviceInstance.getUri());
String baseUrl=serviceInstance.getUri().toString();
baseUrl=baseUrl+"/employee";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex)
{
System.out.println(ex);
}
System.out.println(response.getBody());
}

private static HttpEntity getHeaders() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
return new HttpEntity<>(headers);
}
}


TestAppConfiguration.java
===================
package com.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.WeightedResponseTimeRule;

@Configuration
public class TestAppConfiguration {
@Bean
IRule rule(){
return new WeightedResponseTimeRule();
}
}

Saturday, July 29, 2017

Spring Cloud- REST call using Netflix Feign Client

In this post we implement the Netflix Feign client. Previously we had implemented Load Balancing using Netflix Ribbon. The netflix ribbon code here will be the starting point. Will only be making changes in the employee-consumer module by adding the Netflix Feign code. The employee-producer and Eureka Server code will remain the same.

What is the Netflix Feign Client? Need for it?
Feign is a java to http client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal was reducing the complexity of binding Denominator uniformly to http apis regardless of restfulness. Previous examples in the employee-consumer we consumed the REST services exposed by the employee-producer using REST Template


But we had to write a lot of code to perform following-
For Load balancing using Ribbon.
Getting the Service instance and then the Base URL.
Make use of the REST Template for consuming service.

The previous code was as below
@Controller
public class ConsumerControllerClient {

@Autowired
private LoadBalancerClient loadBalancer;

public void getEmployee() throws RestClientException, IOException {

ServiceInstance serviceInstance=loadBalancer.choose("employee-producer");

System.out.println(serviceInstance.getUri());

String baseUrl=serviceInstance.getUri().toString();

baseUrl=baseUrl+"/employee";

RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex)
{
System.out.println(ex);
}
System.out.println(response.getBody());
}



The previous code, there are chances of exceptions like NullPointer and is not optimal. We will see how the call is made much easier and cleaner using Netflix Feign. If the Netflix Ribbon dependency is also in the classpath, then Feign also takes care of load balancing by default.
Lets Begin-
As mentioned earlier the source code shared in the previous netflix ribbon tutorial will be the starting point. And the employee-consumer model we will be making the changes.




We first add the netflix feign dependency in the pom as follows-
(?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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.javainuse(/groupId)
(artifactId)employee-consumer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.4.1.RELEASE(/version)
(relativePath /) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(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.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-ribbon(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-feign(/artifactId)
(/dependency)
(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/version)
(type)pom(/type)
(scope)import(/scope)
(/dependency)
(/dependencies)
(/dependencyManagement)
(/project)


We next define a Feign Client by creating an interface with @FeignClient annotation. We also specify the name value as "employee-producer". This value is the name of the service registered using Eureka for discovery. We define the method call to be made to consume the REST service exposed by the employee-producer module.
package com.javainuse.services;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.javainuse.controllers.Employee;

@FeignClient(name="employee-producer")
public interface RemoteCallService {
@RequestMapping(method=RequestMethod.GET, value="/employee")
public Employee getData();

}

Next we autowire the RemoteCallService in the ConsumerControllerClient class. Then using it make the REST call. Load Balancing is automatically taken care by Feign Client.
package com.javainuse.controllers;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestClientException;

import com.javainuse.services.RemoteCallService;

@Controller
public class ConsumerControllerClient {

@Autowired
private RemoteCallService loadBalancer;

public void getEmployee() throws RestClientException, IOException {

try {
Employee emp = loadBalancer.getData();
System.out.println(emp.getEmpId());
} catch (Exception ex) {
System.out.println(ex);
}
}

}

Finally we annotate the Spring Boot Main class with @EnableFeignClients.
package com.javainuse;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;

import com.javainuse.controllers.ConsumerControllerClient;

@SpringBootApplication
@EnableFeignClients
public class SpringBootHelloWorldApplication {

public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(SpringBootHelloWorldApplication.class, args);

ConsumerControllerClient consumerControllerClient = ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
consumerControllerClient.getEmployee();

}

@Bean
public ConsumerControllerClient consumerControllerClient() {
return new ConsumerControllerClient();
}
}


As we had done in previous posts- Start the following Spring Boot Applications-
eureka-server
employee-producer
employee-consumer

Circuit Breaker using Hystrix

What is the Netflix Hystrix Circuit Breaker Feature? Need for it?
In previous posts we had two services- employee-consumer consuming the service exposed by the employee-producer.
Due to some reason the employee-producer exposed service throws an exception. In this case using Hystrix we defined a fallback method. In case of exception in the exposed service the fallback method returned some default value.
If the exceptions keep on occuring in the firstPage method() then the Hystrix circuit will break and the employee consumer will skip the firtsPage method all together and directly call the fallback method.
The purpose of circuit breaker is to give time to the first page method or other methods that the firstpage method might be calling and is causing the exception to recover. It might happen that on less load the issue causing the exceptions have better chance of recovering



The employee-producer had the following firstpage method annotated with the hystrix annotation.

Producer Code:
package com.javainuse.controllers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.javainuse.model.Employee;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class TestController {
@RequestMapping(value = "/employee", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "getDataFallBack")
public Employee firstPage() {
System.out.println("Inside firstPage");
Employee emp = new Employee();
emp.setName("emp1");
emp.setDesignation("manager");
emp.setEmpId("1");
emp.setSalary(3000);

if(emp.getName().equalsIgnoreCase("emp1"))
throw new RuntimeException();
return emp;
}
public Employee getDataFallBack() {
System.out.println("Inside fallback");
Employee emp = new Employee();
emp.setName("fallback-emp1");
emp.setDesignation("fallback-manager");
emp.setEmpId("fallback-1");
emp.setSalary(3000);
return emp;
}
}

Previously using employee-consumer we were calling the employee producer only once. Now using for loop we will call it multiple times and check if the circuit trips and the fallback method gets called directly.

Client Code:
package com.javainuse;
import java.io.IOException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;
import com.javainuse.controllers.ConsumerControllerClient;

@SpringBootApplication
public class SpringBootHelloWorldApplication {
public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(
SpringBootHelloWorldApplication.class, args);
ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
for(int i=0;i<100 i="" span="" style="white-space: pre;">
consumerControllerClient.getEmployee();
}

@Bean
public  ConsumerControllerClient  consumerControllerClient()
{
return  new ConsumerControllerClient();
}
}



As we had done in previous posts- Start the following Spring Boot Applications-
eureka-server
employee-producer
employee-consumer

On running the employee consumer we get the output in employee-producer module as follows-




We can see that after some exceptions the fallback method getting called directly and the hystrix annotated method skipped. So the hystrix circuit is open.

Eureka- Ribbon - Histrix - Producer -Consumer


What is Load Balancing? Need for Netflix Ribbon

In computing, load balancing improves the distribution of workloads across multiple computing resources, such as computers, a computer cluster, network links, central processing units, or disk drives. Load balancing aims to optimize resource use, maximize throughput, minimize response time, and avoid overload of any single resource. Using multiple components with load balancing instead of a single component may increase reliability and availability through redundancy. Load balancing usually involves dedicated software or hardware, such as a multilayer switch or a Domain Name System server process.
In previous posts we developed two services employee-producer and employee-consumer. Suppose other modules are also calling and consuming employee-producer module services. So the load at employee-producer is high. To deal with this we this we deploy multiple instances of employee-producer. Suppose two in this case. Now we will have to use a Load Balancer to route any incoming requests to either one of these two services



Eureka: Expose Service API, it have own Server
Ribbon : load balancer at client side
Histrix : circut breaking, exception hander at application server side


Eureka 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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaServer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaServer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.version)
(/properties)

(dependencies)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter(/artifactId)
(/dependency)

(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka-server(/artifactId)
(/dependency)
(/dependencies)
(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)


Application.properties:
server.port=8090

EurekaServerApplication.java
package com.example.demo;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

========================================================================

Application Producer:
(?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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaProducer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaProducer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.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.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)

(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-hystrix(/artifactId)
(/dependency)
(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)


application.properties:
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
eureka.instance.instanceId=${spring.application.name}:${random.value}

bootstrap.properties:
spring.application.name=employee-producer

Employee.java
package com.javainuse.model;

public class Employee {
private String empId;
private String name;
private String designation;
private double salary;

public Employee() {
}

public String getName() {
return name;
}

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

public String getDesignation() {
return designation;
}

public void setDesignation(String designation) {
this.designation = designation;
}

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}

public String getEmpId() {
return empId;
}

public void setEmpId(String empId) {
this.empId = empId;
}

}

Controller Class
package com.javainuse.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.javainuse.model.Employee;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class TestController {

@RequestMapping(value = "/employee", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "getDataFallBack")
public Employee firstPage() {

Employee emp = new Employee();
emp.setName("emp1");
emp.setDesignation("manager");
emp.setEmpId("1");
emp.setSalary(3000);

if(emp.getName().equalsIgnoreCase("emp1"))
throw new RuntimeException();

return emp;
}

public Employee getDataFallBack() {

Employee emp = new Employee();
emp.setName("fallback-emp1");
emp.setDesignation("fallback-manager");
emp.setEmpId("fallback-1");
emp.setSalary(3000);

return emp;

}

}

package com.javainuse;

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

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class SpringBootHelloWorldApplication {

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

(?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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaConsumer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaConsumer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(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.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-ribbon(/artifactId)
(/dependency)

(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)




package com.javainuse;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;

import com.javainuse.controllers.ConsumerControllerClient;

@SpringBootApplication
public class SpringBootHelloWorldApplication {

public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(
SpringBootHelloWorldApplication.class, args);
ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
consumerControllerClient.getEmployee();
}
@Bean
public  ConsumerControllerClient  consumerControllerClient()
{
return  new ConsumerControllerClient();
}
}




package com.javainuse.controllers;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Controller
public class ConsumerControllerClient {
@Autowired
private LoadBalancerClient loadBalancer;
public void getEmployee() throws RestClientException, IOException {
ServiceInstance serviceInstance=loadBalancer.choose("employee-producer");
System.out.println(serviceInstance.getUri());
String baseUrl=serviceInstance.getUri().toString();
baseUrl=baseUrl+"/employee";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex)
{
System.out.println(ex);
}
System.out.println(response.getBody());
}

private static HttpEntity getHeaders() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
return new HttpEntity<>(headers);
}
}


application.properties:
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka

bootstrap.properties:
spring.application.name=employee-consumer

========================================================================
========================================================================

Example2 : 





Eureka Registry - Ribbon Load balancer - Application Producer - Application Consumer


Eureka: Expose Service API, it have own Server
Ribbon : load balancer at client side
Histrix : circut breaking, exception hander at application server side

bootstrap.yml:
eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
      waitTimeInMsWhenSyncEmpty: 0
  instance:
    hostname: localhost

Eureka 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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaServer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaServer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.version)
(/properties)

(dependencies)
(dependency)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter(/artifactId)
(/dependency)

(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka-server(/artifactId)
(/dependency)
(/dependencies)
(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)


Application.properties:
server.port=8090

EurekaServerApplication.java
package com.example.demo;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

========================================================================

Application Producer:
(?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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaProducer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaProducer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(java.version)1.8(/java.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.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)


(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)

application.properties:
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
eureka.instance.instanceId=${spring.application.name}:${random.value}

bootstrap.properties:
spring.application.name=employee-producer

Employee.java
package com.javainuse.model;

public class Employee {
private String empId;
private String name;
private String designation;
private double salary;

public Employee() {
}

public String getName() {
return name;
}

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

public String getDesignation() {
return designation;
}

public void setDesignation(String designation) {
this.designation = designation;
}

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}

public String getEmpId() {
return empId;
}

public void setEmpId(String empId) {
this.empId = empId;
}

}

Controller Class
package com.javainuse.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.javainuse.model.Employee;

@RestController
public class TestController {

@RequestMapping(value = "/employee", method = RequestMethod.GET)
public Employee firstPage() {

Employee emp = new Employee();
emp.setName("emp1");
emp.setDesignation("manager");
emp.setEmpId("1");
emp.setSalary(3000);

return emp;
}
}


package com.javainuse;

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

@SpringBootApplication
@EnableDiscoveryClient
public class SpringBootHelloWorldApplication {

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

========================================================================
Application Consumer

(?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 http://maven.apache.org/xsd/maven-4.0.0.xsd")
(modelVersion)4.0.0(/modelVersion)

(groupId)com.example(/groupId)
(artifactId)EurekaConsumer(/artifactId)
(version)0.0.1-SNAPSHOT(/version)
(packaging)jar(/packaging)

(name)EurekaConsumer(/name)
(description)Demo project for Spring Boot(/description)

(parent)
(groupId)org.springframework.boot(/groupId)
(artifactId)spring-boot-starter-parent(/artifactId)
(version)1.5.6.RELEASE(/version)
(relativePath/) (!-- lookup parent from repository --)
(/parent)

(properties)
(project.build.sourceEncoding)UTF-8(/project.build.sourceEncoding)
(project.reporting.outputEncoding)UTF-8(/project.reporting.outputEncoding)
(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.cloud(/groupId)
(artifactId)spring-cloud-starter-eureka(/artifactId)
(/dependency)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-starter-ribbon(/artifactId)
(/dependency)

(/dependencies)

(dependencyManagement)
(dependencies)
(dependency)
(groupId)org.springframework.cloud(/groupId)
(artifactId)spring-cloud-dependencies(/artifactId)
(version)Camden.SR6(/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)




package com.javainuse;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestClientException;

import com.javainuse.controllers.ConsumerControllerClient;

@SpringBootApplication
public class SpringBootHelloWorldApplication {

public static void main(String[] args) throws RestClientException, IOException {
ApplicationContext ctx = SpringApplication.run(
SpringBootHelloWorldApplication.class, args);
ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
System.out.println(consumerControllerClient);
consumerControllerClient.getEmployee();
}
@Bean
public  ConsumerControllerClient  consumerControllerClient()
{
return  new ConsumerControllerClient();
}
}




package com.javainuse.controllers;

import java.io.IOException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Controller
public class ConsumerControllerClient {
@Autowired
private LoadBalancerClient loadBalancer;
public void getEmployee() throws RestClientException, IOException {
ServiceInstance serviceInstance=loadBalancer.choose("employee-producer");
System.out.println(serviceInstance.getUri());
String baseUrl=serviceInstance.getUri().toString();
baseUrl=baseUrl+"/employee";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex)
{
System.out.println(ex);
}
System.out.println(response.getBody());
}

private static HttpEntity getHeaders() throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
return new HttpEntity<>(headers);
}
}


application.properties:
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka

bootstrap.properties:
spring.application.name=employee-consumer

spring-cloud-dependencies

1.Dalston.SR1

2.Camden.RELEASE

3.Brixton

So for example if you are using Spring Boot 1.2 then go with Angel, 1.3 then Brixton, 1.4+ then Camden is probably your best bet. Even then you can always get things working by resolving dependency conflicts yourself.

Microservice Registration with Spring cloud using Netflix Eureka

When we start a project, we usally have all the configurations in the properties file.
As more and more services are developed and deployed, adding and modifying these properties become more complex. Some services might go down, while some the location might change. This manual changing of properties may create issues.
Eureka Service Registration and Discovery helps in such scenarios. As all services are registered to the Eureka server and lookup done by calling the Eureka Server, any change in service locations need not be handled and is taken care of
This Post is divided into 4 parts-
a.) Overview of Netflix components.
b.) Develop an Employee service to produce and consume REST API using Spring Boot.
c.) Use Eureka for Service Registration.
d.) Use Eureka for Service Discovery.

The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).

Netflix Component NameFunctionality
EurekaService Registration and Discovery
RibbonDynamic Routing and Load Balancer
HystrixCircuit Breaker
ZuulEdge Server

உப்பு மாங்காய்

சுருக்குப்பை கிழவி. சுருக்கங்கள் சூழ் கிழவி. பார்க்கும் போதெல்லாம் கூடையுடனே குடியிருப்பாள். கூடை நிறைய குட்டி குட்டி மாங்காய்கள். வெட்டிக்க...