I came up with this work-around based on my experiences of using an existing database with Grails. When using an existing database the GORM can treat any Enum on your database as a string. Next if you are manually building up the domain from this database model you would want to constrain your faux string by the values of the Enum as expressed in the database. When working from an existing table I would simply cut and paste the values into the inList constraint for the domain class. But what if you have an existing Enum class?
For a really simple example let's consider:
public enum GenderCode {
M,
F;
public String value() {
return name();
}
public static GenderCode fromValue(String v) {
return valueOf(v);
}
}
This is a really simple enumerated type that represents the "M" and "F" codes that many systems use to indicate Male or Female. Now we would probably use this class like this:
class Person {
String name
GenderCode gender
}
... but Grails will not know what to do with the enumerated type. So we can "work around" this limitation by using our good friend constraints... like so:
class Person {
String name
String gender
static constraints = {
name(nullable:false)
gender(inList:GenderCode.getList())
}
}
... only problem... how do we get the GenderCode enumerated type (a straight java class by the way) to give us a List object to use in the inList constraint?
It's not too hard...
public enum GenderCode {
M,
F;
private static Listlist;
public String value() {
return name();
}
public static ListgetList() {
if(list != null) {
return list;
}
return buildList();
}
private static synchronized ListbuildList() {
// List was not initialized...
list = new ArrayList();
for (GenderCode c: GenderCode.values()) {
list.add(c.name());
}
return list;
}
public static GenderCode fromValue(String v) {
return valueOf(v);
}
}
You might notice I chose to use the synchronized key word on the buildList method. Also note that I store the Enumerated types in the grails project under src/java. The domain classes store only strings.
So now when I go to generate scaffolding code for the Person class I'll get a GSP that will use a drop-down list of values from the enumerated type. If I alter the enumerated type to include the value "U" in the enumerated type there is no need to re-generate any of the views... re-populate a database... or update a boot strap script.
If you want the Enum type on your database itself now your DBA can alter that column on that particular table to be of type Enum and coordinate with you what values are in the list. GORM won't complain. And, your DBA will be happy to see true enumerations in their database which are both human-readable and space efficient. Did I also mention that they cut down on the number of joins to lookup tables making queries in all application spaces faster?
What do you think?