Tuesday 30 December 2008

End of year burp..

I've been getting plenty end of year roundups in my reader and thought I might add something forward looking to the blog to encourage the team to use 2009 to investigate some interesting new things which we could all benefit from.

For Grails I would suggest that anyone working on new project (ahem, you know who you are) using Liquibase (or planning to), should seriously consider using Autobase. Its DSL for Liquibase, so keeps things more Groovy and less XML (we loved stepping off the spring.xml train, so now we're in Liquibase XML fun... why?).

The HttpBuilder DSL was announced without too much fanfare, which I know we use a lot. Again, another handy tool to jump on.

If you haven't heard of Robert Fischer by now then you've been sleeping beside your pair, but his new book is sure to be a boon to us all: Grails Persistence with GORM and GSQL. Get your pre-orders in, its out on the 26th of Jan.

Another interesting looking book is ScrumBan by Corey Ladas. We're always talking about improving how we work, and the Lean folks are challenging Scrum'mers to think a little more like them.

Which brings me to my last and more unusual mention which is that David Anderson managed to convince the people at Agile 2009 to setup the Agile Frontier Stage. David Anderson gave the singularly most captivating presentation at Agile Vancouver 2008 and stands out to me to challenge (in a very healthy and practical way) a lot of the orthodoxy which Scrum has become entrenched with. He's good people, see him present!

Thats its from me for this year

Happy New Years all :)

Invalidating Single Cached Items

Should have RTFM on this one but it was stuck on the board for so long and even F5 support couldn't figure out so I thought I'd post it here.

Sometimes we need to remove content from our CMS which means our app servers will serve up 404s for those requests. But we found that our F5 kept serving content from its stand-in cache for another 24 hours after the max-age had expired. We thought the stand-in cache was only there for when all the nodes in your pool had died so it looks like it's doing a little more than that.

Anyway, sometimes when we remove stuff from 'live' we really want it gone so we searched around and found that you can remove a single item from the F5 cache using a SOAP request to the management interface. The bad news is that you have to provide usernames and passwords in the clear but there's a nice way to get the same effect using invalidation triggers. At the back of Chapter 11 in the Policy Management Guide there's a straightforward example of what to do.

Thursday 11 December 2008

Handy Hints in BASH

Ever wanted to diff the output from 2 commands but didn't want to have to write the output to temporary files first? Well bash subshells come to the rescue.

Let's say you want to compare the list of files in 2 different directories. Try this:

diff <(ls /path/to/dir1) <(ls /path/to/dir2)

The bits in brackets are run in a subshell and then we redirect the output of that subshell to the stdin of diff. (On a personal note I prefer to run diff with the -y switch to get a side-by-side diff, but that's me).

Of course you can get really tricky with these things. How about making sure the file permissions are right as well?

diff -y <(ls -l /path/to/dir1 | awk '{print $1, $NF}')
<(ls -l /path/to/dir2 | awk '{print $1, $NF}')

(All that should be on one line. This is my first post so be gentle on me if it comes out looking like an uncombed monkey.)

So, have fun with subshells. And be careful out there.


Caching Grails Services

I've been plugging away for a few days on adding caching to Grails services. At first I tried to go down the road of decorating the services' metaClasses but since Grails uses an AOP proxy to add transactional behaviour to services this wouldn't work - the metaClass I got from the injected service object was not the same one my plugin had added stuff to. Also annotations on the service class were unavailable from the proxy.

The Spring Modules project has a nice caching implementation that uses annotations to decorate methods with caching and flushing behaviour. Getting this to work with Grails, was reasonably straightforward. As it turns out one additional config line made the difference between the spring-modules example config and something that worked in Grails.

I based the config on the annotation example from the Spring Modules documentation, converting the Spring XML to Grails BeanBuilder format:

    import org.springframework.aop.framework.autoproxy.*
import org.springmodules.cache.annotations.*
import org.springmodules.cache.interceptor.caching.*
import org.springmodules.cache.interceptor.flush.*

def doWithSpring = {

// declaration of cacheManager and cacheProviderFacade omitted - implementation specific

autoproxy(DefaultAdvisorAutoProxyCreator) {
proxyTargetClass = true
}

cachingAttributeSource(AnnotationCachingAttributeSource)

cachingInterceptor(MetadataCachingInterceptor) {
cacheProviderFacade = ref("cacheProviderFacade")
cachingAttributeSource = ref("cachingAttributeSource")
def props = new Properties()
props.myCachingModel = 'cacheName=MY_CACHE_NAME'
cachingModels = props
}

cachingAttributeSourceAdvisor(CachingAttributeSourceAdvisor, ref("cachingInterceptor"))

flushingAttributeSource(AnnotationFlushingAttributeSource)

flushingInterceptor(MetadataFlushingInterceptor) {
cacheProviderFacade = ref("cacheProviderFacade")
flushingAttributeSource = ref("flushingAttributeSource")
def props = new Properties()
props.myFlushingModel = 'cacheNames=MY_CACHE_NAME'
flushingModels = props
}

flushingAttributeSourceAdvisor(FlushingAttributeSourceAdvisor, ref("flushingInterceptor"))
}
The vital bit is the proxyTargetClass = true on the autoproxy bean. I won't pretend to understand what that's doing - I just noticed that's how ServicesGrailsPlugin was getting the transactional proxies to work.

After that it's a simple case of annotating service methods (in fact methods on any Spring-managed bean but services are the obvious use case).

    import org.springmodules.cache.annotations.*

@Cacheable(modelId = "myCachingModel")
def getSomethingInAnExpensiveWay(param1, param2) {
// ...
}

@CacheFlush(modelId = "myFlushingModel")
def updateSomething(param1, param2) {
// ...
}
This works fine on transactional and non-transactional Grails services. You can see the cache operations by setting log4j.logger.org.springmodules.cache = "trace".

The actual caching implementation used can be anything - spring-modules supports ehcache, oscache, JBoss cache, JCS, etc. All that's required is to wire in the cacheManager and cacheProviderFacade beans as described in the Spring Modules documentation.

I've bundled the results up as a Grails plugin (grails install-plugin springcache). It uses a ConcurrentHashMap backed simple cache implementation by default but wiring in ehcache or oscache is easy.

Caching and flushing models are configured in Config.groovy, e.g.:

    springcache {
cachingModels {
cachingModel1 = 'cacheName=CACHE_1'
cachingModel2 = 'cacheName=CACHE_2'
}
flushingModels {
flushingModel1 = 'cacheNames=CACHE_1,CACHE_2'
}
}
Particular caching implementations may have further options or require additional external config (such as ehcache's ehcache.xml file).

To disable the plugin you can set springcache.disabled=true. For example, it may be desirable to disable the plugin in the test environment.

Edit: Documentation added on grails.org

Passing enums into a constructor

Take this error:

binding.GrailsDataBinder Unable to auto-create type, 'create' method not found.

I came across this yesterday, and although the cause was documented, two of us managed to miss the crucial sentence in those docs for about an hour, causing much scratching of heads:

"my problem is that when I pass a Status enum to a constructor of some other class"

So, setting enum properties on a domain object is fine:

Burger canHaz = new Burger();
canHaz.flavour = Flavours.CHEESE;

Just not doing so via a constructor call:

Burger willNeverHaz = new Burger(flavour:Flavours.VEGETARIAN);

The original post I found is here:

http://www.nabble.com/Using-enums-gives-%22Unable-to-auto-create-type,-'create'-method-not-found%22-error-td18890306.html

and the JIRA bug report here:

http://jira.codehaus.org/browse/GRAILS-3314

Hopefully this will save someone else lots of head scratching! :o)

Wednesday 10 December 2008

Nasty liquibase bug

We recently came across a nasty liquibase bug.

When you drop a not null constraint on a table and you do not add in the column data type liquibase creates the column with a null column type.

Eg:
dropnotnullconstraint tablename="pirates" columnname="crew" --- creates a null column type.

Easy fix:
dropnotnullconstraint tablename="pirates" columnname="crew" columndatatype="VARCHAR(255)"


Just wanted to give everyone a heads up on the problem so they don't burn half a day trying to figure out what is going on.