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

Thursday, December 23, 2010

Spring MVC ModelAttribute and BindingResult

The Problem:

I am using Spring 3 MVC and I encountered the following error upon form submission:

org.springframework.validation.BindException type mismatch

In my controller I defined the following 2 model attributes:

        model.addAttribute("gene",gene);        
        model.addAttribute("renameAllele", ra);

Upon form submission, I wanted to bind the ModelAttribute to my method arguments as follows:

    @RequestMapping(value="/renameAllele/submit", method=RequestMethod.POST)
    public String submit(@ModelAttribute("renameAllele") @Valid final RenameAllele ra, BindingResult alleleBindingResult, 
            @ModelAttribute("gene") RenameGene gene, SessionStatus status ) {

This method signature didn't work because for every ModelAttribute added, we need to have a corresponding BindingResult argument as well. As you can see above, the ModelAttribute("gene") did not have a corresponding BindingResult.

Solution

To get it working, I changed the method signature as follows:

    @RequestMapping(value="/renameAllele/submit", method=RequestMethod.POST)
    public String submit(@ModelAttribute("renameAllele") @Valid final RenameAllele ra, BindingResult alleleBindingResult, 
            @ModelAttribute("gene") RenameGene gene, BindingResult geneBindingResult, 
            SessionStatus status ) {

I figured this out by reading the spring reference documentation. Here is a quote taken from their site:
"The Errors or BindingResult parameters have to follow the model object that is being bound immediately as the method signature might have more that one model object and Spring will create a separate BindingResult instance for each of them so the following sample won't work:"
Reference: http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html

Tuesday, December 21, 2010

styling tables made easy with DataTables jQuery plugin

In the past I've usually formatted results into a table using 'zebra' styling where each alternating row would be shaded with a different background color. Below is an example:




Typically the JSP would look as follows:


<table cellspacing="0" class="tracker-summaries">
    <tr>
        <th>Procedure</th>
        <th class="right-col">Version</th>
        <th class="right-col">Date added</th>
        <th class="right-col">Filename</th>
        <th class="right-col">&nbsp;</th>
    </tr>
    
    <c:set var="rownum" value="0" />    
<c:forEach items="${procedures}" var="procedure" >
                
        <c:set var="rownum" value="${rownum + 1}" />
        <tr <c:if test="${rownum mod 2 == 1 }">class="odd"</c:if>>
            
            <td>${procedure.type.value }</td>
            <td class="right-col">${procedure.version }</td>
            <td class="right-col">
                <c:if test="${not empty procedure.dateCreated}">
                    <fmt:formatDate pattern="dd/MM/yyyy" value="${procedure.dateCreated}" />
                </c:if>
            </td>    
            <td class="right-col">                
                ${ procedure.filename }
            </td>
            <td class="right-col">
                <a href='<c:url value="/inventory/inventoryDocDownload.html" />?<%= ParamNames.TYPE %>=<%=InventoryDocDownloadController.TYPE_PROCEDURE%>&id=${procedure.id}'>Download</a>
            </td>
        </tr>    
            </c:forEach>

</table>

As highlighted in red, I would manually assign each alternating row a different style to achieve the 'zebra' look and feel. This worked fine, but it became quite repetitive when you have multiple pages listing results in tables.

I recently, discovered a much better solution without having to customize each JSP that contained tabular results, using a jQuery plugin called DataTables

It's really quite simple. You create your tables without any styling attached. Then invoke a few lines of jQuery code to apply styling dynamically as follows:


    <script type="text/javascript">

        $(document).ready(function() {
            oTable = $('table.display').dataTable({
                "bJQueryUI": true,
                "bPaginate": false,
                "bLengthChange" : false,
                "bFilter" : false                            
            });

            $(".ui-toolbar:first").css('display','none');            
        } );        
    
    </script>

If you can apply this to every header to of your page, then all your pages will automatically have their tables properly formatted.

Furthermore, your tables will automatically have sorting, searching and pagination built-in.