0

I would like to cache getText method and update cache on setText. By now cache on getText method works, but I can not update value. Code below is base on tutorial from Hazelcast.

@Service
public class SlowService {

    String text = "Initial value";

    @Cacheable("text")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(value = "text", key = "#newText + 1")
    public String setText(String newText) {
        text = newText;
        return text;
    }
}

How to improve code above to make @CachePut annotation work?

EDIT: Tried adding same keys:

@Cacheable(value = "text", key = "#someKey")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(key = "#someKey")
    public String setText(String newText) {
        text = newText;
        return text;
    }

But getting:

java.lang.IllegalArgumentException: Null key returned for cache operation (maybe you are using named params on classes without debug info?) Builder[public java.lang.String com.example.demo.SlowService.getText()] caches=[text] | key='#someKey' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

Bartek
  • 2,109
  • 6
  • 29
  • 40
  • Why should it. The keys for the cache differ, so the `getText` never sees the cached instance. – M. Deinum Mar 11 '19 at 09:25
  • Ok, but I followed the tutorial, which I linked. They used key `key = "#newText + 1"` – Bartek Mar 11 '19 at 09:32
  • Tutorial is wrong. You cannot have 2 methods, different chache keys and expect it to work. Another problem with this is that the old values never get cleared (unless there is a timeout on the cache time). – M. Deinum Mar 11 '19 at 09:33
  • So, how to achieve update logic with one method? For me it seems that I need two methods, am I wrong? – Bartek Mar 11 '19 at 09:40
  • The only thing you need to do is to make sure the cache key is the same for the `get` and the `set` method. They currently aren't. – M. Deinum Mar 11 '19 at 09:41

2 Answers2

0

You need to make sure the value that you're caching in the cache is referenced by the same key as in when you are using the cache put.

For example:

Say you're caching text "Hello world" with the key "hw". Your cache would hold a key "hw" with the value "Hello world".

Now say you want to update the value with the "hw" key to some other text. For that, you need to make sure the key you pass in is the same as the one you passed it to cache that instance, which would be "hw" in that case.

That way, the key "hw" would hold an updated value with it.

@Cacheable(value = "text", key = "hw")
public String getText() {
    try {
        TimeUnit.SECONDS.sleep(2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return text;
}

@CachePut(key = "hw")
public String setText(String newText) {
    text = newText;
    return text;
}
0

The problem was with key naming, string name should be enclosed by ', hint. Below working code.

@Service
public class SlowService {

    String text = "Initial value";

    @Cacheable(value = "text", key = "'someKey'")
    public String getText() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return text;
    }

    @CachePut(value = "text", key = "'someKey'")
    public String setText(String newText) {
        text = newText;
        return text;
    }
}
Bartek
  • 2,109
  • 6
  • 29
  • 40