Thursday, January 27, 2011

EhCache integration with Spring

Previously I've used EhCache several times in applications where we would manage and retrieve cached items within our code. For example to store a cached item we may see the following:

cache.put(new Element(key, value));

And to get a cached item we may do the following:

            Element element = cache.get(key);
            if (null != element) {
                return element.getObjectValue();
            }

On top of that we need to manage the caches using code similar to the following:
            manager.addCache(name);
            cache = manager.getCache(name);


Several times I've asked myself 'Wouldn't it be nice if the caching mechanims were more transparent?". Caching is one of those "behind the scenes" type of operations and I never did felt comfortable putting it into our application code even if we layered it properly in multiple service tiers.

Today, I learned of EhCache and spring integration which was so easy to setup with little or no cache management. The idea is quite simple: Cache the results returned from method calls.

Here's an example of how you would declare that the results of a method be cacheable:

    @Cacheable(cacheName="mustererMouseObservations")    public Mouse getMouseObservations(String barcode) throws MustererException;

It automatically creates a cache called "mustererMouseObservations" and stores the returned result. Next time the method is invoked with the same arguments, the object returned is taken from the cache!

To declare the ehcache annotations, add the following to the spring bean wiring file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
    
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring        http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.0.xsd"
        >

    <!-- Scans the classpath of this application for @Components to deploy as beans -->
    <context:component-scan base-package="au.org.australianphenomics" />
    <!-- Caching of Spring Method results -->
    <ehcache:annotation-driven create-missing-caches="true" cache-manager="ehCacheManager" />
    <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <!--property name="configLocation" value="classpath:META-INF/spring/ehcache.xml" /-->
    </bean>

If you're using Maven like I am you can add the dependency in your pom file:
        <!--  EhCache annotations -->
        <dependency>
          <groupId>com.googlecode.ehcache-spring-annotations</groupId>
          <artifactId>ehcache-spring-annotations</artifactId>
          <version>1.1.2</version>
        </dependency>

And that's it! There's no need to explicity add items to the cache, or retrieve from the cache. It's all done transparently!

Note:
Be aware that cacheable methods that are self-invocating a method on itself, are not cacheable as stated as follows:

Self-Invocation

Only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual cache interception at runtime even if the invoked method is marked with @Cacheable.


References:
http://code.google.com/p/ehcache-spring-annotations/
http://ehcache.org/recipes/spring-annotations.html
http://developers-blog.org/blog/default/2010/06/07/Caching-Example-with-Spring-Annotations-and-Ehcache
http://onjavahell.blogspot.com/2009/09/annotation-driven-caching-with-ehcache.html

Wednesday, January 26, 2011

JSTL duplication

I wanted to be able to traverse a Java HashMap using JSTL but at the same time I didn't want to display duplicate entries.

To do that with JSTL, I stored the list of already displayed records into a HashMap as follows:

                            <%-- Don't show duplicate gene names --%>
                            <%-- Already process Genes --%>
                            <jsp:useBean id="processed" class="java.util.HashMap" />                            <c:forEach items="${facs.genotypeTranslationErrors}" var="genotypeObservation" varStatus="errorCounter">
                                <c:if test="${empty processed[genotypeObservation.improperGeneName]}">
                                    <c:set target="${processed}" property="${genotypeObservation.improperGeneName}" value="${true}" />                            
                                    <p>
                                        Assay:                            
                                        <span class="errorHighlight">
                                            <strong>${genotypeObservation.improperGeneName}</strong>
                                        </span>
                                    </p>
                                </c:if>                                                
                            </c:forEach>

Reference: http://stackoverflow.com/questions/4517928/how-to-group-rows-with-duplicate-column-properties-in-a-jstl-cforeach

Sunday, January 16, 2011

CSRF Security Error

 This occurred when I combined DWR with Tomcat 7

To resolve this error edited the catalina_home/conf/context.xml

<Context useHttpOnly=”false”>



 Reference: http://redrata.com/2010/11/resolving-dwr-csrf-security-error-popups/#more-125

Tuesday, January 4, 2011

DataTables Date Sorting

If you're using DataTables found at http://www.datatables.net then you may find that date sorting might not be working as expected depending on the country you're coming from.

Data tables by default doesn't sort according to the following date format: dd/MM/yyyy
In order to get this working correctly, you can override the default implementation with the following code snippet:

        // Override default implementation for date sorting
        $.fn.dataTableExt.oSort['date-asc']  = function(a,b) {
            var ukDatea = a.split('/');
            var ukDateb = b.split('/');
            
            var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
            var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
            
            return ((x < y) ? -1 : ((x > y) ?  1 : 0));
        };

        $.fn.dataTableExt.oSort['date-desc'] = function(a,b) {
            var ukDatea = a.split('/');
            var ukDateb = b.split('/');
            
            var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
            var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;
            
            return ((x < y) ? 1 : ((x > y) ?  -1 : 0));
        };


Reference: http://datatables.net/forums/comments.php?DiscussionID=2467
Reference: http://datatables.net/forums/comments.php?DiscussionID=1178