-1

I'm using Google Guava Cache + Spring cache abstraction for caching purpose. I'm trying to make use of Guava's Loading Cache interface for the same.

I know Spring provides support for Guava Cache, but I was wondering whether I can make use of spring's cacheable annotation alongwith Loading Cache?

Basically I wanted to keep the business layer separate from the Cache.

Kindly help. Thanks.

Sandy
  • 459
  • 2
  • 6
  • 19

2 Answers2

1
  1. Guava Cache is deprecated. If you'd existing code, that'd be another matter, but for new code, use Caffeine.

  2. Put a @Cacheable("myCacheName") on the method that you want to cache the return value for.

  3. Put a @EnableCaching on your application class if using Spring Boot, otherwise on some @Configuration class.

  4. Set the spec in application.properties if using Spring Boot, like so: spring.cache.caffeine.spec=maximumSize=10000,expireAfterWrite=5m. If not using Boot, use @PropertySources annotation on the same class as in #3 above.

  5. Add org.springframework.boot:spring-boot-starter-cache and com.github.ben-manes.caffeine:caffeine to your build file. If not using Boot, you'll need to set up the dependencies differently.

You're done.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
0

So you want both butter and jam. Okay. I will help you use loading cache along with keeping caching logic separate.

Consider you have a service class SampleServiceImpl which implements SampleService interface.

Service interface:

public interface SampleService {
    User getUser(int id);
}

Service Implementation:

@Service
public class SampleServiceImpl implements SampleService {

    public User getUser(int id) {
        // fetch user from database
        return user;
    }
}

Create one more class SampleServiceCache

public class SampleServiceCache extends ServiceCacheImpl {

    @Autowired
    public SampleServiceCache(int expiryTime, int maximumSize) {

        loadingCache =
                CacheBuilder.newBuilder().maximumSize(maximumSize).expireAfterAccess(expiryTime, TimeUnit.HOURS).build(
                        new CacheLoader<Integer, User>() {

                            @Override
                            public User load(@Nonnull Integer userId) {
                                return SampleServiceCache.super.getUser(userId);
                            }
                        });
    }
    @Override
    public User getUser(int userId) {
        return loadingCache.getUnchecked(userId);
    }
}

In you bean config:

@Bean
public SampleService sampleService() {
    return new SampleServiceCache(expiry, maxSize);
}

The day you want to remove cache, you have to do two things:
1. Remove the cache class.
2. Change bean config to return actual implementation object rather than cache implementation object.

P.S. You can define multiple loading caches for different behaviors say user retrieval, article retrieval, etc.

rohanagarwal
  • 771
  • 9
  • 30
  • 1
    This has nothing to do with Spring Cache abstraction. – Abhijit Sarkar Jul 07 '17 at 21:31
  • You can not decouple the code if you use @Cacheable. And hence you won't be able to take benefits from loading cache – rohanagarwal Jul 07 '17 at 21:32
  • 1
    I don't think you know what decouple means. – Abhijit Sarkar Jul 07 '17 at 21:33
  • @cacheable handles caching declaratively. So, there is no way you can use Cacheable annotation with loading cache. You can post an answer if you think there is one – rohanagarwal Jul 07 '17 at 21:34
  • also cacheable starts giving pain too early, you will have to use aspectj if you want to cache calls within same class(AOP), complicated spells to generate key, storing cache names(they are compile time constants) – rohanagarwal Jul 07 '17 at 21:39
  • If you're paid by the hour, the above code would be fine. Otherwise, declarative caching, preferably using JCache, is the way to go. Calls within same class is not a caching issue, and you don't need AspectJ for that. See [this](https://stackoverflow.com/a/44961611/839733) – Abhijit Sarkar Jul 07 '17 at 21:47
  • why use hackish ways when there are cleaner ways – rohanagarwal Jul 08 '17 at 08:11
  • would love to see some code from you(would get to learn), pros of jcache(& declarative caching) over loading cache, btw google does provide guava cache(deprecated, now use caffeine instead) that fits into this declarative model. But just think why have they created loading cache. – rohanagarwal Jul 08 '17 at 08:27