Monday, 15 September 2008

Command Objects Revisited

I posted yesterday about command objects but a conversation I had this morning made me realise I'd neglected to mention one of the interesting and less obvious ways to use them.

Imagine a scenario where you have a form that is basically for saving domain object instances but has a few other fields, not directly properties of the domain object in question but things like choices of how to set property values (e.g. a radio button to choose whether or not to update the timestamp on the object), workflow type instructions to the controller (e.g. preview this object after saving it), etc. This is a very common scenario.

You can handle this neatly with command objects by nesting an instance of the domain class inside the command object class, e.g.
    class MyCommand {
boolean updateTimestamp
boolean previewAfterSave
MyDomain domainObj
}
Then name your form fields accordingly...
    <g:checkBox name="updateTimestamp" value="${command.updateTimestamp}" />
<g:checkbox name="previewAfterSave" value="${command.previewAfterSave}" />
<input type="hidden" name="domainObj.id" value="${command.domainObj.id}" />
<input type="text" name="domainObj.name" value="${command.domainObj.name}" />
<g:select name="domainObj.otherDomainObj" from="${OtherDomainClass.list()}" value="${command.domainObj.otherDomainObj.id}" optionKey="id" />
and so on.

2 comments:

Stephen Cresswell said...

However if you're using domain objects in command objects watch out http hacks that update properties that shouldn't be changed, e.g.
class MyCommand {
boolean updateTimestamp
boolean previewAfterSave
MyDomain domainObj
}
http://blah.com/save?domainObj.account.balance=9999999999

Rob said...

Good point and the same is true of forms that update domain objects directly.