Grails supports domain classes as properties of command objects out of the box. I can use a domain class Stuff
with a command StuffCommand
, but not if Stuff
is an abstract class.
Stuff.groovy
abstract class Stuff{
}
StuffCommand.groovy
class StuffCommand{
Stuff stuff
}
ExampleController.groovy
class ExampleController{
def doStuffWithStuff(StuffCommand stuffCmd){
render stuffCmd.stuff ? stuffCmd.stuff as JSON : ''
}
}
Then, the request http://server:port/ctx/example/doStuffWithStuff?stuff=123
will not get the record #123 out of the stuff
table from my database. I love the concise nature of that approach. The query on the database either does not take place or fails silently.
The following workaround helps a little, though:
Create a class that converts ValueConverter
for the abstract comain class. The class name must end with ValueConverter
, other than that you can name it at will, for instance IdStringToStuffValueConverter
.
IdStringToStuffValueConverter
import org.grails.databinding.converters.ValueConverter
class IdStringToStuffValueConverter implements ValueConverter{
@Override
boolean canConvert(Object value) {
value instanceof String || value instanceof Integer || value instanceof Long
}
@Override
Object convert(Object value) {
return Stuff.get(value.toLong())
}
@Override
Class<?> getTargetType() {
return Stuff
}
}
Now I can fire above request and the controller will hit the database again during data binding. But the following does still not work as expected:
ExampleController.groovy
class ExampleController{
def doStuffWithStuff(Stuff stuff){
render stuff ? stuff as JSON : ''
}
}
During this action no database queries take place, hence the workaround does not cover this case. How can I use abstract domain classes as command objects?