crmepham
crmepham

Reputation: 4760

Spring Boot cache not caching method call based on dynamic controller parameter

I am attempting to use Spring Boot Cache with a Caffeine cacheManager.

I have injected a service class into a controller like this:

@RestController
@RequestMapping("property")
public class PropertyController {

    private final PropertyService propertyService;

    @Autowired
    public PropertyController(PropertyService propertyService) {
        this.propertyService = propertyService;
    }

    @PostMapping("get")
    public Property getPropertyByName(@RequestParam("name") String name) {
        return propertyService.get(name);
    }
}

and the PropertyService looks like this:

@CacheConfig(cacheNames = "property")
@Service
public class PropertyServiceImpl implements PropertyService {

    private final PropertyRepository propertyRepository;

    @Autowired
    public PropertyServiceImpl(PropertyRepository propertyRepository) {
        this.propertyRepository = propertyRepository;
    }
    
    @Override
    public Property get(@NonNull String name, @Nullable String entity, @Nullable Long entityId) {
        System.out.println("inside: " + name);
        return propertyRepository.findByNameAndEntityAndEntityId(name, entity, entityId);
    }

    @Cacheable
    @Override
    public Property get(@NonNull String name) {
        return get(name, null, null);
    }
}

Now, when I call the RestController get endpoint and supply a value for the name, every request ends up doing inside the method that should be getting cached.

However, if I call the controller get endpoint but pass a hardcoded String into the service class method, like this:

@PostMapping("get")
public Property getPropertyByName(@RequestParam("name") String name) {
    return propertyService.get("hardcoded");
}

Then the method is only invoked the first time, but not on subsequent calls.

What's going on here? Why is it not caching the method call when I supply a value dynamically?

Here is some configuration:

@Configuration
public class CacheConfiguration {

    @Bean
    public CacheManager cacheManager() {
        val caffeineCacheManager = new CaffeineCacheManager("property", "another");
        caffeineCacheManager.setCaffeine(caffeineCacheBuilder());
        return caffeineCacheManager;
    }

    public Caffeine<Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                .initialCapacity(200)
                .maximumSize(500)
                .weakKeys()
                .recordStats();
    }
}

Upvotes: 0

Views: 1036

Answers (1)

Shadov
Shadov

Reputation: 5591

2 solutions (they work for me):

  • remove .weakKeys()

  • propertyService.get(name.intern()) - wouldn't really do that, possibly a big cost

Sorry, but I don't have enough knowledge to explain this. Probably something to do with internal key representation by Caffeine.

Upvotes: 2

Related Questions