# Reference service for a cache

I'm using JDK 11.

This is my code:

public class ReferenceService {

private final transient Cache<String, Reference> cache;
private final transient EntityManager entityManager;

public ReferenceService(
Cache<String,Reference> cache,
EntityManager entityManager
) {
this.cache = cache;
this.entityManager = entityManager;
}

public Optional<Reference> get(String id) {
return Optional.ofNullable(this.cache.get(id))
.or(() -> Optional.ofNullable(this.entityManager.find(Reference.class, id)));
}
}


I would like to know to write this code again in order to it's more elegant:

return Optional.ofNullable(this.cache.get(id))
.or(() -> Optional.ofNullable(this.entityManager.find(Reference.class, id)));


I guess I'm using too much Optional.ofNullable each time I need to get a reference from cache or from persistence layer.

private <T> Cache<String, T> getOrCreateCache(String name, Class<T> type) {
Cache<String, T> cache = cacheManager.getCache(name, String.class, type);

if (cache == null) {
CompleteConfiguration<String, T> config =
new MutableConfiguration<String, T>()
.setTypes(String.class, type);

cache = cacheManager.createCache(name, config);
}

return cache;
}

• I've updated my answer now. I hope that answers your questions Feb 8 '19 at 17:28

### Design Fix

The correct solution to this is to make your cache responsible for retrieving the entity on cache-miss.

Consider for a moment the goals of a cache:

• Keep expensive to calculate / retrieve information in a manner suitable to quick access
• Abstract away cache handling (invalidation, cache-misses, ...) from consumers
• Give certain guarantees for the consistency of cached information

As it stands the way this code is setting up and using the cache utterly fails on the second point. Luckily javax.caching.Cache does support loading entries into the cache on misses using a CacheLoader.

For this to happen you need to create a CacheLoader that is aware of the EntityManager used to access the entities:

[..] config = new MutableConfiguration<String, T>()
.setTypes(String.class, type)
new CacheLoader<String, T>() {
@Override
public T load(String key) {
return entityManager.find(type, key);
}
@Override
public Map<String, T> loadAll(Iterable<? extends String> keys) {
return Stream.of(keys)

You should notice at this point that you're locking yourself into caching on a single primary key (namely String). This is something that might bite you in the backside down the road, but if you only use Strings as primary keys for entities that should be alright.
• Could I ask you for giving some lights me about why it's a better practice a ClassLoader is aware of handling the entityManager or whatever data-access layer? I mean, my straightforward first approach was to try to get the entity from cache, and at the same method on service layer, try to get it using the entity manager. I guess, it's better to use a ClassLoader approach instead of, but I don't quite figure out how come. Feb 11 '19 at 9:53
• Not ClassLoader, CacheLoader. It's better practice, because it makes sure the Cache is filled correctly. It also allows you to build on the abstraction that a Cache exposes to you. That way your code doesn't need to care about the peculiarities of the cache mechanic. Feb 11 '19 at 13:15
• I'm struggling with an issue related with this behavior. Guess on a create(dto), shere dto has no an id field. So, when I call the cache.putIfAbsent(key??, dto), with key hould I use if it's not resolved until it's written on db. I hope I've explained so well. Feb 11 '19 at 14:33