Nizamuddin
Nizamuddin

Reputation: 159

Spring boot Cache not working expected, returning existing records

I am using springBootVersion = 1.5.2.RELEASE and gradle version = 5.4.1.

I am passing token(consider an account) in request, There might be multiple channels associated to an account(requested token), I want to fetch all channels associated to request account and store them into List.

If user not perform any activity for 2 minutes for that user only Cache should be expired.

In order to fetch channelIds and store them into List, I have used Spring boot @Cacheable annotation but It is not working expected as it is fetching existing list data.

Please consider a dummy scenario to understand.

If I request token = 123, API fetching all channels associated this token and storing them into list which is fine.

but when I request token = 987 still API returning token = 123 channels, API supposed to return channels associated to token = 987

Here is code snippet

Main Spring Boot Runner Class

@SpringBootApplication
@EnableCaching
@ComponentScan(basePackages = { "some packages to scan" })
public class ChannelApiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ChannelApiApplication.class, args);
    }
}

UserController.java

@RestController
public class UserController {
public ResponseEntity<AccountsAssociatedChannels> getAccountsAssociatedChannels(
        @PathVariable Integer userId,
        @RequestHeader("Cookie") String btCookie,
        @RequestParam(value = "page", required = false, defaultValue = "1") int page,
        @RequestParam(value = "pageSize", required = false, defaultValue = "25") int pageSize,
        UriComponentsBuilder uriBuilder, HttpServletResponse response, HttpServletRequest request)
        throws Exception {
    try {
        List<AccountAssociatedChannels> accountResponse = userService.getAccountsAssociatedChannels(userId,
                btCookie, page, pageSize);

UserService.java

@Service
@Configurable
public class UserService {

@Autowired
ChannelServiceClient channelServiceClient;

public List<AccountAssociatedChannels> getAccountsAssociatedChannels(Integer userId, String btCookie, int page,
            int pageSize) throws Exception {

    // Calling Rest API to get channels associated to btCookie
    List<MyChannelResponse> myChannelResponse = channelServiceClient.getMyChannelResponse(btCookie, page,
            pageSize, null);

ChannelServiceClient.java

@Service
public class ChannelServiceClient {

    @Cacheable(value = "channelIds", key = "#root.args[0]")
    public List<MyChannelResponse> getMyChannelResponse(String btCookie, Integer page, Integer pageSize, String nextLinkURL)
            throws Exception {

        List<MyChannelResponse> channelIds = new ArrayList<>();

        // Fetch all channelIds associated user and store into list.
        while (true) {

            // invoke getChannels() method to get channels
            MyChannelResponses myChannelResponse = getChannels(btCookie, page, pageSize, nextLinkURL);
            List<PaginationLinks> links = myChannelResponse.getLinks();
            channelIds.addAll(myChannelResponse.getChannels());
            //Some logic
        }
    } // getMyChannelResponse() method close



    @Cacheable(value = "mychannel", key = "#root.args[0]")
    public MyChannelResponses getChannels(String btCookie, Integer page, Integer pageSize, String uri)
            throws Exception {
        try {
            log.debug("Entering Cookie: " + btCookie + " to get channels.");    
            // Calling Spring Boot Rest API to get channel associated btCookie

        } catch (Exception e) { 
            // throwing some exception
        }
    }// getChannels() method close
}       

Thank you.

Upvotes: 0

Views: 1410

Answers (2)

Nizamuddin
Nizamuddin

Reputation: 159

Below code clear cache for every 2 minutes

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.common.cache.CacheBuilder;

@Configuration
public class CacheConfiguration extends CachingConfigurerSupport {

    private static final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);

    @Bean
    @Override
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();

        log.info("cacheConfig");

        Cache getChannels = new ConcurrentMapCache("getChannels",
                CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.MINUTES).build().asMap(), false);

        cacheManager.setCaches(Arrays.asList(getChannels));

        return cacheManager;
    }

    @Override
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }

    @Override
    public CacheErrorHandler errorHandler() {
        return null;
    }

    @Override
    public CacheResolver cacheResolver() {
        return null;
    }

}

And Cacheable method will be

@Cacheable(value = "getChannels", key = "#btCookie", cacheManager="cacheManager")
    public List<MyChannelResponse> getMyChannelResponse(String btCookie, Integer page, Integer pageSize)
            throws Exception {

Upvotes: 0

Hemant
Hemant

Reputation: 1438

Change key in above code from both methods to this

@Cacheable(value = "mychannel", key = "#btCookie")

Upvotes: 2

Related Questions