Showing posts with label caching. Show all posts
Showing posts with label caching. Show all posts

How to implement cache (LRU Cache) using LinkedHashMap in java

Recently i wanted to implement a simple Least recently used (LRU) cache in one my applications. But my use case is simple enough that instead of going for something ehcache i decided to build it on own by using java.util.LinkedHashMap
As you can see from the code its very simple. All you have to do is extend java.util.LinkedHashMap and override its protected removeEldestEntry() method so that it checks if the size of map is greater than a size you specified while creating the Map if yes remove the eldest entry
Now the question is when Map is full which entry will it remove, you have 2 options
  1. Eldest: If you just want to remove the first entry that you inserted in the Map when adding a new entry then in your constructor you could use super(cacheSize, 0.75f);, so LinkedHashMap wont keep track of when a particular entry were accessed.
  2. Least recently used (LRU): But if you want to make sure that the entry that was least recently used should be removed then call super(cacheSize, 0.75f, true); from constructor of your LRUCache so that LinkedHashMap keeps track of when entry was accessed and removes the Least recently used entry

Cache Manager Service

The Portal Server has following services that cache data to improver performance. Take a look at WebSphere Portal 6.1 Performance Tunig Guide for detailed information on how to tune these services

Navigator Service

The navigator service manages the content model for unauthenticated users, which controls the pages those users are able to see. This content model is periodically reloaded by WebSphere Portal; new pages which are visible to unauthenticated users will not be available until the next reload occurs.

This service also controls the HTTP cache-control headers which will be sent on unauthenticated pages

Registry Service
WebSphere Portal maintains information about many resource types in its databases. Some of these resources are replicated into memory for faster access; this is provided by the registry service. This replicated information will be periodically reloaded from the database, thus picking up any changes which may have been made on a peer node in a clustered environment.

The registry service holds information related to portlet defintion, portlet application definition, theme, skin, client.

Cache Manager Service

The Cache Manager Service is responsible for managing the different caches used in WebSphere Portal Version 6.1. It used to manage user Portal Access Control cache, Portal Environment Cache, Data Store, Portal User Management Cache. Take a look at WebSphere\wp_profile\PortalServer\config\CacheManagerService.properties file to find out what type of information is stored in this cache.

The portal provides two different types of caches: shared and non-shared.

Shared caches
The shared caches are cluster aware. This means that deleting an element from the cache on one cluster node results in deleting that element from the corresponding cache instances on all other nodes. This ensures that frequently changing data are kept consistent over the whole cluster installation.

Non-shared caches
The non-shared caches are used for data where cluster awareness is of no concern. This avoids unnecessary network communication overhead.

Caching portlet output

The Portlet Specification 2.0 as well as Portlet Specification 2.0 define how your portlet can request portlet container to cache its output.

The way it works is if you want portal container to cache output of your portlet then you can add expiration-cache element to your portlet.xml like this.

<expiration-cache>-1</expiration-cache>

Value of expiration cache means this to portal

  1. -1: Value of -1 tells portal server that the output of portlet never expires

  2. 0: Value of 0 is equivalent of not adding the expiration-cache element at all. It means that dont cache the output of the portlet.

  3. positive no.: Value of more than 0 means cache output of portlet for those many mil-seconds



If you set the expiration cache element for portlet then on the first request to portlet the portlet container will pass request to doView() method and cache its output. There after whenever portal server gets request it will return content from cache instead of passing control to doView() method of the portlet. The cache will get expired if either it is expired or you perform some action on the portlet. In that case the doView() method would get called again. Clicking on renderURL in the portlet does not result in doView() method being called again.

Please note that if you go to say either Edit or HELP mode of the portlet then the cache wont be discarded also content generated in doEdit() or doHelp() method does not get cached.

If you have cachemonitor.ear installed on your portal server then you can look at the content that is being cached like this.



I am using the SampleCachePortlet.war Portlet for testing fragment cache. This portlet writes time stamp when output was generated. As you can see the portal server is caching the output generated by portlet for every user under different entry.

You can use Cache Monitor to verify the cached content. This is a sample entry

/wps/PA_SampleCache/SampleCachePortlet:7_6RUKKSU31G8I602VFOAQ3710G3
/wps/PA_SampleCache/SampleCachePortlet:7_6RUKKSU31G8I602VFOAQ3710G3:sunil:text/html:en-AU, en;q=0.9, en-US;q=0.8:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7 (.NET CLR 3.5.30729):UTF-8:normal::UTF-8:requestType=GET
none 7_6RUKKSU31G8I602VFOAQ3710G3:sunil
None 1

As you can see the value of
Template: <urloftheportlet>:<portletinstanceid>
CacheId:<urloftheportlet>:<portletinstanceid>:<username>:<contenttype>
Timeout (seconds): Time when cache expires. It is saying none in our case because we set expiration-cache to -1
Dependency IDs: <portletinstanceid>:<username>

If you try accessing the portlet with different users then you will see one entry for each user. Now if you dont want that instead you want portal to cache output across users. Ex. Company news portlet should display same data to all the users then add value of cache-scope equal to public like this in portlet.xml


<cache-scope>public</cache-scope>


Once you do that portal will keep only one copy of the portlet output across the users, your cache entry will look like this in the cache monitor

/wps/PA_SampleCache/SampleCachePortlet:7_6RUKKSU31G8I602VFOAQ3710G3 /wps/PA_SampleCache/SampleCachePortlet:7_6RUKKSU31G8I602VFOAQ3710G3:public:text/html:en-US, en;q=0.9:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7 (.NET CLR 3.5.30729):UTF-8:normal::UTF-8:requestType=GET none 7_6RUKKSU31G8I602VFOAQ3710G3:public None 1


As you can see the Cache Id does not include userName this time instead it says public same thing with the dependencyId it says <portletinstanceid>:public.

Enabling Potlet Fragment caching

WebSphere Portal server can cache output of the portlet at either the application server level or at the remote proxy server. Portlet output caching is turned off by default so you will have to turn it on by following these steps


  1. Make sure that Dynamic Caching Service is enabled to server startup



  2. Enable the servlet caching using the WAS Admin console like this



  3. Now enable the Portlet Fragment caching using the WAS Admin Console like this


  4. Restart your WebSphere Portal server for these changes to take effect



Now if you deploy a portlet that asks WPS to cache its output then portal will do that.