question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Stub getting lost while using hystrix

See original GitHub issue

Hi all, I’d like to report not a bug but a limitation i have encounter.

I created a test that use Wiremock rule :

  @Rule
  public WireMockRule myRemoteService = new WireMockRule(4242);
  // ...
    myRemoteService.stubFor(//
        get("/entities")//
            .willReturn(//
                aResponse()//
                    .withStatus(HttpStatus.SC_OK)//
                    .withHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE)//
                    .withBody("[]")));

This remote service is accessed through a feign client with ribbon and hystrix in the mix.

If hystrix is not enabled, everything works fine. As soon as i enable hystrix, the stub is not used and i got a hystrix exception (and no fallback are defined). Deeping in hystrix code to debug before the request execution, I found that wiremock mapping are not defined. This is because hystrix execute in a separate thread than the test’s one.

To fix the problem, 2 solutions :

  • make hystrix work in the same thread (isolation strategy : semaphore) [theory, i didn’t test this approach]
  • write your own concurrency strategy (get and store the wiremock threadlocal value before going into separate thread, then, in the separate thread, put back the wiremock value) [i had it working in our project]

Here is the strategy i wrote (only for the test) :

import java.util.concurrent.Callable;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import com.github.tomakehurst.wiremock.client.WireMock;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;

@Component
@Primary
public class TestHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

  public TestHystrixConcurrencyStrategy() {
    try {
      HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
    } catch (IllegalStateException ise) {
      log.info("strategy already exists", ise);
      HystrixConcurrencyStrategy existingStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
      log.debug("here is the existing strategy", existingStrategy);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> Callable<T> wrapCallable(Callable<T> callable) {
    ThreadLocal<WireMock> wiremockTL;
    try {
      wiremockTL = (ThreadLocal<WireMock>) FieldUtils.readStaticField(WireMock.class, "defaultInstance", true);
    } catch (IllegalAccessException exception) {
      throw new TechnicalException("Failure to access Wiremock.defaultInstance", exception);
    }
    return new HystrixContextWrapper<>(callable, wiremockTL);
  }

  public static class HystrixContextWrapper<V> implements Callable<V> {
    private Callable<V> delegate;
    private WireMock wireMock;
    private ThreadLocal<WireMock> wiremockTL;

    /**
     * Wrap a callable.
     * 
     * @param delegate the callable to wrap
     */
    public HystrixContextWrapper(Callable<V> delegate, ThreadLocal<WireMock> wiremockTL) {
      this.delegate = delegate;
      this.wiremockTL = wiremockTL;
      wireMock = wiremockTL.get();
    }

    @Override
    public V call() throws Exception {
      WireMock wireMockInitial = wiremockTL.get();
      wiremockTL.set(wireMock);
      try {
        return this.delegate.call();
      } finally {
        wiremockTL.set(wireMockInitial);
      }
    }
  }
}

I’m not satisfied with this approach because i’m depending on static attribute’s name and i have to do reflection to access it. For test purpose, it’s ok i guess. I’d like to know if there is a better way to define wiremock rule in a multithread context like this (and i’d love to keep the simplicity of the wiremockrule =P).

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9

github_iconTop GitHub Comments

2reactions
ldiasrscommented, Aug 7, 2018

I found the same problem when i wrote some test for Hystrix timeout.

With Hystrix enable and using the @Rule the server get lost and not respond some times.

The workaround was to use the WireMockServer instead of WireMockRule

0reactions
gungorcommented, Nov 30, 2019

It is about hystrix default timeout. Because stub may appear after hystrix timeout passed. You should increase it as @devjiel mentioned for all hystrix timeouts with this property: hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 10000

Read more comments on GitHub >

github_iconTop Results From Across the Web

Stub getting lost while using hystrix · Issue #606 - GitHub
This remote service is accessed through a feign client with ribbon and hystrix in the mix. If hystrix is not enabled, everything works...
Read more >
spring - Hystrix - slow response on first request - Stack Overflow
It happens when the HystrixCommandGroup is initialized the first time. Most time is lost when creating the HystrixMetrics: hystrix profiling.
Read more >
Copying current request information into Feign interceptor with ...
The idea was that if an incoming request has an Accept-Language header, I should pass it over with every Feign request in order...
Read more >
Test Doubles — Fakes, Mocks and Stubs. | by Michal Lipski
In this article I will describe three implementation variations of testing doubles: Fake, Stub and Mock and give you examples when to use...
Read more >
spring-cloud/spring-cloud - Gitter
So I can get all the pieces working, just not together. Specifically when I switched from using restTemplate based REST client definitions to ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found