skip to Main Content

I am using java boot for my development. For now I have used ‘EhCache’ for caching , it is directly supported from Java boot. This is “in-process” cache, i.e., becomes part of your process. It is okay for now. But my server will run on multiple nodes in near future. Hence want to switch to ‘Memcached’ as common caching layer.

After spending good amount of time, I could not get good sample of using Memcached from java boot. I have looked at ‘Simple Spring Memcached‘ which comes close to my requirement. But still it gives example using XML configuration in Spring way. Java boot does not use such XML configuration as far as possible. At least I could not map the example quickly to java boot world.

I want to use Memcahed ( directly or via cache-abstraction-layer) from java boot. If anybody points me to a relevant java boot example, it will save a lot of time for me.

3

Answers


  1. Chosen as BEST ANSWER

    I have already accepted answer given by @ragnor. But I think I should post a complete example here which has worked for me.

    1. Make sure you have cache-enabled for your application by adding @EnableCaching
    2. POM.xml should have following dependency:
    <dependency>
            <groupId>com.google.code.simple-spring-memcached</groupId>
            <artifactId>spring-cache</artifactId>
            <version>3.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.simple-spring-memcached</groupId>
            <artifactId>spymemcached-provider</artifactId>
            <version>3.6.1</version>
        </dependency>
    
    1. Add a config file to configure your memcached cache configuration, say MySSMConfig.java
    @Configuration
    @EnableAspectJAutoProxy
    @ImportResource("simplesm-context.xml") // This line may or may not be needed,
                                            // not sure
    public class SSMConfig 
    {
        private String _memcachedHost; //Machine where memcached is running
        private int _memcachedPort;    //Port on which memcached is running
    
         @Bean
         public CacheManager cacheManager() 
         {
             //Extended manager used as it will give custom-expiry value facility in future if needed
             ExtendedSSMCacheManager ssmCacheManager = new ExtendedSSMCacheManager();
    
             //We can create more than one cache, hence list
             List<SSMCache>cacheList = new ArrayList<SSMCache>();
    
             //First cache: Testcache
             SSMCache testCache = createNewCache(_memcachedHost, _memcachedPort, 
                                        "testcache", 5);
    
             //One more dummy cache
             SSMCache dummyCache = createNewCache(_memcachedHost,_memcachedPort, 
                        "dummycache", 300);
    
             cacheList.add(testCache);
             cacheList.add(dummyCache);
    
             //Adding cache list to cache manager
             ssmCacheManager.setCaches(cacheList);
    
             return ssmCacheManager;
         }
    
    
        //expiryTimeInSeconds: time(in seconds) after which a given element will expire
        //
        private SSMCache createNewCache(String memcachedServer, int port, 
                                    String cacheName, int expiryTimeInSeconds)
        {
            //Basic client factory to be used. This is SpyMemcached for now.
            MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl();
    
            //Memcached server address parameters
            //"127.0.0.1:11211"
            String serverAddressStr = memcachedServer + ":" + String.valueOf(port);
            AddressProvider addressProvider = new DefaultAddressProvider(serverAddressStr);
    
            //Basic configuration object
            CacheConfiguration cacheConfigToUse = getNewCacheConfiguration();
    
            //Create cache factory
            CacheFactory cacheFactory = new CacheFactory();
            cacheFactory.setCacheName(cacheName);
            cacheFactory.setCacheClientFactory(cacheClientFactory);
            cacheFactory.setAddressProvider(addressProvider);
            cacheFactory.setConfiguration(cacheConfigToUse);
    
            //Get Cache object
            Cache object = null;
            try {
                object = cacheFactory.getObject();
            } catch (Exception e) {
    
            }
    
            //allow/disallow remove all entries from this cache!!
            boolean allowClearFlag = false;
            SSMCache ssmCache = new SSMCache(object, expiryTimeInSeconds, allowClearFlag); 
    
            return ssmCache;
    
        }
    
        private CacheConfiguration getNewCacheConfiguration() 
        {
            CacheConfiguration ssmCacheConfiguration = new CacheConfiguration();
            ssmCacheConfiguration.setConsistentHashing(true);
            //ssmCacheConfiguration.setUseBinaryProtocol(true);
            return ssmCacheConfiguration;
        }
    
    }
    
    1. OK, we are ready to use our configured cache.
    2. Sample methods in some other class to read from cache and to remove from cache
    @Cacheable(value="dummycache, key="#givenId.concat('-dmy')", unless="#result == null")
        public String getDummyDataFromMemCached(String givenId)
        {
            logger.warn("getDummyDataFromMemCached: Inside DUMMY method to actually get data");
            return "Sample-" + String.valueOf(givenId);
        }
        @CacheEvict(value="dummycache",key="#givenId.concat('-dmy')")
        public void removeDummyDataFromMemCached(String givenId)
        {
            //Do nothing
            return;
        }
    
    1. Note that we have added suffix to the kache-keys. As Memcached does not support cache-zones, "dummycache" and "testcache" ultimately does not remain separate on a single server. (They may remain separate with some other cache implementation). Hence to avoid conflict, we append unique suffix to the cache-key.

    2. If you want to cache objects of your own class, then make sure that they are serializable. Just change your class definition to 'XYZ implements Serializable'.


  2. You can find some materials how to configure SSM using Java configuration instead of XML files here and here.
    Basically you have to move definitions of all beans from XML to Java.

    Login or Signup to reply.
  3. You could also check Memcached Spring Boot library. It uses Memcached implementation for Spring Cache Abstraction.

    In other words you use the same configuration and same annotations as you would use with any other Spring Cache implementation. You can check out here the usage of the library.

    There are also example projects in Kotlin and Java.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search