giovedì 19 maggio 2011

Narrowing properties returned from Grails Criteria

These snippets show a nice feature that I think could be better documented in Grails docs: the use of projections closure to narrow properties returned from criteria.



And it works with associations too:

martedì 17 maggio 2011

SpringCache custom cache resolver & Acegi plugin

Today's snippet is derived from excellent SpringCache plugin documentation, I had to resolve my cache against a property of currently logged user in a sort of multitenancy, so I had to define a custom CacheResolver in src/groovy:

import grails.plugin.springcache.CacheResolver

class CustomCacheResolver implements CacheResolver {
 def authenticateService
 
  String resolveCacheName(String baseName) {
   def user = authenticateService.principal().domainClass
   user = User.get(user.id)
   def bancheIds = user.banche*.getId().sort().join("_")
   "${baseName}-banche-${bancheIds}"
  }
}

and then wire authenticateService in resources.groovy:

customCacheResolver(CustomCacheResolver) {
  authenticateService = ref("authenticateService")
 }

now it can be referenced from SpringCache annotations:

@CacheFlush(caches = "categorieCache", cacheResolver = "customCacheResolver")

and every tenant (defined by banche collection identifiers) has its cache.

Note that I used Acegi plugin, which now is discontinued, but I think the same could be obtained with SpringSecurity plugin also. Just wire springSecurityService and resolve current logged user from it with getCurrentUser().

mercoledì 11 maggio 2011

Having a Jenkins Grails build agains a war and code coverage reports

Recently I've read Luke Daley's post about testing Grails apps against a war and Christian Oestreich's post regarding Jenkins builds and code reports, so I tried to merge their knowledge and get a Jenkins build with tests against war AND code reports.

After struggling with various configurations (and erroneously blaming geb for not having my functional tests working) it turned out that you can't have code coverage if its target is a war: cobertura jar must be included in your war file or you'll encounter a ClassNotFoundException.

Having cobertura jars in production builds is not an acceptable solution, so I've ended including the dependency inside an environment check in project's BuildConfig.groovy:

// Including cobertura jar (testing against a war, special case)  
  if (grailsSettings.grailsEnv == "test"){
    def args = System.getProperty("grails.cli.args")
    if (args.tokenize().containsAll(['-war','-coverage'])){
      compile('net.sourceforge.cobertura:cobertura:1.9.4.1'){
        excludes "asm", "log4j"
      }
    }
  }


Note that cobertura jar is included only if the '-war' and '-coverage' switches are passed together in the command line and environment is 'test'.

Now I can run all of my tests from Jenkins against a war build and having all code reports I need, Chuck Norris is happy, and I can go back to meditate.