0
votes

I'm using a Map container as the value in LoadingCache:

@Service
public class SlideCacheSpace {

    @Value("${value}")
    private int expire;

    private LoadingCache<Integer, ConcurrentHashMap<Point, Boolean>> loadingCache = CacheBuilder.newBuilder()
            .maximumSize(10000)
            .expireAfterWrite(expire, TimeUnit.SECONDS)
            .build(
                    new CacheLoader<Integer, ConcurrentHashMap<Point, Boolean>>() {
                        public ConcurrentHashMap<Point, Boolean> load(Integer key)  {
                            return new ConcurrentHashMap<>(5000);
                        }
                    });


    public boolean contains(int slug, Point point) {
        ConcurrentHashMap<Point, Boolean> points = loadingCache.getIfPresent(slug);
        if (points == null) {
            return false;
        }

        return points.contains(point);
    }

    public void put(int slug, Point point) throws ExecutionException {
        ConcurrentHashMap<Point, Boolean> points = loadingCache.get(slug);
        points.put(point, true);
    }

    public void delete(int slug) {
        loadingCache.invalidate(slug);
    }
}

The issue is my slideCacheSpace.put(key, val) method doesn't take any effect on the LoadingCache. After calling it, the LoadingCache doesn't load anything and is still empty (inspected size during debug). It remains empty no matter how many times the put method is called. The load method in the CacheLoader, however, does get called and every time a new Map container is returned. It seems that the LoadingCache just ignores the value it loads. The contains method never returns true.

I'm wondering how it could happen.

2
Debug and see what are the contents of loadingCache. For map view use loadingCache.asMap().Xaerxess

2 Answers

1
votes

The contains method never returns true is because the Point class doesn't implement hashCode/equals method correctly. Or you can try using String instead of Point, then the contains will return true.

0
votes

The cause is rather non-obvious. I'm constructing the laodingCache at class loading time, and the value injection hasn't completed. So the expire value is always 0. Simple fix:

@Value("${value}")
private int expire;
private LoadingCache<Integer, ConcurrentHashMap<Point, Boolean>> loadingCache;


    @PostConstruct
    public void init() {
        loadingCache = CacheBuilder.newBuilder()
                .maximumSize(5000)
                .expireAfterAccess(expire, TimeUnit.SECONDS)
                .build(new CacheLoader<Integer, ConcurrentHashMap<Point, Boolean>>() {
                    @Override
                    public ConcurrentHashMap<Point, Boolean> load(Integer key)   {
                        return new ConcurrentHashMap<>(2500);
                    }
                });
    }

The value injection should work as expected this way.