GORM :: override a setter on a Grails Domain
by Colin on Jan.08, 2009, under Groovy-Grails
Rather than implement properties in the Java Language, we have a convention called a Java Bean. This basically means that properties are implemented with getter and setter methods with a PascalCase property name in the method among a few other simple conventions.
Grails makes it incredibly easy to manage domain classes since it is inherently domain-centric. When you need to enhance your Domain classes at the core of your application, you have an option of implementing your own getters and setters. I love that by default you do not have to implement your own setters, but you have the power to do so if you wish; the principle of sensible defaults. Here is an example of a Book Object with two properties, author and isbn.
class Book {
String author
String isbn
}
Consider the case where a Book is in your Database with the ISBN of 978-1430219262 and a user tries to search for "9781430219262". Unless you do some searchable magic, the user will not find the book. A simple solution fo the issue would be to never store ‘-’ in the databse. to make this happen you could easily remove the dash in the setter. So your domain would look like this:
class Book {
String author
String isbn
void setIsbn(String i) {
isbn = i.replace('-','')
}
}
When I first tried this, I failed a few times before I got it right. Maybe I was just spoiled with Groovy’s groovyness, but I started out writing
def setIsbn(i){ ... } and when that didn’t work: void setIsbn(i){ ... } which was being called, but never actually set the property. Then I had a forehead smacking moment where I realized that the method signature must precisely match the signature of a JavaBean setter like public void setPropertyName(Type propVal) { ... } In my case I had to make sure that the method was public (public by default), has a return type of void (which is not the default behavior of a closure), and the parameter passed in was of the same type as the property (String)
And then I blogged about it — the fourth day.
January 9th, 2009 on 7:46 am
Colin,
Great post – I’ve struggled with the same thing in the past. One way you can make sure you get the correct method signature is to run javap on a compiled groovy class (before you override the method, of course):
groovyc Book.groovy
javap Book
Compiled from “Book.groovy”
public class Book extends java.lang.Object implements groovy.lang.GroovyObject{
…
public void setIsbn(java.lang.String);
….
}
You can then copy that method signature directly into your code to and override it to your hearts content.
(hat tip to http://naleid.com/blog/2008/12/24/groovy-spread-operator-optional-for-properties-plus-a-peek-into-the-sausage-factory/ for getting me interested in javap)
January 10th, 2009 on 12:27 am
oh great. i just know that we can override the setter in GORM. THAT’s really usefull since I need to format the date from String to java.util.date (i am not using g:datepicker, but using my own javascript date picker).
thank you for sharing your knowledge…
August 18th, 2009 on 9:24 am
That certainly helps. Thanks for your suggestion. Thanks to Mike too for his insight
January 29th, 2010 on 3:35 pm
I’m curious, does GORM use the property set when retrieving from the database?
on a credential domain class I wanting to guard against a password field being set to a non-hashed value… So my initial thinking was to create:
String password
void setPassword(String pw) {
password = getHash(pw,salt)
}
but if the hashed password was retrieved from the database wouldn’t it end up going through another cycle of hashing?