javaspring-mvccachingproxyreddison

@Cacheable in DAO layer not being triggered (Spring/Reddis)


I am having trouble caching internal methods within my DAO layer while in Proxy mode.

I am aware that while in Proxy mode, only external method calls coming in through the proxy are intercepted. However,I want to avoid having to switch to AspectJ mode and was wondering if any other work arounds existed.

I am displaying my code below and am wondering what changes, if any, I can add to make this process work.

--Note I am using swagger to document my code

--Also note my code has been watered down....for obvious reasons

//Controller

@RestController
@Api(produces = "application/json", protocols = "https", tags =  "Securities", description = "Securities  information")
public class SecuritiesInfoController extends Controller {

private SecuritiesInfoManager _securitiesInfoManager = new SecuritiesInfoManager();

@RequestMapping(value = "/security", method = RequestMethod.GET)
    public List<SecuritiesInfo> getAll(){ 
   return _securitiesInfoManager.getAll(); 
    }
}

//Service

public class SecuritiesInfoManager extends Manager {

private SecuritiesInfoDAO _securitiesDAO = new SecuritiesInfoDAO();

public List<SecuritiesInfo> getAll() {
    return _securitiesDAO.getAll();
}
}

//DAO

public class SecuritiesInfoDAO extends DAO  {

private static String securitiesTable = "Securities";

@SecuritiesInfoDAOInterface

public List<SecuritiesInfo> getAll() {
 //Magic
}
    }

//Interface

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(cacheNames = "SecuritiesInfo",cacheManager="cacheManager",
keyGenerator="keyGenerator" )
public @interface SecuritiesInfoDAOInterface {

}

//CacheConfig

@Configuration
//@EnableCaching(mode = AdviceMode.PROXY)
@EnableCaching(proxyTargetClass = true)
//@EnableCaching

public class CacheConfig extends CachingConfigurerSupport {

@Bean
public SecuritiesInfoDAO myService() {
    // configure and return a class having @Cacheable methods
    return new SecuritiesInfoDAO();
}
  @Bean
  public JedisConnectionFactory redisConnectionFactory() {
    JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();

    // Defaults
    redisConnectionFactory.setHostName("Nope");
    redisConnectionFactory.setPort(LoL);
    System.out.println("IN CONNTECTION");
    redisConnectionFactory.setPassword("Please help me :)");
    return redisConnectionFactory;
  }


  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
      System.out.println("cf: "+cf.toString());
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    redisTemplate.setConnectionFactory(cf);
    return redisTemplate;
  }

  /*
  @Primary
  @Bean
  public RedisTemplate<String,ExpiringSession> redisTemplate2(RedisConnectionFactory connectionFactory) {
      RedisTemplate<String, ExpiringSession> template = new RedisTemplate<String, ExpiringSession>();

      template.setHashValueSerializer(new LdapFailAwareRedisObjectSerializer());

      template.setConnectionFactory(connectionFactory);
      return template;
  }
  */


  @Bean
  public CacheManager cacheManager(RedisTemplate<String, String> redisTemplate) {
      System.out.println("IN CACHE MANAGER");
    RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);

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

  @Bean
  public KeyGenerator keyGenerator() {
    return new KeyGenerator() {
      @Override
      public Object generate(Object o, Method method, Object... objects) {
        // This will generate a unique key of the class name, the method name,
        // and all method parameters appended.
        StringBuilder sb = new StringBuilder();
        sb.append(o.getClass().getName());
        sb.append(method.getName());
        for (Object obj : objects) {
          sb.append(obj.toString());
        }
        System.out.println(sb.toString());
        return sb.toString();
      }
    };
  }

Solution

  • So I figured out the answer. It turns out I wasn't implementing/instantiating the interface correctly.

    First I have to @Autowire my manager class in my controller. Then @autowire my interface class in my manager.

    For a more detailed solution, I am placing my revised code below.

    //Controller

    @RestController
    @Api(produces = "application/json", protocols = "https", tags =    "Securities", description = "Securities  information")
    public class SecuritiesInfoController extends Controller {
    
    @Autowired
    private SecuritiesInfoManager _securitiesInfoManager = new   SecuritiesInfoManager();
    
    @RequestMapping(value = "/security", method = RequestMethod.GET)
       public List<SecuritiesInfo> getAll(){ 
    return _securitiesInfoManager.getAll(); 
     }
    }
    

    //Service

    public class SecuritiesInfoManager extends Manager {
    
     @Autowired
        public void setSecuritiesInfoDAOInterface(SecuritiesInfoDAOInterface _securitiesInfoDAOInterface) {
            this._securitiesInfoDAOInterface = _securitiesInfoDAOInterface;
        }
    
    public List<SecuritiesInfo> getAll() {
    return _securitiesInfoDAOInterface.getAll();
     }
    }
    

    //DAO

    public class SecuritiesInfoDAO extends DAO implements SecuritiesInfoDAOInterface {
    
    private static String securitiesTable = "Securities";
    
    @Override
    
    public List<SecuritiesInfo> getAll() {
     //Magic
     }
    
    }
    

    //Interface

    public interface SecuritiesInfoDAOInterface {
        @Cacheable(cacheNames = "SecuritiesInfo",cacheManager="cacheManager", keyGenerator="keyGenerator" )
        List<SecuritiesInfo> getAll();
     }
    }
    

    //CacheConfig

    @Configuration
    @EnableCaching
    public class CacheConfig extends CachingConfigurerSupport {
    @Bean
    public SecuritiesInfoManager myService() {
        // configure and return a class having @Cacheable methods
        return new SecuritiesInfoManager();
     }
    //rest same as before
    }
    

    //WebConfig

    @Configuration
    @ComponentScan(basePackages = {"package name"})
    public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        AntPathMatcher matcher = new AntPathMatcher();
        matcher.setCaseSensitive(false);
        configurer.setPathMatcher(matcher);
      }
     }