Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-7663

Programmatic approach for Circuit-Breaker feature is not working

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Not A Problem
    • 3.2.1
    • None
    • JAX-RS
    • None
      • which version of the software - Apache CXF 3.2.1
      • what platform and JDK - Tomcat 7, JDK 1.8.0_131
    • Unknown

    Description

      As per the documentation - https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Failover#JAX-RSFailover-Code.1, I tried running the following code along with associated configurations, but the circuit breaker mechanism is not opening up once the threshold count for connectivity failures have exceeded. As the circuit stays closed, the invocation attempts are still being accepted which is against expected behaviour.

       

      public class CustomerRestClient {
      
          private CustomerRestClientFactory customerRestClientFactory;
      
          public List<Customer> filterByFirstName(String firstName) {
              List<Customer> filteredCustomers = new ArrayList<>();
              CircuitBreakerFailoverFeature cbFailoverFeature = new CircuitBreakerFailoverFeature(4, 180000L);
              SequentialStrategy strategy = new SequentialStrategy();
              cbFailoverFeature.setStrategy(strategy);
              
              List<Feature> featureList = new ArrayList<Feature>();
              featureList.add(cbFailoverFeature);
      
              WebClient client = customerRestClientFactory.getClient(featureList).path("/");
              // Call service to get all customers
              List<Customer> customers = client.get(new GenericType<List<Customer>>() {});
              return filteredCustomers;
          }
      
          public void setCustomerRestClientFactory(CustomerRestClientFactory customerRestClientFactory) {
              this.customerRestClientFactory = customerRestClientFactory;
          }
      }
      

       

      public class CustomerRestClientFactory implements InitializingBean {
      
          private List providerList;  // Value is injected by Spring
          private String serviceUrl;  // Value is injected by Spring
      
          public WebClient getClient(List<? extends Feature> featureList) {
              if (featureList == null || featureList.isEmpty()) {
                  throw new IllegalArgumentException("featureList is not initialized.");
              }
              JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
              bean.setAddress(serviceUrl);
              bean.setServiceClass(WebClient.class);
              bean.setProviders(providerList);
              bean.setFeatures(featureList);
      
              return bean.createWebClient();
          }
      
      }
      <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">             <property name="dateFormat">
              <bean class="java.text.SimpleDateFormat"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd'T'HH:mm:ss"/>
              </bean>
      </property>
      <property name="serializationInclusion">
          <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value> </property>
      </bean>
      <bean id="jsonProvider" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider">
           <property name="mapper" ref="objectMapper"/>
      </bean>
      <util:list id="providerList">
          <ref bean="jsonProvider" />
          <bean name="exceptionHandler" class="com.mycompany.refapp.exception.AppExceptionHandler" />
      </util:list>
      <bean id="customerRestClientFactory" class="com.mycompany.refapp.client.CustomerRestClientFactory">
          <property name="providerList" ref="providerList" />
          <property name="serviceUrl" value="${customer.rest.service.url}" />
      </bean>
      

      Log containing stack traces (attached).

      After a lot of debugging, I came to an understanding that the counter for connection failures never exceeds the threshold limit because the state of the data (including the counter) is specific to each of the WebClient objects, instantiated for each call. I assumed that if the same instance of a WebClient is used across multiple calls that fail, then the counter would have been updated and eventually open the circuit. Please find attached screenshot for details.

      1) Is my understanding correct?

      2) Kindly help with a working example, as the one mentioned in CWIKI documentation is not working.

       

       

      Attachments

        1. Reason_UnableToOpenCircuit_WebClient_ProgramaticApproach.png
          118 kB
          RANADEEP SHARMA
        2. app.log
          217 kB
          RANADEEP SHARMA

        Activity

          People

            Unassigned Unassigned
            ranadeep.sharma@gmail.com RANADEEP SHARMA
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: