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

About Author

Author Image
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

Request for Proposal

Name is required

Comment is required

Sending message..