Spring Cloud + Hysterix Circuit Breaker(2021) Hello World Example | CodeUsingJava






















Spring Cloud + Hysterix Circuit Breaker (2021) with Example

In this tutorial we will be implementing Spring Boot with Hysterix Circuit Breaker with the help of example.
In an enterprise application, couple of services work as a team for the smooth working of an application.
There may be cases that a service fails and the result can lead to the failure of the whole application. So here comes the role of Hysterix Circuit Breaker.
If any of services is not working in an enterprise application, the execution is redirected to (fallback) to a diverse path automatically can be implemented by the circuit breaker. Netflix provide a tool known as Hysterix for this mechanism.
The Hysterix can be explained as follows:-
Spring Boot  hysterix intro

In this example, we have a eureka server, a HysterixDemoServer and a HysterixDemoClient. We are calling an API of HysterixDemoServer from the HysterixDemoClient. There would be a different behaviour seen in case the HysterixDemoServer is down.
  • EurekaServer

    All the services can register their address(hosts and port number) to the eureka server. This will be the standard directory layout for maven project structure-
    Spring Boot eureka server Maven Project
    We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.
    	<?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.2.2.RELEASE</version>
    			<relativePath/> <!-- lookup parent from repository -->
    		</parent>
    		<groupId>com.codeusingjava.Hysterix</groupId>
    		<artifactId>HysterixEurekaServer</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    		<name>eureka-service</name>
    		<description>Demo project for Spring Boot Eureka register service</description>
    	
    		<properties>
    			<java.version>1.8</java.version>
    			<spring-cloud.version>Hoxton.SR1</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>
    				<exclusions>
    					<exclusion>
    						<groupId>org.junit.vintage</groupId>
    						<artifactId>junit-vintage-engine</artifactId>
    					</exclusion>
    				</exclusions>
    			</dependency>
    		</dependencies>
    	
    		<dependencyManagement>
    			<dependencies>
    				<dependency>
    					<groupId>org.springframework.cloud</groupId>
    					<artifactId>spring-cloud-dependencies</artifactId>
    					<version>0</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>
    	
    
    Creating the configuration in application.yml file as follows-
    We can externalise our configuration with the help of this file.
    	eureka:
    	client:
    	  registerWithEureka: false
    	  fetchRegistry: false
    	server:
    	  waitTimeInMsWhenSyncEmpty: 0
    
    Creating the configuration in application.properties file as follows-
    	spring.application.name=HysterixEurekaService
    	server.port=8761
    
    The main class for HysterixEurekaServer is as follows-
    	package com.codeusingjava.Hysterix;
    
    	import org.springframework.boot.SpringApplication;
    	import org.springframework.boot.autoconfigure.SpringBootApplication;
    	import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    	
    	@EnableEurekaServer
    	@SpringBootApplication
    	public class HysterixEurekaServerApplication {
    	
    		public static void main(String[] args) {
    			SpringApplication.run(HysterixEurekaServerApplication.class, args);
    		}
    	
    	}
    	
    

    HysterixDemoServer

    It is the simple service which executes the api mentioned in the controller.
    The api present in the controller of this application would be accessed by thr HysterixDemoClient service.
    The Maven project structure is a follows:-
    Spring Boot server  Project str.
    We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.
    	<?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.2.2.RELEASE</version>
    			<relativePath/> <!-- lookup parent from repository -->
    		</parent>
    		<groupId>com.codeusingjava.Hysterix</groupId>
    		<artifactId>HysterixDemoServer</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    		<name>demo-server</name>
    		<description>Demo project for Spring Boot server microservice</description>
    	
    		<properties>
    			<java.version>1.8</java.version>
    			<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
    		</properties>
    	
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloud</groupId>
    				<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    			</dependency>
    	
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-test</artifactId>
    				<scope>test</scope>
    				<exclusions>
    					<exclusion>
    						<groupId>org.junit.vintage</groupId>
    						<artifactId>junit-vintage-engine</artifactId>
    					</exclusion>
    				</exclusions>
    			</dependency>
    	
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-web</artifactId>
    			</dependency>
    		</dependencies>
    	
    		<dependencyManagement>
    			<dependencies>
    				<dependency>
    					<groupId>org.springframework.cloud</groupId>
    					<artifactId>spring-cloud-dependencies</artifactId>
    					<version>0</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>
    	
    
    Creating the configuration in application.yml file
    	spring:
    	application:
    	  name: HysterixDemoServer
      
      server:
    	port: 8088
      
      
      eureka:
    	client:
    	  registerWithEureka: true
    	  fetchRegistry: true
    	  serviceUrl:
    		defaultZone: http://localhost:8761/eureka/
    	instance:
    	  hostname: localhost
      
    
    Creating the controller class for HysterixDemoServer
    	package com.codeusingjava.Hysterix.controller;
    
    	import org.springframework.web.bind.annotation.GetMapping;
    	import org.springframework.web.bind.annotation.RequestMapping;
    	import org.springframework.web.bind.annotation.RestController;
    	
    	@RestController
    	@RequestMapping("/api/server")
    	public class HelloController {
    	
    		@GetMapping
    		public String message(){
    			return "Welcome to Hysterix Demo Server";
    		}
    	
    	}
    	
    
    Creating the main class
    @EnableDiscoveryClient enables the service discovery and such functionalities.
    	package com.codeusingjava.Hysterix;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @EnableDiscoveryClient
    @SpringBootApplication
    public class DemoServerApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(DemoServerApplication.class, args);
    	}
    
    }
    
    

    HysterixDemoClient

    It is another service registered with the EurekaServer.
    It is the client service where the API of HysterixDemoServer is to be consumed. The project structure for the HysterixDemoClient is as follows-
    Spring Boot client  Project str.
    In the pom.xml, we need to add all the dependencies that we added in HysterixDemoServer.
    Now add the following dependency also in the pom.xml file.
    	<?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.2.2.RELEASE</version>
    			<relativePath/> <!-- lookup parent from repository -->
    		</parent>
    		<groupId>com.codeusingjava.Hysterix</groupId>
    		<artifactId>HyserixDemoClient</artifactId>
    		<version>0.0.1-SNAPSHOT</version>
    		<name>demo-client</name>
    		<description>Demo project for Spring Boot</description>
    	
    		<properties>
    			<java.version>1.8</java.version>
    			<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
    		</properties>
    	
    		<dependencies>
    			<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-hystrix</artifactId>
    				<version>1.2.5.RELEASE</version>
    			</dependency> 
    	
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-test</artifactId>
    				<scope>test</scope>
    				<exclusions>
    					<exclusion>
    						<groupId>org.junit.vintage</groupId>
    						<artifactId>junit-vintage-engine</artifactId>
    					</exclusion>
    				</exclusions>
    			</dependency>
    	
    			<dependency>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-starter-web</artifactId>
    			</dependency>
    		</dependencies>
    	
    		<dependencyManagement>
    			<dependencies>
    				<dependency>
    					<groupId>org.springframework.cloud</groupId>
    					<artifactId>spring-cloud-dependencies</artifactId>
    					<version>0</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 application.yml file is as follows:-
    	spring:
    	application:
    	  name: HysterixDemoClient
      
      server:
    	port: 8089
      
      
      eureka:
    	client:
    	  registerWithEureka: true
    	  fetchRegistry: true
    	  serviceUrl:
    		defaultZone: http://localhost:8761/eureka/
    	instance:
    	  hostname: localhost
      
    
    The controller class for the HysterixDemoClient is as follows-
    @HysterixCommand is defined on the method where we need to apply the fallbackMethod.
    The fallbackMethod which is in our program is handleFallback() will be executed when HysterixDemoServer service is not in an active state.
    	package com.codeusingjava.Hysterix.controller;
    
    	import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    	import org.springframework.beans.factory.annotation.Autowired;
    	import org.springframework.web.bind.annotation.GetMapping;
    	import org.springframework.web.bind.annotation.RequestMapping;
    	import org.springframework.web.bind.annotation.RestController;
    	import org.springframework.web.client.RestTemplate;
    	
    	@RestController
    	@RequestMapping("/api/client")
    	public class DemoController {
    	
    		@Autowired
    		public RestTemplate restTemplate;
    	
    		@GetMapping
    		@HystrixCommand(fallbackMethod = "handleFallback")
    		public String test(){
    			String url = "http://HysterixDemoServer/api/server";
    			return restTemplate.getForObject(url, String.class);
    		}
    	
    		public String handleFallback(){
    			return "This service is fallback service. It is called when HysterixDemoServer is down";
    		}
    	}
    	
    
    Run the following Spring Boot class for starting our application.
    @EnableCircuitBreaker defines that the functionality such that circuit breaker is enabled automatically in the application.
    	package com.codeusingjava.Hysterix;
    
    	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;
    	import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    	import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    	import org.springframework.context.annotation.Bean;
    	import org.springframework.context.annotation.Configuration;
    	import org.springframework.web.client.RestTemplate;
    	
    	@EnableCircuitBreaker
    	@EnableDiscoveryClient
    	@SpringBootApplication
    	public class DemoClientApplication {
    	
    		public static void main(String[] args) {
    			SpringApplication.run(DemoClientApplication.class, args);
    		}
    	}
    	
    	@Configuration
    	class DemoClienConfiguration{
    	
    		@Bean
    		@LoadBalanced
    		public RestTemplate restTemplate(){
    			return new RestTemplate();
    		}
    	
    	}
    	
    
Run the application
If we now run the HysterixEurekaServerApplication
Now run the HysterixDemoServer as spring boot application
Now run the HysterixDemoClient as spring boot application The output is as follows:-
Spring Boot Maven Project

Go to console at localhost:8761
Spring Boot Maven Project

Now click the url of the HysterixDemoClient. Now type the following url:- http://localhost:8089/api/client The output is as follows-
Spring Boot Maven Project

Now Purposely stop the HysterixDemoServer service and again refresh the above url. The output is as follows:-
Spring Boot Maven Project

Downloads-

Spring Cloud + Hysterix Circuit Breaker Hello World Example