Search code examples
javarestspring-mvcehcache

How to Cache a Method with two parameters in Spring-Mvc


I want to convert transactions's amount fields to another currency and I decided to use cache mechanism with @Cacheable annotations. In this cacheable method, I call an rest api method to get currency rate. According to I am setting caching period to 60 seconds and always send same parameters, program executes cacheable methods scope for each coming transactions.

I want to see logs for every minutes or calling different parameter, I used log.error() because of this.

CurrencyConverterService.java

@Service
public class CurrencyConverterService {
    private Logger log = LogManager.getLogger(CurrencyConverterService.class);
    @Autowired
    private ICurrencyService currencyService;

    int counter=0;

    @Cacheable(value = "allCurrency")
    public Float getCurrencyRate(String targetCurrCode, String baseCurrCode){
        log.error("getCurrencyRate called " +targetCurrCode +" - "+baseCurrCode+" - counter "+ counter+" Times");
        counter++;
        Float rate = currencyService.calculateParity(targetCurrCode, baseCurrCode);
        return rate;
    }

    public BigDecimal currencyConverter(Object value, String targetCurrCode, String baseCurrCode){
        float rate;

        if (baseCurrCode.equals(targetCurrCode)){
            rate = 1.0f;
        }else{
            rate = getCurrencyRate(targetCurrCode, baseCurrCode);
        }
        return ((BigDecimal)value).multiply(new BigDecimal(rate));
    }
}

Demo.java

@Service
public class Demo{
    @Autowired
    public ApplicationContext appContext;
    public CurrencyConverterService currencyConverterService;

    public void getCurrencyFromAPI(Object value, String targetCurrCode, String baseCurrCode){
        ....
        currencyConverterService = (CurrencyConverterService) appContext.getBean("currencyConverterService");
        currencyConverterService.currencyConverter(value, targetCurrCode, baseCurrCode);
        ....

    }
}

ehcache.xml

<ehcache
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
        updateCheck="false" monitoring="off" dynamicConfig="true">

    <diskStore path="java.io.tmpdir"/>

    <cache
            name="allCurrency"
            eternal="false"
            maxElementsInMemory="200"
            maxElementsOnDisk="10000"
            timeToIdleSeconds="600"
            timeToLiveSeconds="600"
            overflowToDisk="true"
            diskExpiryThreadIntervalSeconds="86400"
            memoryStoreEvictionPolicy="LFU"/>
</ehcache>

If I send 1000 transactions in four minutes. I see outputs below;

getCurrencyRate calleddd EUR-USD - counter 1 times
getCurrencyRate calleddd EUR-USD - counter 2 times
...
getCurrencyRate calleddd EUR-USD - counter 999 times
getCurrencyRate calleddd EUR-USD - counter 1000 times

but I want to see like below;

getCurrencyRate calleddd EUR-USD - counter 1 times
getCurrencyRate calleddd EUR-USD - counter 2 times
getCurrencyRate calleddd EUR-USD - counter 3 times
getCurrencyRate calleddd EUR-USD - counter 4 times

Thank you for your help.


Solution

  • I fixed this problem. If I call cached method from other methods in same class like above, does not work. If I call directly cached method from other classes, works properly. I should use like below;

    Demo.java

    @Service
    public class Demo{
        @Autowired
        public ApplicationContext appContext;
        public CurrencyConverterService currencyConverterService;
    
        public void getCurrencyFromAPI(Object value, String targetCurrCode, String baseCurrCode){
            ....
            currencyConverterService = (CurrencyConverterService) appContext.getBean("currencyConverterService");
            currencyConverter(value, targetCurrCode, baseCurrCode);
            ....
    
        }
    
        public BigDecimal currencyConverter(Object value, String targetCurrCode, String baseCurrCode){
            float rate;
    
            if (baseCurrCode.equals(targetCurrCode)){
                rate = 1.0f;
            }else{
                rate = currencyConverterService.getCurrencyRate(targetCurrCode, baseCurrCode);
            }
            return ((BigDecimal)value).multiply(new BigDecimal(rate));
        }
    
    }
    

    CurrencyConverterService.java

    @Service
    public class CurrencyConverterService {
        private Logger log = LogManager.getLogger(CurrencyConverterService.class);
        @Autowired
        private ICurrencyService currencyService;
    
        int counter=0;
    
        @Cacheable(value = "allCurrency")
        public Float getCurrencyRate(String targetCurrCode, String baseCurrCode){
            log.error("getCurrencyRate called " +targetCurrCode +" - "+baseCurrCode+" - counter "+ counter+" Times");
            counter++;
            Float rate = currencyService.calculateParity(targetCurrCode, baseCurrCode);
            return rate;
        }
    }