New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HystrixRequestContext initialization for @CacheResult #1314

Closed
cicioflaviu opened this Issue Aug 10, 2016 · 4 comments

Comments

Projects
None yet
3 participants
@cicioflaviu
Copy link

cicioflaviu commented Aug 10, 2016

After requesting this method:

    @RequestMapping(method = RequestMethod.GET)
    @CacheResult(cacheKeyMethod = "getAllProductsCacheKey")
    @HystrixCommand(fallbackMethod = "getAllProductsFallback")
    public Product[] getAllProducts() {
        ServiceInstance instance = loadBalancer.choose("product-service");
        return restTemplate.getForObject(instance.getUri() + "/products", Product[].class);
    }

it gives me :

java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?

After hours of searching I didn't found nothing that works, any advice?

@mattrjacobs

This comment has been minimized.

Copy link
Contributor

mattrjacobs commented Aug 10, 2016

So your method is creating an instance of HystrixCommand and executing it. The @CacheResult annotation is trying to set up a request-cache for all executions of this command. The request-cache will de-duplicate multiple executions of command instances which share a cache key in a single request.

For that to happen, the concept of a request-scope must be defined. For Hystrix, it is HystrixRequestContext. You need to delineate the start of a request with HystrixRequestContext.initializeContext. That returns an instance of HystrixRequestContext. When the request is done, you call shutdown() on that instance.

That should get you unblocked. The Wiki has more info, like: https://github.com/Netflix/Hystrix/wiki/How-To-Use#Caching

@cicioflaviu

This comment has been minimized.

Copy link

cicioflaviu commented Aug 11, 2016

@mattrjacobs so the following implementation should be correct?

    @RequestMapping(method = RequestMethod.GET)
    @HystrixCommand(fallbackMethod = "getAllProductsFallback")
    public Product[] getAllProducts() {
        Product[] p;
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try{
            p =  getAll();
        } finally {
            context.shutdown();
        }
        return p;
    }


    @CacheResult(cacheKeyMethod = "getAllProductsCacheKey")
    private Product[] getAll(){
        ServiceInstance instance = loadBalancer.choose("product-service");
        return restTemplate.getForObject(instance.getUri() + "/products", Product[].class);
    }
@mattrjacobs

This comment has been minimized.

Copy link
Contributor

mattrjacobs commented Aug 11, 2016

That implementation would, I think, fix the error you're seeing. It wouldn't do any caching, though, so it's not the correct solution.

Before you go on, you should take a moment to read the linked Wiki and make sure that request-caching is appropriate for your use case. Request-caching assumes that you've got a well-defined request-scope (a web-server request is a common example). In that request, request-caching will de-duplicate the work of executing multiple commands with the same cache key. The 2nd-nth commands will all get the result of the first.

A fairly common case is running a servlet-based web server, so you can see the hystrix-request-context module for an example of how to add request-scoping to a servlet-based web server

@mukteshkrmishra

This comment has been minimized.

Copy link

mukteshkrmishra commented Aug 11, 2016

:+1 for Matt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment