In modern web applications scalability could be one of things that you have to take under consideration when you plan architecture and use of tools in your project. If you know that your application will be used by hundreds or even thousands of clients, your database will be very big and SQL/JDBC/ORM queries will be very tough for hard disk and CPU – consider using cache. Currently I have work with Memcached and Ehcache. While Memcached is written in C and works as a server, Ehcache is a pure java solution and could also work without need for standalone process. In this article I will show an example of using Ehcache.
Important: you must have following jars (or newer versions) in classpath:
ehcache-core-2.3.1.jar ehcache-terracotta-2.3.1.jar slf4j-api-1.5.11.jar slf4j-jdk14-1.5.11.jar
Consider the simple example:
import java.text.Format; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.config.CacheConfiguration; /** * Simple class that keeps article. */ class Article { public static final String CACHE_NAME = "articleCache"; private Integer id; private String text; private String author; public Article(Integer id, String text, String author) { this.id = id; this.author = author; this.text = text; } /** getters and setters are removed */ } public class EhcacheTest { private final Cache cache; /** * dynamic cache configuration * without using an xml file. */ public EhcacheTest() { CacheManager cacheManager = new CacheManager(); cacheManager.addCache(Article.CACHE_NAME); cache = cacheManager.getCache(Article.CACHE_NAME); // let's configure your cache! CacheConfiguration cacheConfiguration = cache .getCacheConfiguration(); cacheConfiguration.setMaxElementsInMemory(100); // after 30 seconds of creating element // will be marked as removed cacheConfiguration.setTimeToLiveSeconds(30); // if nothing uses key - the element // will be marked as removed after 15 seconds cacheConfiguration.setTimeToIdleSeconds(15); // LRU = Last Recently Used - when 100 elements already // in cache - removed will be last recently used one. cacheConfiguration.setMemoryStoreEvictionPolicy("LRU"); } /** * For need of example I assume that this * is very long database operation which * takes about 10 seconds ;) */ private Article getArticleFromDB(Integer id) throws Exception { System.out.println("!!!DB: article " + id); TimeUnit.SECONDS.sleep(10); return new Article(id, "some ehcache text", "author is codesmuggler"); } /** * Function for getting article. * First checks if it is already in cache - * if not - gets it from database and * places in cache */ public Article getArticle(Integer id) throws Exception { // class used for keeping element data Element element = null; // have you this an article in cache? if ((element = cache.get(id)) == null) { // you don't have an article in cache, // so you have to ask database // for it Article article = getArticleFromDB(id); element = new Element(id, article); cache.put(element); return article; } else { // you have an article in cache, // so just return the value! System.out.println("CACHE: article " + id); return (Article) element.getObjectValue(); } } public static void main(String[] args) throws Exception { EhcacheTest ehcacheTest = new EhcacheTest(); int i = 0; Format formatter = new SimpleDateFormat("HH:mm:ss"); while (i++ < 5) { System.out.println("TRY: " + i + " TIME: " + formatter.format(new Date())); Article art = ehcacheTest.getArticle(7); System.out.println("GOT ARTICLE: " + art.getId() + " TIME: " + formatter.format(new Date())); // sleep to allow cache to knock out an article key TimeUnit.SECONDS.sleep(10); } } }
An example prints:
TRY: 1 TIME: 22:20:20 !!!DB: article 7 GOT ARTICLE: 7 TIME: 22:20:30 TRY: 2 TIME: 22:20:40 CACHE: article 7 GOT ARTICLE: 7 TIME: 22:20:40 TRY: 3 TIME: 22:20:50 CACHE: article 7 GOT ARTICLE: 7 TIME: 22:20:50 TRY: 4 TIME: 22:21:00 !!!DB: article 7 GOT ARTICLE: 7 TIME: 22:21:10 TRY: 5 TIME: 22:21:20 CACHE: article 7 GOT ARTICLE: 7 TIME: 22:21:20
As you see on 5 tries database operation is executed only 2 times, which saves 30 seconds of database engine execution! Moreover, you can configure ehcache whatever you like. You may also use an XML file for it – but configuration options are the topic for another article.
Using cache for your application – if well configured – can cut off execution time of clients requests. However, in small applications can be an overkill.