Pdrit
Pdrit

Reputation: 91

Using a Spring CacheManager from dependent jar

I have several WAR projects that include a dependency to a certain utility JAR project. I would like to be able to cache certain methods from the utility project by using spring's @Cacheable annotation, so I tried creating a configuration file on the utility project where I could define a CacheManager bean that could handle the caching of the methods. The configuration file looks like this:

(Note that I'm using a Redis caching implementation, but the spring config should be very similar for other caching providers)

@Configuration
@EnableCaching
public class RedisConfig {

    @Value("${redis.hostUrl}")
    private String hostUrl = null;

    @Value("${redis.port}")
    private Integer port = null;

    @Value("${redis.defaultExpiration}")
    private Integer defaultExpiration = null;


    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory = new JedisConnectionFactory();
        // Defaults
        redisConnectionFactory.setHostName(hostUrl);
        redisConnectionFactory.setPort(port);
        return redisConnectionFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(cf);
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(defaultExpiration);

        cacheManager.setUsePrefix(true);

        List<String> cacheNames = new ArrayList<String>();
        cacheNames.add("testing");
        cacheManager.setCacheNames(cacheNames);
        return cacheManager;
    }
}

I'm pretty sure the configuration itself is not a problem because I have similar configuration files in other WAR modules and caching works fine on those. However, since this is a JAR that gets loaded by other modules, my guess is that the CacheManager is not being picked up by Spring.

In project A, which has a dependency to the utils project, I have a method like the following (edited for simplicity; ignore the invalid syntax):

@RequestMapping(...)
@ResponseBody
public Dto methodA(...) {

    //The relevant part
    testCachedMethod(value);
    cachedMethodFromProjectB(value);

}

@Cacheable(value="testing")
public String testCachedMethod(String value) {
    return value;
}

Project B is another WAR that has its own CacheManager (not tied to utils), and has similar methods cached using @Cacheable. If I hit Project A's methodA, the caches from Project B get stored properly, but the cachedMethod from Project A does not store anything in the cache (and neither do the methods from the utils project annotated with @Cacheable). I also tried the other way around, creating the CacheManager directly on Project A, but it also fails to cache the annotated methods inside the utils project (and I'd prefer declaring the manager on the utils project so it can be reused by other modules).

I know Spring is properly initializing the beans in the utils project because project A fails to run if its context's property placeholder does not find the property files for the @Value annotations from the cache Config file. So I'd suppose the CacheManager bean is there, but somehow it doesn't work. Any ideas on what I'm doing wrong or if it's even possible to use a CacheManager from a dependent JAR (if possible, using Java configuration)? I'm using Spring 3.2.0.RELEASE.

Been trying to figure this out for a couple days now, so any help is greatly appreciated.

Upvotes: 1

Views: 2115

Answers (1)

Pdrit
Pdrit

Reputation: 91

Turned out to be an issue with the spring cache abstraction's default proxy mode. All the methods whose caching annotations were not working were being called by other methods within the same object. I can properly manipulate the caches from the dependent jar project using @Autowire on the CacheManager bean and manually performing the caching operations. While it should be possible to use the annotations by enabling the AspectJ weaving mode, I don't want to add more complexity by having to deal with the weaving in the dependent modules.

Upvotes: 2

Related Questions