Grails

Errors null - command object - edit closure

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Blocker Blocker
  • Resolution: Won't Fix
  • Affects Version/s: 1.2-RC2
  • Fix Version/s: 1.2 final
  • Component/s: Controllers
  • Labels:
    None
  • Environment:
    Windows XP

Description

There are data inconsistencies in our historical database, so the users have asked us to display errors when edit.gsp is loaded. The page is backed by a command object declared at the bottom of the controller class file. The command object is annotated with @Validateable. Within the edit closure we have

accountDetailsCommand.errors.rejectValue('username','username.format')

This line generates an exception in Grails 1.2.0.RC2 - "Cannot invoke method rejectValue() on null object"

In Grails 1.1.1 and 1.1.2 this error sometimes occurred on hot-reload, but it never happened once the application was running.

Activity

Hide
Jeff Brown added a comment -

I haven't investigated the real cause of this yet but why are you marking a command object as @Validateable? Command objects are made validateable by default.

Show
Jeff Brown added a comment - I haven't investigated the real cause of this yet but why are you marking a command object as @Validateable? Command objects are made validateable by default.
Hide
Martin Flower added a comment -

Hi Jeff, so I have AccountController.groovy which contains AccountController and AccountDetailsCommand. When I first attempted to access the errors in the edit{} closure, errors was null. I raised the question on the mailing list and received the following reply

http://old.nabble.com/Re%3A-Error-messages-within-edit%7B%7D-p26779988.html

and when I used @Validateable it worked - as long I restarted grails each time I made a change.

Hope that makes sense.

Martin

Show
Martin Flower added a comment - Hi Jeff, so I have AccountController.groovy which contains AccountController and AccountDetailsCommand. When I first attempted to access the errors in the edit{} closure, errors was null. I raised the question on the mailing list and received the following reply http://old.nabble.com/Re%3A-Error-messages-within-edit%7B%7D-p26779988.html and when I used @Validateable it worked - as long I restarted grails each time I made a change. Hope that makes sense. Martin
Hide
Martin Flower added a comment -

Maybe I should also say that I call new AccountDetailsCommand() within the edit{} closure. Is there a better way ?

Show
Martin Flower added a comment - Maybe I should also say that I call new AccountDetailsCommand() within the edit{} closure. Is there a better way ?
Hide
Jeff Brown added a comment -

You should not be creating an instance of the command object class yourself. If your controller action accepts a command object as an argument, one will be created, populated with request parameters and validated and then will be passed as an argument into your controller action.

If you can create a simple app that is representative of what you are trying to do and attach that here, I can help you sort out the best solution.

Show
Jeff Brown added a comment - You should not be creating an instance of the command object class yourself. If your controller action accepts a command object as an argument, one will be created, populated with request parameters and validated and then will be passed as an argument into your controller action. If you can create a simple app that is representative of what you are trying to do and attach that here, I can help you sort out the best solution.
Hide
Martin Flower added a comment -

I haven't got the code in front of me, but I think the sequence of urls is

account/show/1234
account/edit/1234

in the show{} closure I call Account.get(params.id) and then call a method

accountDetailsCommand = populateCommandFromAccount(account) which calls new AccountDetailsCommand()

and then return accountDetailsCommand to the view - no problem.

in edit{} I'm basically trying to do the same thing, but add error messages as well. All works, apart from the error messages.

Do I need to add all the properties of AccountDetailsCommand to the request so that it can be instantiated automatically in the edit{} closure ? that is

account/edit?name=zxc&country=ytr&telephone=terte&....

I'll look at the code again tomorrow and aim to come back with a Hello World application.

Thanks

Martin

Show
Martin Flower added a comment - I haven't got the code in front of me, but I think the sequence of urls is account/show/1234 account/edit/1234 in the show{} closure I call Account.get(params.id) and then call a method accountDetailsCommand = populateCommandFromAccount(account) which calls new AccountDetailsCommand() and then return accountDetailsCommand to the view - no problem. in edit{} I'm basically trying to do the same thing, but add error messages as well. All works, apart from the error messages. Do I need to add all the properties of AccountDetailsCommand to the request so that it can be instantiated automatically in the edit{} closure ? that is account/edit?name=zxc&country=ytr&telephone=terte&.... I'll look at the code again tomorrow and aim to come back with a Hello World application. Thanks Martin
Hide
Martin Flower added a comment -

Looking again at the documentation, I see that command objects are designed to handle form submission. I have used them also for displaying data. In my database I have many different domain objects - I retrieve and enrich selected information from these to display on the screen, and to allow the user selected updates. I use a command object to display the information, and the same command object to retrieve information for update. So I use new() in my show{} closure (never a problem). Today I have stopped using new() in my edit{} closure, and I reference the command object in the closure parameters - this instantiates a command with just an id field, everything else null. I need to call command.clearErrors(), then populate the command details from the selected domain objects, I can then populate errors with any warnings that the users wish to see highlighted (which was the original requirement).

In summary, this JIRA can be set to resolved. Is my usage of command object for data display unusual (new() command in show{}) ? Is there a better way ?

Show
Martin Flower added a comment - Looking again at the documentation, I see that command objects are designed to handle form submission. I have used them also for displaying data. In my database I have many different domain objects - I retrieve and enrich selected information from these to display on the screen, and to allow the user selected updates. I use a command object to display the information, and the same command object to retrieve information for update. So I use new() in my show{} closure (never a problem). Today I have stopped using new() in my edit{} closure, and I reference the command object in the closure parameters - this instantiates a command with just an id field, everything else null. I need to call command.clearErrors(), then populate the command details from the selected domain objects, I can then populate errors with any warnings that the users wish to see highlighted (which was the original requirement). In summary, this JIRA can be set to resolved. Is my usage of command object for data display unusual (new() command in show{}) ? Is there a better way ?
Hide
Martin Flower added a comment -

ok, no clearErrors() in 1.1 ... but otherwise it works

Show
Martin Flower added a comment - ok, no clearErrors() in 1.1 ... but otherwise it works
Hide
Graeme Rocher added a comment -

I'll let Jeff comment on alternative options

Show
Graeme Rocher added a comment - I'll let Jeff comment on alternative options
Hide
Jeff Brown added a comment -

Martin,

As you noted, Grails' "command objects" (probably not the best name we could have used) are really designed to help support form submission. It sounds like you are using them for a different purpose. My recommendation is not to do that. If you have these classes that you want to populate in a controller for the purpose of sending those objects into the view for rendering and you want those objects to be validateable, define a class under src/groovy/com/mypackage/etc and mark it as @Validateable. If you want to accept form submission parameters and have them automatically bound to an object and validated, use command objects.

I hope that makes sense.

Show
Jeff Brown added a comment - Martin, As you noted, Grails' "command objects" (probably not the best name we could have used) are really designed to help support form submission. It sounds like you are using them for a different purpose. My recommendation is not to do that. If you have these classes that you want to populate in a controller for the purpose of sending those objects into the view for rendering and you want those objects to be validateable, define a class under src/groovy/com/mypackage/etc and mark it as @Validateable. If you want to accept form submission parameters and have them automatically bound to an object and validated, use command objects. I hope that makes sense.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: