Using command objects in Grails
Posted By : Akash Sharma | 30-Nov-2013
In this blog I am going to share the details of how to use command object in grails. A command object is a class that is used in conjunction with data binding, usually to allow validation of data that may not fit into an existing domain class.
First of all we have to create a form that submits user details.The name of the form input fields are same as UserCommand class fields name.
userRegistration.gsp
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main"/>
<g:javascript library="jquery"/>
</head>
<body>
<g:formRemote name="saveUser" url="[controller:'user', action:'register']" update="showErrorInSaveUser">
<label for="name">Username</label><g:textField name="name"/><br/>
<label for="emailId">Email Id</label><g:textField name="emailId"/><br/>
<label for="password">Password</label><g:textField name="password"/><br/>
<label for="password2">Renter Password</label><g:textField name="password2"/><br/>
<g:submitButton name="Save User"/>
</g:formRemote>
<div id="showErrorInSaveUser">
<g:render template="/user/userSaveError"/>
</div>
</body>
</html>
_userSaveError.gsp template
This is template for showing error messages.hasError tag is used just to check before rendering error if an error exists.
<div class='value ${hasErrors(bean:command,field:'name','errors')}'>
<div id="nameErrorFromCommand" name="name" >${fieldError(bean:command,field:'name')}</div>
</div>
<div class='value ${hasErrors(bean:command,field:'emailId','errors')}'>
<div id="emailIdErrorFromCommand" name="emailId" >${fieldError(bean:command,field:'emailId')}</div>
</div>
<div class='value ${hasErrors(bean:command,field:'password','errors')}'>
<div id="passwordErrorFromCommand" name="password" >${fieldError(bean:command,field:'password')}</div>
</div>
<div class='value ${hasErrors(bean:command,field:'password2','errors')}'>
<div id="password2ErrorFromCommand" name="password2" >${fieldError(bean:command,field:'password2')}</div>
</div>
UserController file
The command object class must be in same file as of controller class.
package com.oodles.practiceblog.auth
class UserController
{
def userRegistration={}
def register = { UserCommand command ->
log.debug "params for register action :"+params
if (command.hasErrors())
{
command.errors.allErrors.each{ log.debug "error while saving User domain via RegisterCommand :"+it }
render template:"/user/userSaveError",model: [command:command]
return
}
else{
//save user data
}
}
}
class UserCommand
{
String name
String emailId
String password
String password2
def userService
static constraints = {
name nullable: false, blank: false, minSize: 6
//Apply your own validation condition and validate via database
emailId nullable: false, blank: false, email: true, validator: { val, obj ->
if( User.findByEmailId(val) ){
return "com.oodles.practiceblog.auth.UserCommand.emailId.validator"
}
}
//validation condition can be executed from a service
password nullable: false, blank: false, minSize: 8,validator:{ val, obj ->
obj.userService.passwordValidator(val, obj)
}
password2 nullable: false, blank:false, validator: { val, obj ->
if( obj.password != val ){
return "com.oodles.practiceblog.auth.UserCommand.password2.validator"
}
}
}
}
UserService service
Custom validation conditions can be checked in service methods.We just need to return proper message type defined in message.properties file in i18n .
package com.oodles.practiceblog
import com.oodles.practiceblog.auth.UserCommand
class UserService
{
def passwordValidator(String password,UserCommand command)
{
if (command.name && command.name.equals(password)) {
return 'com.oodles.practiceblog.auth.UserCommand.password.validator'
}
}
}
messages.properties in i18n
Custom error messages can be written in this file.
#custom command object validation errors for UserCommand
# {0} for field name
# {1} for class name
# {2} for value in params
# {3} for constraint parameter
com.oodles.practiceblog.auth.UserCommand.name.blank=Property {0} must not be blank
com.oodles.practiceblog.auth.UserCommand.name.minSize.notmet=Property {0} is less than minimum value of {3}
com.oodles.practiceblog.auth.UserCommand.name.nullable=Property {0} must not be blank
com.oodles.practiceblog.auth.UserCommand.emailId.blank=Property Email Address must not be blank
com.oodles.practiceblog.auth.UserCommand.emailId.email.invalid=Invalid Email Address
com.oodles.practiceblog.auth.UserCommand.emailId.nullable=Property Email Address must not be blank
com.oodles.practiceblog.auth.UserCommand.emailId.validator=Email Address as {2} already exists
com.oodles.practiceblog.auth.UserCommand.password.blank=Property {0} must not be blank
com.oodles.practiceblog.auth.UserCommand.password.minSize.notmet=Property {0} is less than minimum value of {3}
com.oodles.practiceblog.auth.UserCommand.password.nullable=Property {0} must not be blank
com.oodles.practiceblog.auth.UserCommand.password.validator=name must be different from password
com.oodles.practiceblog.auth.UserCommand.password2.blank=Property Renter Password must not be blank
com.oodles.practiceblog.auth.UserCommand.password2.nullable=Property Renter Password must not be blank
com.oodles.practiceblog.auth.UserCommand.password2.validator=Property Renter Password must be same as Password
For more information follow this link and this link.
Thanks
Akash Sharma
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Akash Sharma
Akash is a bright Groovy and Grails developer and have worked on development of various SaaS applications using Grails technologies. Akash loves playing Cricket and Tennis