NRA
NRA

Reputation: 937

REST service based on Spring boot , spring caching with hazelcast failing to handle cache error

I am using Spring boot and hazelcast for my REST service for caching.

I am caching at service layer (API) using spring @Cachable annotation with custom key generator. Every thing works fine except when it throws RuntimeException from custom key generator function it is not handled by custom error class which I have added to handle error scenario.

The custom error class (CacheErrorHandler) that extends org.springframework.cache.annotation.CachingConfigurerSupport overrides all methods to handle GET,PUT,EVICT errors.

In my case I am expecting it to break into handleCacheGetError function if the custom customKeyGenerator throw RuntimeException.

Can any body point me what I am missing here or help to explain is the right way to handle caching error for cache (like HAZELCAST or REDIS etc) with spring annotation (i.e. using @Cachable).

As sample , here is what my API caching looks like

@Cacheable(cacheNames = "TestCache",keyGenerator = "customKeyGenerator")
public Response getAPIResponse(Integer param1){
...
}

Similarly , my cache configuration class which extends CachingConfigurerSupport, looks like this

@Configuration
public class CacheConfiguration extends CachingConfigurerSupport {
...

@Override
    public CacheErrorHandler errorHandler() {
        return new CustomHZCacheErrorHandler();
    }
...
}

Here CustomHZCacheErrorHandler looks like

public class CustomHZCacheErrorHandler implements CacheErrorHandler {
    private static final Logger logger = LoggerFactory.getLogger(CustomHZCacheErrorHandler.class);

    public CustomHZCacheErrorHandler() {
    }

    public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
        logger.warn("Error while getting cache " + cache.getName() + " for Key " + key);
    }

    public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
        logger.warn("Error while putting cache " + cache.getName() + " for Key " + key);
    }

    public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
        logger.warn("Error while evicting cache " + cache.getName() + " for Key " + key);
    }

    public void handleCacheClearError(RuntimeException exception, Cache cache) {
        logger.warn("Error while clearing cache " + cache.getName());
    }
}

Upvotes: 0

Views: 1360

Answers (1)

Gokhan Oner
Gokhan Oner

Reputation: 3257

@NRA, according to Spring Doc, https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/interceptor/CacheErrorHandler.html, CacheErrorHandler used only exceptions thrown by the cache provider, nothing else. Not for Key Generator or not even for the exceptions thrown by the annotated method.

Please see: https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/cache/interceptor/AbstractCacheInvoker.java#L71

For MVC Controller, Spring has an annotation to help you handle errors: @ErrorHandler. You can find more details here: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

If not using MVC, you can define an Aspect Bean & handle all errors for that method/class/package. The trick is, KeyGenerator called using an interceptor, before the method, so you need to put an aspect to that KeyGenerator class as well to catch it.

Please see this working example: https://gist.github.com/gokhanoner/026c2b90fe3a61b93626383a61932395

Note: I didn't test throwing exception from Cache provider side, you most probably need to define CacheErrorHandler as well for that part.

Upvotes: 1

Related Questions