Circuit Breaker Pattern with CRISP API

Info: The POJO Mapping feature used in the following examples is supported from version 2.1.1.

Overview

You can implement the Circuit Breaker Pattern in components and services that use the CRISP API. For example, you can define HstComponent classes as Spring-managed components and inject business service components into them. In the business service layer, you can use Circuit Breaker framework annotations (such as @HystrixCommand from Netflix Hystrix) to provide fallback methods if an operation fails or times out.

The CRISP API provides Resource objects as a thin abstraction over backend JSON or XML data from REST API calls. Applying the Circuit Breaker Pattern on top of the CRISP API introduces minimal overhead. This approach allows you to use all CRISP API features, including repository-based configuration, caching control, and generic object support for templating.

The following sections show how to use the Netflix Hystrix framework in a delivery tier web application. The examples include a Spring-managed component and a business service component with a @HystrixCommand method that reads data using the CRISP API.

Applying Netflix Hystrix in the Delivery Tier Web Application

Delivery tier web applications are typically not Spring Boot applications. To use Hystrix, add the hystrix-javanica dependency. For details, see the hystrix-javanica project.

Add the following dependency to the root pom.xml:

<properties> <!-- SNIP --> <!-- If necessary, update the version to the most proper and latest one. --> <hystrix-javanica.version>1.5.12</hystrix-javanica.version> <!-- SNIP --> </properties> <dependencyManagement> <dependencies> <!-- SNIP --> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> <version>${hystrix-javanica.version}</version> </dependency> <!-- SNIP --> </dependencies> </dependencyManagement>

Then, add the dependency to site/pom.xml:

<dependencies> <!-- SNIP --> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> </dependency> <!-- SNIP --> </dependencies>

Spring Configuration for Hystrix and Spring-Managed Components

The delivery tier web application uses Spring AOP. Add the following configuration to enable AspectJ and @HystrixCommandAspect. Place this configuration in site/src/main/resources/META-INF/hst-assembly/overrides/hystrix-javanica-spring-aspect.xml:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- Enable AspectJ-based aspect management in Spring. --> <aop:aspectj-autoproxy /> <!-- Register HystrixCommandAspect for handling @HystrixCommand annotations. --> <bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"> </bean> </beans>

To enable Spring-managed components and allow automatic wiring of business service beans, add the following to site/src/main/resources/META-INF/hst-assembly/overrides/spring-managed-components.xml:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- Enable annotation scanning for Spring-managed components and service beans. --> <!-- In this example, all Spring-managed components are in org.onehippo.cms7.crisp.demo.components, and service beans are in org.onehippo.cms7.crisp.demo.service. --> <context:component-scan base-package="org.onehippo.cms7.crisp.demo.components,org.onehippo.cms7.crisp.demo.service" /> </beans>

After these configurations, you can implement components that use the Netflix Hystrix framework in your delivery tier web application.

Example: Components Using Hystrix

The following example shows a business service bean, ProductService. The service defines a @HystrixCommand method, getProductCollection(), which uses the CRISP API. If the method fails or times out, Hystrix automatically falls back to getReliableProductCollection().

@Service public class ProductService { private static Logger log = LoggerFactory.getLogger(ProductService.class); // Demo cached JSON file for fallback data. private static final URL DEMO_LOCAL_CACHED_PRODUCTS_JSON_URL = ProductService.class.getResource("cached-products.json"); // ObjectMapper for parsing JSON data in the fallback method. private ObjectMapper objectMapper = new ObjectMapper(); /** * Hystrix command with a fallback method and a 3-second execution timeout. */ @HystrixCommand( fallbackMethod = "getReliableProductCollection", commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") } ) public Collection<Product> getProductCollection() { Resource productCatalogs = null; ResourceServiceBroker resourceServiceBroker = CrispHstServices.getDefaultResourceServiceBroker(HstServices.getComponentManager()); final Map<String, Object> pathVars = new HashMap<>(); productCatalogs = resourceServiceBroker.findResources(RESOURCE_SPACE_DEMO_PRODUCT_CATALOG, "/products/", pathVars); ResourceBeanMapper resourceBeanMapper = resourceServiceBroker .getResourceBeanMapper(RESOURCE_SPACE_DEMO_PRODUCT_CATALOG); Collection<Product> productCollection = resourceBeanMapper.mapCollection(productCatalogs.getChildren(), Product.class); return productCollection; } /** * Fallback method that reads cached data from a JSON file in the classpath. */ public Collection<Product> getReliableProductCollection() { List<Product> productsList = new LinkedList<>(); InputStream is = null; BufferedInputStream bis = null; try { is = DEMO_LOCAL_CACHED_PRODUCTS_JSON_URL.openStream(); bis = new BufferedInputStream(is); JsonNode root = objectMapper.readTree(bis); for (Iterator<JsonNode> it = root.elements(); it.hasNext();) { JsonNode elem = it.next(); Product product = objectMapper.convertValue(elem, Product.class); productsList.add(product); } } catch (Exception e) { log.error("Failed to read data from json resource file.", e); } finally { IOUtils.closeQuietly(bis); IOUtils.closeQuietly(is); } return productsList; } }

The fallback method, getReliableProductCollection(), reads data from a local JSON file in the classpath. This approach is used for demonstration purposes.

The following example shows a Spring-managed HstComponent, ProductListComponent:

@Service @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ProductListComponent extends BaseHstComponent { private static Logger log = LoggerFactory.getLogger(ProductListComponent.class); @Autowired private ProductService productService; @Override public void doBeforeRender(final HstRequest request, final HstResponse response) { super.doBeforeRender(request, response); Collection<Product> products = productService.getProductCollection(); request.setAttribute("products", products); } }

Because ProductListComponent is instantiated by Spring, the productService dependency is injected automatically. In the doBeforeRender(...) method, the component calls ProductService#getProductCollection(). Spring AOP and the Netflix Hystrix framework create a dynamic proxy for the service bean. The caller (ProductListComponent) can invoke the service operation without needing to manage circuit breaker logic. Hystrix applies the Circuit Breaker Pattern automatically.

Summary

You can apply the Circuit Breaker Pattern in your delivery tier web application using the Netflix Hystrix framework. Implement HstComponent classes as Spring-managed components and inject business service components. Spring AOP and Hystrix will create dynamic proxies to enable the Circuit Breaker Pattern automatically. Use @HystrixCommand annotations to define fallback behavior for operations that use the CRISP API and may fail or time out.

References

Share Feedback
Page: /build/crisp-api/introduction-config/circuit-breaker-pattern-with-crisp-api
Section: Build
Category *