Technipelago AB

Technipelago Blog Stuff that we learned...

Custom error response for Spring REST endpoints

Publicerad den 1 okt 2017

It's easy to customize the error response from REST endpoints in Spring Boot. This blog post explains how to add a custom error code to the response.

The default error response from a Spring Boot REST endpoint looks something like this:

    "error": "Not Found", 
    "exception": "", 
    "message": "A record with value [foo] was not found", 
    "path": "/foo", 
    "status": 404, 
    "timestamp": 1507117452642

If we want to include custom information into the error response it's easy. Just add an ErrorAttributes bean to the spring context.

The following code snippet checks if the thrown exception is a custom exception MyException. This exception type contains a code attribute that holds a unique error code. We want to include that code as a specific key in the error response.

public class MyApplication {

    public static void main(String[] args) {, args);

    public ErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes() {
            public Map getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
                final Map errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
                // Customize the default entries in errorAttributes by adding the error code.
                Throwable exception = this.getError(requestAttributes);
                if (exception instanceof MyException) {
                    errorAttributes.put("code", ((MyException) exception).getCode());
                return errorAttributes;

If a controller method throws MyException the response now looks like this:

    "code": "12345",
    "error": "Not Found", 
    "exception": "", 
    "message": "A record with value [foo] was not found", 
    "path": "/foo", 
    "status": 404, 
    "timestamp": 1507117452642

Tags: spring boot rest

Grails 3.2.0 - java.lang.IllegalArgumentException: Incorrect type for parameter [tenantId]

Publicerad den 11 sep 2016

With Grails 3.2.0 native multi-tenancy has finally arrived in Grails core. This makes Grails a powerful framework for multi-tenant web applications. But these advanced features comes with a price. New kind of problems surface and you most know what you're doing more than ever.

Tested with Grails 3.2.0.RC1

Consider the following code:


import grails.gorm.MultiTenant

class Person implements MultiTenant {
    Long tenantId
    String firstName
    String lastName
    def beforeValidate() {
        if(tenantId == null) {
            tenantId = Tenants.currentId()



Tenants.withId(1) {
    new Person(firstName: "Groovy", lastName: "Grails").save(failOnError: true)

This looks ok, doesn't it?

Well, this is what you get:

java.lang.IllegalArgumentException: Incorrect type for parameter [tenantId]

	at org.hibernate.internal.FilterImpl.setParameter(
	at org.grails.orm.hibernate.AbstractHibernateDatastore.enableMultiTenancyFilter(
	at org.grails.orm.hibernate.AbstractHibernateDatastore$
	at org.grails.orm.hibernate.GrailsHibernateTemplate$1.doInHibernate(
	at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(
	at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(
	at org.grails.orm.hibernate.GrailsHibernateTemplate.executeWithNewSession(
	at org.grails.orm.hibernate.AbstractHibernateDatastore.withNewSession(
	at org.grails.orm.hibernate.AbstractHibernateDatastore.withNewSession(
	at grails.gorm.multitenancy.Tenants.withTenantIdInternal_closure1(Tenants.groovy:182)
	at grails.gorm.multitenancy.Tenants$CurrentTenant.withTenant(Tenants.groovy:273)
	at grails.gorm.multitenancy.Tenants.withTenantIdInternal(Tenants.groovy:181)
	at grails.gorm.multitenancy.Tenants.withId(Tenants.groovy:157)

Because tenantId in Person is a Long you must make sure you supply a Long parameter to withId(1).


Tenants.withId(1L) {
    new Person(firstName: "Groovy", lastName: "Grails").save(failOnError: true)

Tags: grails multi-tenancy 3.2.x

In Grails 2.5.1 don't name a request parameter "namespace"

Publicerad den 7 sep 2015

Lessons learned the hard way...

When I upgraded a Grails 2.4.5 application to Grails 2.5.1 one group of events stopped working. No event listeners were found for the namespace and topic.

Reverting back to Grails 2.4.5 made the events work again.

I think the change that hit me was this commit. I had a request parameter called "namespace" that I used to dynamically set the namespace for the the events. But in Grails 2.5.1 "namespace" is a reserved parameter name for the controller namespace. So the value I sent in the request parameter was overwritten (actually it is removed) by Grails.

Renaming my request parameter from "namespace" to "ns" solved my problem. But I wonder if this is expected behaviour by Grails, removing "my" parameter like that?

Tags: grails 2.5.1 namespace upgrade problem

Scale and crop any image size to Full HD

Publicerad den 28 maj 2015

If you need to scale images in various sizes and formats to same size (in this example to full HD) you can use ImageMagick and the following command:

convert in.jpg -resize "1920x1080^" -gravity center -crop 1920x1080+0+0 +repage -quality 50 out.jpg

Tags: web image convert

Use Perl to fix your old Grails controllers

Publicerad den 1 mar 2012

Use Perl to replace Grails action references with deprecated format redirect(action: show) to redirect(action: 'show') and action closures to action methods

Today I finally took the time to upgrade my largest Grails 1.3.7 application to Grails 2.0.1

You can read about it here.

I started to develop this application during spring 2008 and I've been upgrading to all Grails versions between 1.1 and 1.3.7. This makes the code base somewhat "dynamic". Different code styles and implementations depending on Grails version, best practices at the time, and my skills level.

As a result, lots of old controller code has redirects that reference action closures directly using the action's property instead of the action name.


instead of the recommended:


I did a "grep" on all my 70 controllers and found out that 50 of them (300+) lines had bad redirects!!!

No way I was going to change all those lines manually.

That's when my old Perl knowledge came to rescue!

Here's the script


while(<>) {
  if(/redirect(.+)action:\s*(\w+)/) {
    print "$`redirect$1action: \"$2\"$'";
  } else {
    print $_;


$ cd grails-app/controllers/...
$ cp *Controller.groovy $HOME/i-am-a-chicken
$ perl -i *Controller.groovy

All redirect(action:prop) are now changed to redirect(action:"prop")
The following script converts
def actionMethod = {arg1, arg2 ->
  // ...
def actionMethod(arg1, arg2) {
  // ...
But it's not tested in "production" so please use with caution.

while(<>) {
  if(/^\s*def\s+(\w+)\s*=\s*\{([^\-]*)\-\>\s*$/) {
    print "def $1($2) {\n";
  } elsif(/^\s*def\s+(\w+)\s*=\s*\{\s*$/) {
    print "def $1() {\n";
  } else {
    print $_;
Good old Perl, thank you!

Tags: grails perl controller upgrade

Grails 1.3.7 to 2.0.1 upgrade experiences

Publicerad den 28 feb 2012

Today I finally took the time to upgrade my largest Grails 1.3.7 application to Grails 2.0.1. This blog post describe how I did it.

I started to develop this application during spring 2008. What was the Grails version back then? Was it 1.0 or maybe 1.1? I'm not sure what version I started with. Anyway I've been eager to upgrade to new Grails versions fairly quickly after each release so I've been using all Grails versions since 1.1.

This particular application is in production use by a handfull of clients. It's a mission critical CRM system so quality is important. That's the main reason why I didn't jump on the Grails 2.0 wagon as early as I used to. All my Grails apps in production are still on Grails 1.3.7.

I constantly monitor the Grails mailing list to hear what people say about upgrade experiences and the quality of Grails 2.0. I did not touch Grails 1.4/2.0 until 2.0.0 was released. Then I felt comfortable enough to upgrade a few plugins and simple apps. But I still was a little afraid to upgrade my largest and most important Grails app to 2.0.

When Grails 2.0.1 was released I upgraded some more plugins and started a completely new client project on Grails 2.0.1. After two weeks working full days with 2.0.1 I decided to try and upgrade my major 1.3.7 application to 2.0.1.

This is a transcript of my upgrade session:


2012-03-01 12:30 - Starting Grails 1.3.7 to 2.0.1 upgrade

# grails upgrade


# Manually updated BuildConfig.groovy by looking at a freash 2.0.1 application. I also bumbed the version number for all plugin dependencies to the latest and greatest.

# grails compile

/Users/goran/.grails/2.0.1/projects/myapp/plugins/persistent-result-0.6/src/java/grails/plugins/persistentresult/ cannot find symbol

symbol  : constructor PagedResultList(java.util.List)

location: class grails.orm.PagedResultList



This code is in one of my own developed plugins. I have a custom class derived from grails.orm.PagedResultList and it seems like it has changed a lot between 1.3.7 and 2.0

I looked at my implementation and decided I could subclass java.util.AbstractList instead of PagedResultList. It took some time to change the implementation but I finally got it to work.

# grails compile


# grails test-app

| Error Error executing script TestApp: org.codehaus.groovy.grails.exceptions.GrailsConfigurationException: Database driver [org.hsqldb.jdbcDriver] for HSQLDB not found. Since Grails 2.0 H2 is now the default database. You need to either add the 'org.h2.Driver' class as your database driver and change the connect URL format (for example 'jdbc:h2:mem:devDb') in DataSource.groovy or add HSQLDB as a dependency of your application. (Use --stacktrace to see the full trace)

Ahh. I must modify DataSource.groovy and change HSQLDB to H2. Since this is a plugin a standard DataSource.groovy is sufficient so I copied one from a fresh Grails 2.0.1 plugin.

# grails test-app


# grails publish-plugin --repository=myCompanyRepository


Now I went back to the main Grails app and updated BuildConfig.groovy to depend on the fixed plugin.

# grails compile

| Warning The [saveQuery] action in [PersonController] accepts a parameter of type [PersonQueryCommand] which has not been marked with @grails.validation.Validateable. This may lead to an intermittent MissingMethodException for validate(). We strongly recommend that you mark command object classes with @Validateable in order to avoid the problem.

I added @Validateable to all commands objects

# grails compile


# grails run-app

| Running Grails application

| Error 2012-03-01 13:31:06,814 [pool-7-thread-1] ERROR [localhost].[/myapp]  - Error configuring application listener of class org.codehaus.groovy.grails.web.util.Log4jConfigListener

Message: org.codehaus.groovy.grails.web.util.Log4jConfigListener

   Line | Method

->>  46 | findClass in org.grails.plugins.tomcat.ParentDelegatingClassLoader

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

|   306 | loadClass in java.lang.ClassLoader

|   247 | loadClass in     ''

Hmmm.. Something with logging. I copied Config.groovy from a fresh Grails 2.0.1 application and merged my Config.groovy file manually inspecting every line.

# grails run-app


Googling for: grails org.codehaus.groovy.grails.web.util.Log4jConfigListener

Ahh I must upgrade applicationContext.xml and sitemesh.xml in web-app/WEB-INF.

I copied applicationContext.xml and sitemesh.xml from a fresh Grails 2.0.1 application.

# grails run-app



Ahhh stupid me! I had a a custom src/templates/war/web.xml

I removed web.xml since I could not find any customizations in it.

# grails run-app



| Error 2012-03-01 13:58:48,901 [http-bio-8080-exec-9] ERROR [/myapp].[default]  - Servlet.service() for servlet [default] in context with path [/myapp] threw exception [Filtered request failed.] with root cause

Message: It looks like you are missing some calls to the r:layoutResources tag. After rendering your page the following have not been rendered: [head]

Updated my layouts to use Resources.

Application is up and running and I browsed through the main pages. (No I don't have any functional tests yet)


One controller that subclasses a base controller in src/groovy did not work (404).

I changed all closures to methods in the abstract controller and did the same in the controller subclass.


I added all methods that only existed in the abstract class to my subclass and made them call super.method()

(this was a quick fix. I need to go back later and find out what really was the problem)


In the problematic controller class I had a lot of redirects that referenced action closure properties directly instead of their name.

redirect(action: show,

I changed all to: 

redirect(action: "show",





There are lot more tests I need to perform before I can put this in production but it feels great to have come this far. And it went faster than I expected. I was prepared for a few days of banging my head against the keyboard.

Tags: grails upgrade

Parse query string with Groovy

Publicerad den 31 jan 2012

This little piece of Groovy code transforms a URL query string into a Map

One day I needed to parse a URL query string outside of a web container using only Groovy. I was surprised there was no standard was to do this and I could not find a small convenient library to use. So I rolled my own.

This is what I came up with:

// Define a complex query to test with.
def url = new URL("" +
  "?sclient=psy-ab&hl=sv&site=&source=hp&" +
  "q=parse+query+string+groovy&pbx=1&" +
  "oq=parse+query+string+groovy&aq=f&aqi=&aql=&gs_sm=e&" +
  "gs_upl=2640l7169l0l7417l25l14l0l11l11l0l102l616l13.1l25l0&" +
  "bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=41e3a896b66de401&" +

def map = url.query.split('&').inject([:]) {map, kv-> def (key, value) = kv.split('=').toList(); map[key] = value != null ? URLDecoder.decode(value) : null; map }

assert map.q == "parse query string groovy"


Works great! So let's add this method to the URL class

URL.metaClass.queryAsMap = {
  if(!delegate.query) return [:]

  delegate.query.split('&').inject([:]) {map, kv ->
    def (key, value) = kv.split('=').toList()
    if(value != null) {
      map[key] = URLDecoder.decode(value)
    return map

Tags: groovy

Setup two Ubuntu 10.04 LTS Servers as Cassandra Hosts

Publicerad den 22 dec 2011

Step-by-step instructions for setting up a Ubuntu server from scratch with Apache Cassandra NoSQL database

Step-by-step instructions for setting up a Ubuntu server from scratch with Apache Cassandra NoSQL database.

Install Ubuntu

Install Ubuntu Server 10.04 without any extra packages.

Install Java

sudo apt-get install python-software-properties

sudo add-apt-repository "deb lucid partner"

sudo apt-get update

sudo apt-get install sun-java6-jdk

sudo vi /etc/profile

export JAVA_HOME=/usr/lib/jvm/java-6-sun

Install Apache Cassandra


tar xf apache-cassandra-1.0.6-bin.tar.gz

sudo mkdir /var/log/cassandra

sudo mkdir /var/lib/cassandra

sudo chmod 777 /var/log/cassandra

sudo chmod 777 /var/lib/cassandra

Configuring a basic cluster with two hosts

Setup a second Ubuntu server, follow all of the "Install Ubuntu, Java and Cassandra" steps above, then:

On the first Ubuntu server, modify conf/cassandra.yaml:

cluster_name: 'Your Cluster Name'

initial_token: 0

listen_address: <this server's IP address>

rpc_address: <this server's IP address>

seeds: <ip1, ip2>

On the second Ubuntu server, modify conf/cassandra.yaml:

cluster_name: 'Your Cluster Name'

initial_token: 85070591730234615865843651857942052864

listen_address: <this server's IP address>

rpc_address: <this server's IP address>

seeds: <server_1_ip, server_2_ip>

Note: Each Ubuntu server must be able to contact the other via the IP addresses mentioned.

Now start Cassandra on the first Ubuntu server, give it a moment to come up, then start Cassandra on the second Ubuntu server.

Start Cassandra

cd .../apache-cassandra-1.0.6

bin/cassandra -f

Install SSH

Install SSH Server so you can access the node

sudo apt-get install openssh-server

Tags: cassandra bigdata ubuntu setup

Basic Authentication with grails-cxf plugin

Publicerad den 10 aug 2010

Secure your CXF-powered web services with 'basic-authentication

With the help of Chris Dail's excellent blog post I managed to secure my CXF-powered web service with 'basic-authentication'. This is how I did it:

Step 1: Download from Chris blog and put it in src/java.

Step 2: Add this to resources.groovy

securityInterceptor(BasicAuthAuthorizationInterceptor) {
  users = ['wsuser':'secret']

Step 3: Add this to BootStrap.groovy

class BootStrap {
  def myWebServiceFactory
  def securityInterceptor

  def init = { servletContext ->


SOAP requests must now provide the right username and password to access the web service.

In this example I have a grails service called MyWebService that exposes web service methods. In BootStrap you access it's factory by appending "Factory" to the service class name.

Next step for me is to use Shiro plugin to authenticate requests instead of hard coded usernames and passwords.

Tags: grails security cfx

How to drop a foreign key in MySQL

Publicerad den 19 jun 2010

Often when trying to drop a foreign key in MySQL I get an error message.

ERROR 1025: Error on rename of ‘./dbname/#sql-110_1′ to ‘./dbname/tablename’ (errno: 150)

The procedure I take when this happens is this:

MySQL> show engine innodb status;

Scroll up to find this section:



100623 16:15:14 Error in foreign key constraint of table devdb/foo:

there is no index in the table which would contain

the columns as the first columns, or the data types in the

table do not match the ones in the referenced table

or one of the ON … SET NULL columns is declared NOT NULL.

CONSTRAINT “FK335CD11BA9A1557E” FOREIGN KEY (”bar_id”) REFERENCES “bar” (”id”)

MySQL> alter table tablename drop foreign key FK335CD11BA9A1557E;
MySQL> alter table tablename drop bar_id;

Sometimes I have to repeat the steps twice because there are two foreign keys to drop.

Tags: mysql

Groovy loves POI and POI loves Groovy

Publicerad den 19 feb 2010

This little Groovy builder makes reading Microsoft Excel documents a breeze. With it you can write the following code to insert customers into your Grails database

new ExcelBuilder("customers.xls").eachLine([labels:true]) {
  new Person(name:"$firstname $lastname",
    address:address, telephone:phone).save()

If the spreadsheet has no labels on the first row, you can use numeric index to access cells.

new ExcelBuilder("customers.xls").eachLine {
  println "First column on row ${it.rowNum} = ${cell(0)}"

Here is the builder source.

The only jar you need is the Apache POI jar

package extract.excel

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.hssf.usermodel.HSSFSheet
import org.apache.poi.hssf.usermodel.HSSFRow
import org.apache.poi.hssf.usermodel.HSSFCell
import org.apache.poi.hssf.usermodel.HSSFDateUtil

 * Groovy Builder that extracts data from
 * Microsoft Excel spreadsheets.
 * @author Goran Ehrsson
class ExcelBuilder {

    def workbook
    def labels
    def row

    ExcelBuilder(String fileName) {
        HSSFRow.metaClass.getAt = {int idx ->
            def cell = delegate.getCell(idx)
            if(! cell) {
                return null
            def value
            switch(cell.cellType) {
                case HSSFCell.CELL_TYPE_NUMERIC:
                if(HSSFDateUtil.isCellDateFormatted(cell)) {
                    value = cell.dateCellValue
                } else {
                    value = cell.numericCellValue
                case HSSFCell.CELL_TYPE_BOOLEAN:
                value = cell.booleanCellValue
                value = cell.stringCellValue
            return value

        new File(fileName).withInputStream{is->
            workbook = new HSSFWorkbook(is)

    def getSheet(idx) {
        def sheet
        if(! idx) idx = 0
        if(idx instanceof Number) {
            sheet = workbook.getSheetAt(idx)
        } else if(idx ==~ /^\d+$/) {
            sheet = workbook.getSheetAt(Integer.valueOf(idx))
        } else {
            sheet = workbook.getSheet(idx)
        return sheet

    def cell(idx) {
        if(labels && (idx instanceof String)) {
            idx = labels.indexOf(idx.toLowerCase())
        return row[idx]

    def propertyMissing(String name) {

    def eachLine(Map params = [:], Closure closure) {
        def offset = params.offset ?: 0
        def max = params.max ?: 9999999
        def sheet = getSheet(params.sheet)
        def rowIterator = sheet.rowIterator()
        def linesRead = 0

        if(params.labels) {
            labels ={it.toString().toLowerCase()}
        offset.times{ }


        while(rowIterator.hasNext() && linesRead++ < max) {
            row =

Tags: groovy poi excel

How to copy a MySQL database

Publicerad den 10 dec 2009

How to copy a MySQL database with mysqldump

This is how I copy databases.

# Export
mysqldump --opt --skip-add-drop-table
  -h localhost -u root -p
    database > database.sql

# Import
mysql -u root -p
drop database dbname;
create database dbname;
use dbname;
source database.sql

Tags: mysql

Tomcat och hantering av svenska tecken

Publicerad den 5 okt 2009

Apache Tomcat fungerar inte alltid med svenska tecken om du inte först ändrar lite i konfigurationen

När jag började köra mina Grails-applikationer på Tomcat så slutade bl.a. searchable-pluginen att fungera med svenska tecken (åäö). Samma sak med ui-komponenten jQuery/autocomplete.

Problemet är kodningen av svenska tecken i en URL och löses genom följande tillägg i Tomcats server.xml

<Connector port="8080" protocol="HTTP/1.1"
  redirectPort="8443" connectionTimeout="20000"

Eller om man använder Apache HTTPD framför Tomcat med AJP:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"

Tags: tomcat encoding

Win32Wrapper startup timeout

Publicerad den 29 mar 2009

This blog post describes how to increase the startup timeout for Win32Wrapper

I use Win32Wrapper to start Jetty as a windows service. However, the default startup timeout of 30 seconds is to short for my Grails application to start. So I have to increase the startup timeout.

I did not find the parameter documented clearly, so I put it here as a reminder if I need it again.

Add this line to jetty-service.xml

wrapper.startup.timeout = 60

Tags: jetty windows

Reading IMAP mailbox with Groovy

Publicerad den 15 mar 2009

Groovy can make it easy to read an IMAP mailbox

The following Groovy code connects to an IMAP mailbox and read all unread messages.

import javax.mail.*
import java.util.Properties

Properties props = new Properties()
props.setProperty("", "imap")
props.setProperty("", host)
props.setProperty("mail.imap.port", port)
def session = Session.getDefaultInstance(props, null)
def store = session.getStore("imap")
def inbox

try {
  store.connect(host, username, password)
  inbox = openFolder(store, "INBOX")
  def messages =
    new FlagTerm(new Flags(Flags.Flag.DELETED), false))
  messages.each { msg ->
    println("${msg.subject} ${msg.sender}")
    msg.setFlag(Flags.Flag.SEEN, true)
} finally {
  if(inbox) {

Tags: groovy email imap

Make sure you have the right Content-Type for JSON

Publicerad den 3 mar 2009

Yesterday I spent 4 hours debugging a YUI AutoComplete component that I put on my page via the Grails-UI plugin. The result container (drop down) was not expanded even though the AJAX request returned perfect formed JSON data.

It was not until I put a YAHOO logger on my page and put som extra logging statements in autocomplete-debug.js that I found the simple and stupid problem.

The content-type of my AJAX response was set to “text/json” instead of “application/json”.

I copied an example from the web and did not notice the wrong content type.

The content type “application/json” is registered with IANA but there are many examples out there with other content types for JSON data. Read the specification.

Happy to have found the problem, but very frustrated that I spent that many hours on it.

By the way: Grails make it really simple to render JSON responses. But make sure you specify “application/json”.

def ajaxFindSystems = {
  def result = Systems.list()
  render(contentType:'application/json') {
    results {
    resultset (rows:result.size())

Tags: grails json

Add method on String to truncate long texts nicely

Publicerad den 17 nov 2008

I had several domain classes with long text content that I wanted to display just a summary of on the screen, especially in lists columns, etc.. I first added a getIntro(int numChars) method on domain classes with long strings, and used them when appropriate.

But I soon realised that I violated the DRY principle (Dont Repeat Yourself) with getInto() methods all over the place. I could have put the method in a base class but my text properties did not have the same name in all domain classes, so that was complicated.

I think I found a much better solution. I removed all those methods and added a getIntro(int) method to String and GString in BootStrap.groovy.

import org.apache.commons.lang.StringUtils

String.metaClass.intro = {len ->
  return StringUtils.abbreviate(delegate, len) ?: ''

GString.metaClass.intro = {len ->
  return StringUtils.abbreviate(delegate.toString(), len)

Now if I want a short introduction of a long text displayed somewhere I can just do like this:

def longText = "This is a long text that can mess upp the gui if it is displayed in its full length"

The result will be: This is a long text…

Adding new methods to existing classes is a really nice feature in Groovy!

Tags: groovy grails

Multiple Grails-UI AutoComplete components

Publicerad den 9 nov 2008

If you have a Grails-UI autoComplete component on a page that are dependent on another input element on the page, you can use the dependsOn=”id-of-other-element” config parameter.

Then the value of that other component will be passed in a “dependsOnValue” request parameter.

However, if the dependant element is also an autoComplete component and you want to send it’s hidden id-value in the request, you must use an alternative syntax for dependsOn.

  dependsOn="[value:’category’, label:’cat’, useId:true]"

The label parameter is optional, but you can use it to change the request parameter name from “dependsOnValue” to something else (in this case ‘cat’).

This is not well documented but I found it by looking at the Grails-UI source (InputTagLib.groovy).

Tags: grails ui

Invoke JPA lifecycle events in Grails

Publicerad den 24 sep 2008

If you use JPA instead of GORM, Grails will not invoke JPA lifecycle events automatically, i.e. @PrePersist, @PreUpdate, @PostRemove, etc.

That was a requirement in my project and I don’t know if this will be fixed in future versions of Grails. An issue exists that are targeted for Grails 1.1 (

However I solved it with a Hibernate event listener. Now I can annotate my JPA entities as usual and have Grails call them at the right time. The same entities are used by other Java Enterprise components in Glassfish so it’s good to have this work transparently from both sides.

Here’s the code:

package my.package;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import org.hibernate.event.PreInsertEvent;
import org.hibernate.event.PreInsertEventListener;
import org.hibernate.event.PreUpdateEvent;
import org.hibernate.event.PreUpdateEventListener;

 * If you use JPA instead of GORM, grails will not invoke
 * JPA lifecycle events automatically.
 * This event listener will bridge the gap.
 * It will listen to Hibernate events and invoke
 * corresponding JPA lifecycle events,
 * i.e. @PreInsert, @PreUpdate, @PostRemove, etc.
 * Put this code in BootStrap.groovy
 * to install the listener
 * (modify/duplicate for each event).
 * def init = { servletContext ->
 * def mel = new my.package.MyEventListener()
 * def ctx = WebApplicationContextUtils.
 *     getRequiredWebApplicationContext(servletContext)
 * def sessionFactory  = ctx.getBean('sessionFactory')
 * EventListeners eventListeners = sessionFactory.eventListeners
 * // PreInsert
 * def listeners = eventListeners.preInsertEventListeners
 * listeners = Arrays.copyOf(listeners, listeners.length + 1)
 * listeners[-1] = mel
 * eventListeners.preInsertEventListeners = listeners
 * // PreUpdate
 * listeners = eventListeners.preUpdateEventListeners
 * listeners = Arrays.copyOf(listeners, listeners.length + 1)
 * listeners[-1] = mel
 * eventListeners.preUpdateEventListeners = listeners
 * }
public class MyEventListener implements PreInsertEventListener, PreUpdateEventListener {
     * Invoke JPA entity methods annotated with @PreInsert.
     * @param event the Hibernate event
     * @see javax.persistence.PrePersist
     * @return normally false, true if method cannot be invoked.
    public boolean onPreInsert(final PreInsertEvent event) {
        Object m = event.getEntity();
        boolean veto = false;
        for (Method meth : m.getClass().getDeclaredMethods()) {
            if (meth.getAnnotation(PrePersist.class) != null) {
                try {
                } catch (Exception ex) {
                    Logger.getLogger(MyEventListener.class.getName()).log(Level.SEVERE, null, ex);
                    veto = true;
        return veto;

     * Invoke JPA entity methods annotated with @PreUpdate.
     * @param event the Hibernate event
     * @see javax.persistence.PreUpdate
     * @return normally false, true if method cannot be invoked.
    public boolean onPreUpdate(final PreUpdateEvent event) {
        Object m = event.getEntity();
        boolean veto = false;
        for (Method meth : m.getClass().getDeclaredMethods()) {
            if (meth.getAnnotation(PreUpdate.class) != null) {
                try {
                } catch (Exception ex) {
                    Logger.getLogger(MyEventListener.class.getName()).log(Level.SEVERE, null, ex);
                    veto = true;
        return veto;

Tags: grails jpa

Serialize domain objects in Grails Web Flow

Publicerad den 15 sep 2008

If you are using Grails Web Flow and put domain object in flash scope.

flash.model = new MyModel()

Make sure your events beforeInsert, beforeUpdate, beforeDelete, etc. are marked transient. Otherwise the domain object cannot be serialized and you get the following exception:

Could not serialize flow execution; make sure all objects stored in flow or flash scope are serializable; nested exception is

This happens because closures cannot be serialized.

Always mark your closues as transient to avoid future serialization problems.

class MyModel implements {

transient def beforeInsert = { … }


Tags: grails