Monday, February 4, 2013

Experimenting with MyBatis


iBATIS has been the workhorse for our data heavy applications for quite some time, and we were largely happy with it – till MyBatis took it to the next level. While iBATIS has been decommissioned circa mid 2010 (and now lives in the apache attic), the real trigger to move to see what MyBatis offered, was Spring’s decision to deprecate support for iBATIS in Spring 3.2.0.RELEASE and all of my DAO classes would show those pesky warnings in eclipse. Some time ago, we had a training on the nuances of iBATIS  in which we outlined a few examples. I thought that converting this same setup to MyBatis would be a good exercise to  see the features in action and how these two are similar and where they differ.
To start off, I fired up the migration tool viz ibatis2mybatis on my existing XML files in the previous setup. The tool is pretty decent and gets us almost 90% there. The major changes that still needed to be done were:
  1. Add namespacing to be consistent with mapper package name
  2. Changing of primary key attributes of a result map from <result> tag to <id> tag (needed for group by operations and performance optimizations)
  3. Strict ordering of elements in the resultMap tag so that <id/> is followed by <result/> followed by <association/> followed by <collection/> (not sure why the DTD has been defined thusly)
  4. Replace intermediate resultMap created for collections by providing the type information to the <collection/> tag itself. For an example see userWithLoginLocationsAndUniqueSites resultMap.
  5. Cache settings are not migrated and need to be defined by hand again. But that is extremely simple now — <cache/> and you have a cache local to the mapper!
After this, the only other changes were to the config file to disable the default lazyLoading. We prefer the objects to be POJO’s and also helps in reflective comparison of objects for hashCode and equals. Since we use mybatis-spring integration (provided by mybatis), we don’t need to deal with the SqlSesssionFactory ourselves (and hence worry about clean closing).
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="testerDataSource" />
        <property name="configLocation" value="classpath:com/kilo/dao/sqlmap-config.xml" />
        <property name="mapperLocations" value="classpath:com/kilo/dao/mapper/*.xml" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.kilo.dao.mapper" />
    </bean>
The mappers just need to be interfaces with the names of the methods matching the sql fragment that needs to be fired. Hence, no need for any DAOImpl’s whatsover! However, it has its downside as you may have already imagined – now you can’t craft fancy params to pass down to your mybatis sql fragment as parameters.
References:

Tuesday, January 29, 2013

CORS filters choices


Have you ever had to workaround Javascript’s Same origin policy and felt the need to take a shower with an industrial grade disinfectant immediately after? Well fear no more, as HTML5 to the rescue – CORS - Cross Origin Resource Sharing. Almost every conceivable hack that web developers used to do is being standardized as a feature spec in HTML5 and I thought CORS was a good feature. While there is good merit in the same origin policy, with the ubiquity of data vending servers that are being re-used in other data vending servers, there need to be a straight-forward solution to transitive data sharing. The workarounds of setting document.domain property, using JSONP or using crossdomain.xml (flex only) were not seamless. By making this a HTML5 spec and conveying it by means of headers, there is now, a definite method in the madness. This tutorial does a very good job of explaining nuances related to preflight, credentials (cookies) and caching policies along with all its usages via JQuery. The obvious concern of security has been aptly addressed in the following snip from the tutorial.

A WORD ABOUT SECURITY

While CORS lays the groundwork for making cross-domain requests, the CORS headers are not a substitute for sound security practices. You shouldn’t rely on the CORS header for securing resources on your site. Use the CORS headers to give the browser directions on cross-domain access, but use some other security mechanism, such as cookies or OAuth2, if you need additional security restrictions on your content.
What was missing was a good server side filter that will enable this for a typical java webapp. While the spec is pretty straight forward for the vanilla use cases, it quickly gets involved once we get into the details. There are two alternatives out there that I could find:
  1. com.thetransactioncompany.cors.CORSFilter
    1. Pros:
      1. Hugely popular
      2. Additional support for allowing subdomains in allow list
      3. Frequently updated for latest specs and bug fixes
      4. Liberal license (Apache)
    2. Cons:
      1. Not from a stable house
  2. org.eclipse.jetty.servlets.CrossOriginFilter
    1. Pros:
      1. From Jetty
      2. Liberal license (Eclipse)
    2. Cons:
      1. Not very popular
      2. May seem somewhat unintuitive if we use jetty related artifacts in a tomcat container environment
      3. Not aggressively updated
So, overall, it seems that the CORS filter from dzhuvinov is the winner, but would be happy to know if others feel differently.
References:

Monday, January 21, 2013

Some more fun with @Cacheable


Let's say we configure a cache for methods for a third-party service class that is not under your direct control via AOP (as discussed in the previous post).
    <cache:advice id="externalFibonacciCacheAdvice" cache-manager="externalConcurrentMapFibonacciCacheManager">
        <cache:caching>
            <cache:cacheable method="*" cache="externalConcurrentMapFibonacci" />
        </cache:caching>
    </cache:advice>
Now say that this class has another method similar to getFibonacci(int):long as getNonFibonacci(int):long which returns a non-fibonacci constant number of -1.
    /**
     * Constantly returns -1
     * 
     * @param index
     * @return
     */
    public long getNonFibonacci(int index) {
        return -1;
    }
Now, I will modify the driver as:
        long fibonacci = ((ExternalFibonacciServiceImpl) externalFibonacciService)
                .getFibonacci(45);
        LOG.info("Fibonacci number is " + fibonacci);
        long nonFibonacci = ((ExternalFibonacciServiceImpl) externalFibonacciService)
                .getNonFibonacci(45);
        LOG.info("Non-fibonacci number is " + nonFibonacci);
What is the output?
[ 2013-01-21 21:21:48,496 [main] driver.SpringCacheTesterDriver.main():36  INFO ]: Fibonacci number is 1836311903
[ 2013-01-21 21:21:48,501 [main] driver.SpringCacheTesterDriver.main():39  INFO ]: Non-fibonacci number is 1836311903
What the hell?! Further investigation led me to SPR-8933 where it seems that this was by design. The default key generator only takes the method arguments into account (which seems to make sense when you define your services close to your domain objects - but goes awfully awry when you have a facade service like ReferenceDataService which will vend out data like countries as well as currencies). 
Thankfully there is a workaround (and a nice way to introduce a feature) - enter key-generator. The default key generator implementation used is org.springframework.cache.interceptor.DefaultKeyGenerator. We can define a custom MethodAwareCacheKeyGenerator that extends the DefaultKeyGenerator and takes the method name also into account. Just beanify it and use it
    <bean id="methodAwareCacheKeyGenerator" class="org.springframework.cache.interceptor.MethodAwareCacheKeyGenerator" />

    <cache:advice id="externalFibonacciCacheAdvice" cache-manager="externalConcurrentMapFibonacciCacheManager"
        key-generator="methodAwareCacheKeyGenerator">
        <cache:caching>
            <cache:cacheable method="*" cache="externalConcurrentMapFibonacci" />
        </cache:caching>
    </cache:advice>
And voila...
[ 2013-01-21 21:40:17,419 [main] driver.SpringCacheTesterDriver.main():36  INFO ]: Fibonacci number is 1836311903
[ 2013-01-21 21:40:17,419 [main] driver.SpringCacheTesterDriver.main():39  INFO ]: Non-fibonacci number is -1
It is important to note that though the problem was demonstrated with the AOP route, it can also easily happen if you define it via annotations on methods having same datatypes.
References:
  • https://jira.springsource.org/browse/SPR-8933
  • Code available at https://github.com/kilokahn/spring-testers/tree/master/spring-cache-tester

Saturday, January 19, 2013

More fun with @Cacheable


I am assuming the audience has already got themselves familiar with the previous post where vanilla cache operations were demonstrated. The scope of this post will be:
  • Using multiple cache managers in a context
  • Using aspectj to cache self calls
  • Using cache:advice to cache non-owned calls
Using multiple cache managers in a context
So continuing from the fibonacci example from before, let's say that I wish to use both the simple cache manager as well as the ehcache cache manager? As with the pitfalls in using tx:annotation-driven, only one manager can effectively parade the annotations in the desired way. In tx:annotation-driven, we specify the transaction manager to use in the annotation itself, whereas such a thing is not available in the cache:annotation-driven (yet). Hence, when two cache managers wish to operate in tandem, enter org.springframework.cache.support.CompositeCacheManager. This specifies the list of cache managers that need to be used.
    <bean id="compositeCacheManager" class="org.springframework.cache.support.CompositeCacheManager">
        <property name="cacheManagers">
            <array>
                <ref bean="ehcacheManager" />
                <ref bean="concurrentMapCacheManager" />
            </array>
        </property>
    </bean>
The directive to process the annotation will refer to this compositeCacheManager as the sole manager
    <cache:annotation-driven cache-manager="compositeCacheManager" proxy-target-class="true"
        />
The output can be verified as showing each of the two cache managers operating without treading on each other's toes.
[ 2013-01-18 15:28:36,226 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$a3241f9a took 7.586 seconds
[ 2013-01-18 15:28:36,227 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$a3241f9a took 0.001 seconds
[ 2013-01-18 15:28:36,227 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$a3241f9a took 0.0 seconds
[ 2013-01-18 15:28:36,227 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 15:28:43,797 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$a3241f9a took 7.569 seconds
[ 2013-01-18 15:28:43,797 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 15:28:51,247 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$73a5e038 took 7.449 seconds
[ 2013-01-18 15:28:51,247 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$73a5e038 took 0.0 seconds
[ 2013-01-18 15:28:51,247 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$73a5e038 took 0.0 seconds
[ 2013-01-18 15:28:51,253 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal Ehcache flush
[ 2013-01-18 15:28:58,850 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$73a5e038 took 7.597 seconds
[ 2013-01-18 15:28:58,853 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal Ehcache flush
Using aspectj to cache self calls
Now let's get into some AspectJ magic! It would be worthwhile to spend a few minutes knowing how load time weaving (LTW) lends itself to processing annotations. There is anentire section in the Spring documentation that outlines the interactions in detail. In a nutshell, contrasting with the proxy based approach, the logic before/after/around a call is embedded in the bytecode of the class as the class is being loaded into the JVM. The JVM provides hook-ins via the java.lang.instrument.ClassFileTransformers route which can be configured per classloader. Since this logic is now part of the bytecode loaded in the JVM itself, any and all calls will have access to the logic coded for before/after/around calls. We will discover more as we take the tour. In our example for the concurrent map and ehcache based cached services, we were only storing the results for the fibonacci with index 45 and not the ones preceding it - and we gave the reason as the mode being proxy which doesn't support self calls (recursive or public/private/protected). Let's say we do want to achieve the benefits of the intermediate fetches as well, we should switch over to using the aspectj mode. Here are the set of steps you need to do and why:
Add maven dependencies for spring-aspects (which pulls in aspectj related jars)
        <!-- for mode aspectj -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
            <scope>runtime</scope>
        </dependency>
    <cache:annotation-driven cache-manager="compositeCacheManager" mode="aspectj" />
Informs Spring that we need to use aspectj for processing the annotations.
    <context:load-time-weaver/>
Inform spring to load time weave the bytecode for the beans that have been annotated. IMHO, specifying #2 should have automatically caused #3, but it is not - so we live with it.
-javaagent:/u/baigm/winnt/.m2/repository/org/springframework/spring-instrument/3.1.3.RELEASE/spring-instrument-3.1.3.RELEASE.jar
Specify the javaagent that will do the actual work of instrumenting the bytecode. From Java 5 onwards, java has built in support for agents that can help with instrumentation related activities which come out-of-the-box in most JEE containers. If you are not running in a JEE container (like Tomcat) or running a standalone java application, Spring provides a lightweight instrumentation jar that provides the implementation of a LoadTimeWeaver (viz. InstrumentationLoadTimeWeaver). So you need to add this to your launch configuration in your eclipse or to your invocation if outside eclipse.
And you are all set! Run the driver to see that the initial run itself now finishes in much under a second.
[ 2013-01-18 16:05:10,306 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.074 seconds
[ 2013-01-18 16:05:10,306 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 16:05:10,306 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 16:05:10,313 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 16:05:10,317 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.004 seconds
[ 2013-01-18 16:05:10,317 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 16:05:10,354 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.037 seconds
[ 2013-01-18 16:05:10,355 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.001 seconds
[ 2013-01-18 16:05:10,355 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 16:05:10,387 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal Ehcache flush
[ 2013-01-18 16:05:10,397 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.008 seconds
[ 2013-01-18 16:05:10,400 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal Ehcache flush
The call after the flush however returns faster than the first call - which may be due the the instrumentation stuff bootstrapping and subsequent calls reusing cached instrumented code.
Using cache:advice to cache non-owned calls
The annotation route is good when we are owning the services that need caching. If you don't own the services that vend out the data, you are forced to wrap it in a facade and place your annotation on this facade. The other route may be to use the cache:advice directive. This is similar to the tx:advice which we use to wrap calls around certain pointcuts based on fully qualified classnames, methods, arguments and argument types. So first off, we define a separate concurrent cache to be used for this external service.
    <bean id="externalConcurrentMapFibonacci"
        class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" />
    <bean id="externalConcurrentMapFibonacciCacheManager"
        class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <ref bean="externalConcurrentMapFibonacci" />
            </set>
        </property>
    </bean>
Then we define a cache advice (pointcut) with the cache manager to be used and defining which methods need to be cached and which backing cache store is to be used.
    <cache:advice id="externalFibonacciCacheAdvice" cache-manager="externalConcurrentMapFibonacciCacheManager">
        <cache:caching>
            <cache:cacheable method="*" cache="externalConcurrentMapFibonacci" />
        </cache:caching>
    </cache:advice>
Here we are asking Spring to cache all methods (via *) using the externalConcurrentMapFibonacciCacheManager cache manager and to use the externalConcurrentMapFibonacci cache as the underlying store.
    <aop:config proxy-target-class="true">
        <aop:pointcut id="externalFibonacciCacheOperation" expression="execution(* com.kilo.external..*.*(..))"/>
        <aop:advisor advice-ref="externalFibonacciCacheAdvice" pointcut-ref="externalFibonacciCacheOperation"/>
    </aop:config>
Now, we ask aop to to bind the pointcut to work on all beans of package com.kilo.external and use the advice defined before. We have to give the proxy-target-class="true" to use CGLIB based proxies (we can choose to use aspectj mode for reasons mentioned before).
You may verify the working via the output:
[ 2013-01-18 17:20:50,374 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.248 seconds
[ 2013-01-18 17:20:57,615 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.241 seconds
[ 2013-01-18 17:21:04,863 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.247 seconds
[ 2013-01-18 17:21:04,863 [main] driver.SimpletonFibonacciServiceImpl.flushFibonacciCache():27  INFO ]: No-op
[ 2013-01-18 17:21:12,119 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.255 seconds
[ 2013-01-18 17:21:12,119 [main] driver.SimpletonFibonacciServiceImpl.flushFibonacciCache():27  INFO ]: No-op
[ 2013-01-18 17:21:12,161 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.042 seconds
[ 2013-01-18 17:21:12,161 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 17:21:12,161 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 17:21:12,167 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 17:21:12,172 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl took 0.004 seconds
[ 2013-01-18 17:21:12,172 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 17:21:12,210 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.038 seconds
[ 2013-01-18 17:21:12,211 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 17:21:12,211 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.0 seconds
[ 2013-01-18 17:21:12,242 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal Ehcache flush
[ 2013-01-18 17:21:12,250 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl took 0.008 seconds
[ 2013-01-18 17:21:12,253 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache_aroundBody2():30  INFO ]: Royal Ehcache flush
[ 2013-01-18 17:21:19,873 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.external.ExternalFibonacciServiceImpl$$EnhancerByCGLIB$$6337baf took 7.62 seconds
[ 2013-01-18 17:21:19,874 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.external.ExternalFibonacciServiceImpl$$EnhancerByCGLIB$$6337baf took 0.0 seconds
[ 2013-01-18 17:21:19,874 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.external.ExternalFibonacciServiceImpl$$EnhancerByCGLIB$$6337baf took 0.0 seconds
[ 2013-01-18 17:21:19,874 [main] external.ExternalFibonacciServiceImpl.flushFibonacciCache():28  INFO ]: No-op
[ 2013-01-18 17:21:19,874 [main] driver.SpringCacheTesterDriver.doHeavyLifting():55  INFO ]: com.kilo.external.ExternalFibonacciServiceImpl$$EnhancerByCGLIB$$6337baf took 0.0 seconds
Hope this helps!
There is one gotcha with the cache mapping that I will try to cover in a new post.
References:
  • http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/aop.html#aop-aj-ltw
  • http://www.eclipse.org/aspectj/doc/released/devguide/ltw.html
  • http://stackoverflow.com/questions/8658789/using-spring-cache-annotation-in-multiple-modules
  • Test bed available at https://github.com/kilokahn/spring-testers/tree/master/spring-cache-tester

Friday, January 18, 2013

Fun with @Cacheable


From Spring 3.1.0.RELEASE onwards the @Cacheable annotation has been added to the spring-context jar. We will go through the motions of demonstrating how it can be leveraged through a contrived example of calculating the fibonacci numbers. We will have a service interface that is supposed to get the fibonacci number given an index over and over.
public interface FibonacciService {
    long getFibonacci(int index);
}
We will have three different service implementations. One will be a simpleton who will plainly calculate the number - called SimpletonFibonacciServiceImpl.
    public long getFibonacci(int index) {

        if (index == 0 || index == 1) {
            return 1;
        }

        long fiboMinusOne = getFibonacci(index - 1);
        long fiboMinusTwo = getFibonacci(index - 2);

        return fiboMinusOne + fiboMinusTwo;
    }
Our driver will make it go through its paces by making it calculate the 45th number of the fibonacci series.
    private static void doWorkWithFiboService(FibonacciService fibonacciService) {
        // First one
        doHeavyLifting(fibonacciService);
        // Some more
        doHeavyLifting(fibonacciService);
        // Come on... one last
        doHeavyLifting(fibonacciService);
        // Now flush
        fibonacciService.flushFibonacciCache();
        // Do some more
        doHeavyLifting(fibonacciService);
        // Be polite - clean out at the end - flush!
        fibonacciService.flushFibonacciCache();
    }

    private static void doHeavyLifting(FibonacciService fibonacciService) {
        StopWatch sw = new StopWatch();
        sw.start();
        fibonacciService.getFibonacci(45);
        sw.stop();

        LOG.info(fibonacciService.getClass().getCanonicalName() + " took "
                + sw.getTotalTimeSeconds() + " seconds");
    }
It roughly takes 7 seconds on a stock host to perform each computation (measured via org.springframework.util.StopWatch which is a good tool for poor man's benchmarking if you've not used it already).
[ 2013-01-18 10:49:04,006 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.212 seconds
[ 2013-01-18 10:49:11,236 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.23 seconds
[ 2013-01-18 10:49:18,465 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.229 seconds
[ 2013-01-18 10:49:18,466 [main] driver.SimpletonFibonacciServiceImpl.flushFibonacciCache():27  INFO ]: No-op
[ 2013-01-18 10:49:25,695 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.SimpletonFibonacciServiceImpl took 7.229 seconds
[ 2013-01-18 10:49:25,695 [main] driver.SimpletonFibonacciServiceImpl.flushFibonacciCache():27  INFO ]: No-op
To demonstrate the use of cache, we will have the second guy will use a concurrent map as the backing store for caching numbers once they are computed.
    @Cacheable("concurrentMapFibonacci")
    public long getFibonacci(int index) {

        if (index == 0 || index == 1) {
            return 1;
        }

        long fiboMinusOne = getFibonacci(index - 1);
        long fiboMinusTwo = getFibonacci(index - 2);

        return fiboMinusOne + fiboMinusTwo;
    }
The service has been annotated with the @Cacheable annotation. The annotation needs to be provided with the name of the backing cache store. The cache store definition (viz. concurrentMapFibonacci) is defined in the Spring context file as
    <bean id="concurrentMapFibonacci"
        class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" />
    <bean id="concurrentMapCacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <ref bean="concurrentMapFibonacci" />
            </set>
        </property>
    </bean>
To enable the processing of the annotation, we need to specify the directive:
    <cache:annotation-driven proxy-target-class="true" cache-manager="concurrentMapCacheManager" />
This is very similar to the tx:annotation-driven directive that we use to enable processing for the @Transactional annotation. Here we ask Spring to process all beans in the container for the @Cacheable annotation and use the bean named "concurrentMapCacheManager" to act as the CacheManager (which is of type SimpleCacheManager). The processing can be done via proxies or aspectj byte code weaving. For simple use cases, we prefer using proxies which is the default mode (we will cover the aspectj angle in the next post). In using proxies, by default JDK proxies are created which fail if the bean to be proxied doesn't implement any interface. In contrast CGLIB based proxies work on POJO's with the exception of final classes and non-default constructor classes (because they work by subclassing the POJO). We ask it to use CGLIB based proxies by specifying the proxy-target-class="true" switch.
[ 2013-01-18 11:17:24,707 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$5ea80813 took 7.595 seconds
[ 2013-01-18 11:17:24,708 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$5ea80813 took 0.001 seconds
[ 2013-01-18 11:17:24,708 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$5ea80813 took 0.0 seconds
[ 2013-01-18 11:17:24,709 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal ConcurrentMap flush
[ 2013-01-18 11:17:32,283 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.ConcurrentMapFibonacciServiceImpl$$EnhancerByCGLIB$$5ea80813 took 7.574 seconds
[ 2013-01-18 11:17:32,283 [main] driver.ConcurrentMapFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal ConcurrentMap flush
The first call takes the full time to calculate the fibonacci number, but the subsequent calls just fetch the numbers from the cache and hence finish instantaneously. Let's now explore the flushing or eviction of entries from the cache. The cache manager that we have used here is a SimpleCacheManager which provides a no-frills management (we will see fancy controls in management via EhCacheCacheManager later on). To evict entries from a cache on a particular call, we have the @CacheEvict annotation.
    @CacheEvict(allEntries = true, beforeInvocation = true, value = "concurrentMapFibonacci")
    public void flushFibonacciCache() {
        LOG.info("Royal ConcurrentMap flush");
    }
In this annotation we have asked Spring to evict all entries in the cache named "concurrentMapFibonacci" before said method is invoked. We can choose to evict bespoke keys via the keys directive (using SpEL). If the method has any arguments, those are used as keys for the entries to be evicted (ofcourse, in the absence of allEntries = true). So as expected, when the flush call is made, the cache goes cold, and the subsequent fetch again takes the full 7 odd seconds. It is important to note that though we are making recursive calls, the only key-value that got cached is the final one and not the intermediate ones. The reason being the mode that we chose. Proxy based solutions will only intercept calls that are being made from one spring bean to another and self calls are not processed (recursive or private/protected/public calls to the same class). In the next post, we will use aspectj to get a real live and kicking cache that will also house the intermediate entries and observe the improvement empirically.
The previous eviction policy was somewhat straight-jacketed. Who wants to call a method to flush caches periodically? Not me, because frankly it can be handled by a better cache store and an intelligent manager. Here is where ehcache comes in.
    @Cacheable("fibonacciEhcache")
    public long getFibonacci(int index) {

        if (index == 0 || index == 1) {
            return 1;
        }

        long fiboMinusOne = getFibonacci(index - 1);
        long fiboMinusTwo = getFibonacci(index - 2);

        return fiboMinusOne + fiboMinusTwo;
    }
To ask Spring to use ehcache as the underlying store, we specify so in the Spring context file:
    <bean id="fibonacciEhcache"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="ehcache.xml" />
    </bean>
    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="fibonacciEhcache"/>
    </bean>
We ask it to create a cache store named fibonacciEhcache who is managed by the EhCacheCacheManager.
    <cache:annotation-driven cache-manager="ehcacheManager" proxy-target-class="true"/>
Further configuration for the cache is available in the ehcache config file named "ehcache.xml" available on the classpath which looks something like:
<?xml version="1.0" encoding="UTF-8"?>
<!-- To know more about the available configuration. Refer http://ehcache.org/ehcache.xml -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" monitoring="autodetect"
    updateCheck="false" dynamicConfig="false">

    <diskStore path="java.io.tmpdir" />

    <cache name="fibonacciEhcache" maxEntriesLocalHeap="10000"
        maxEntriesLocalDisk="1000" eternal="false"
        diskSpoolBufferSizeMB="20" timeToIdleSeconds="300"
        timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU"
        transactionalMode="off">
        <persistence strategy="localTempSwap" />
    </cache>

    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        diskSpoolBufferSizeMB="30"
        maxElementsOnDisk="1000"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU" />

</ehcache>
The cache named fibonacciEhcache is has been thus configured to keeping the backing disk store on the java.io.tmpdir location (by default /tmp on linux) and have the cache purged every 10 minutes (via the timeToLiveSeconds="600"). Other explanations can be found in the documentation of the sample ehcache.xml file.
[ 2013-01-18 11:38:12,689 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$a1d7290c took 7.598 seconds
[ 2013-01-18 11:38:12,690 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$a1d7290c took 0.001 seconds
[ 2013-01-18 11:38:12,690 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$a1d7290c took 0.0 seconds
[ 2013-01-18 11:38:12,697 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal Ehcache flush
[ 2013-01-18 11:38:20,286 [main] driver.SpringCacheTesterDriver.doHeavyLifting():52  INFO ]: com.kilo.driver.EhcacheFibonacciServiceImpl$$EnhancerByCGLIB$$a1d7290c took 7.588 seconds
[ 2013-01-18 11:38:20,287 [main] driver.EhcacheFibonacciServiceImpl.flushFibonacciCache():30  INFO ]: Royal Ehcache flush
The runs reflect roughly the same behavior as with the concurrent map usage.
This will serve as a primer and we will have some more fun in the next post where we explore slightly more involved use cases.
References:
  • http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/cache.html
  • http://ehcache.org/ehcache.xml
  • Testbed available at https://github.com/kilokahn/spring-testers/tree/master/spring-cache-tester

Friday, November 30, 2012

Exploring open source licenses

A presentation to remind me on the (well-known) licenses out there.

Addendum:

1. License for SaaS. AGPL (v1 and v3) are two copyleft licenses that cover this. Again, the rationale behind them is to be able to provide source code for software being used over the web. v1 is very similar to GPL v2 and v3 is on the lines of GPL v3.
2. EPL. A business-friendly license having weaker copyleft license than GPL. Not compatible with GPL and hence a work combining GPL and EPL cannot be redistributed. EPL requires distribution of a separate license (hence not very much in the free spirit) for the original work in the software which are supported by patents. EPL also contains a patent-retaliation clause which causes the contract between the author and user to terminate when the user initiates a lawsuit for patent infringement against the author.

Wednesday, November 28, 2012

Don’t let tx:annotation-driven get you


When we start developing a new application, we typically have a single data source that we define and all of our business logic revolves around getting data back and forth the data source. As the application matures, we often run into scenarios where we need to depend on jars given my others or we give out our jars to others for them to use. With Spring involved, the context also becomes part of the contract between the two sub-systems. Here is where tx:annotation-driven can get you. Typically, we define a PlatformTransactionManager of org.springframework.jdbc.datasource.DataSourceTransactionManager and bind it to the datasource that it should manage.
    <bean id="testerDataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
        <property name="url" value="${tester.datasource.url}" />
        <property name="username" value="${tester.datasource.username}" />
        <property name="password" value="${tester.datasource.password}" />
    </bean>
    <bean id="testerTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="testerDataSource" />
    </bean>
Next, to achieve declarative transactional functionality on specific methods in our service, we can use tx:advice in conjunction with aop:pointcut to indicate the advice that will act on the methods matching the pointcut. However, I prefer defining annotations on the service method itself to effect this declaratively. The upside of this, in my opinion, is that the reader of the code is clearly made aware of what are the transactional boundaries the service method is going to honor.
    @Transactional
    public void getReferenceData() {
        referenceDataDAO.getReferenceData();
    }
From Spring’s manual:
Declaring transaction semantics directly in the Java source code puts the declarations much closer to the affected code. There is not much danger of undue coupling, because code that is meant to be used transactionally is almost always deployed that way anyway.
To get @Transactional to work its magic, i.e. create a proxy which does the heavy lifting of beginning the transaction, delegating the call to the actual class, and either committing or rolling back the transaction based on the result of the call, we need to inform Spring to scan all beans that have this annotation on it. We inform Spring using the “tx:annotation-driven” directive. It is a namespace handler which scans all beans in the Spring container to proxy all methods that have been annotated with @Transactional. The @Transactional can also be placed at the class level, when it is applicable to all methods in the class. So this namespace handler will by default look for a bean named ‘transactionManager’ of class PlatformTransactionManager. If your transaction manager bean happens to be named any differently, you have to state it explicitly. Another note of caution from Spring:
Method visibility and @Transactional
When using proxies, you should apply the @Transactionalannotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the@Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (using mode=”aspectj”) if you need to annotate non-public methods.
Using the “proxy-target-classes” clause, we are able to choose whether we create interface-based JDK proxies or CGLIB based proxies. The former will only work if the class you are proxying is implementing an interface whereas CGLIB-based ones work with either one. OK, so far so good, how is that tx:annotation-driven is going to get me? Just when it is all so comfortable, there is another data source that now comes in the context, either because you imported someone else’s jar or because you started talking to a new data source, tx:annotation-driven will try to hijack any @Transactional annotations intended for those data sources as well and ask the existing transaction manager to try and manage it. All that the transaction manager does is hold a connection from the data source it had been configured with in a threadlocal. When trying to manage a hijacked data source the threadlocal that it has kept with it is non-consequential in rolling back the transaction if required. The worst part is that there is no error that is thrown, just that the effect will not happen.
On a related note, because the connection is held in a threadlocal, if you are spawning threads or delegating control to other threads from a  method that is annotated with @Transactional, all bets are off and you might end up with infinite waits or deadlocks.
So, what is the recommended solution? Spring suggests that we qualify your transaction managers and rather than giving a bare @Transactional, specify the transaction manager (via qualifier) that you intend to use. In addition to this, one can also choose to avoid specifying the transaction manager when specifying the tx:annotation-driven which will force every user of @Transactional to specify the transaction manager it wishes to use (otherwise the container throws an exception saying that it didn’t find a bean with the name ‘transactionManager’). While this is more work, I think it is worth the clarity it provides and makes it explicit for users of the service method in other contexts.
References:
1. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative
2. Test bed available at https://github.com/kilokahn/spring-testers/tree/master/spring-tx-annotation-tester