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?

0

There are 0 answers