I'm trying to do some validation on a domain class object, but I get a strange exception when I call the 'validate' method. I have a form where I input some data: Here is the code for my form:
<body>
<div id='register'>
<div class='inner'>
<div class='fheader'>Register</div>
<g:if test='${flash.message}'>
<div class='login_message'>${flash.message}</div>
</g:if>
<form action='<g:createLink controller="register" action="create" />' method='POST' id='registerForm' class='cssform' autocomplete='off'>
<p>
<label for='username'>Username:</label>
<input type='text' class='text_' name='username' id='username'/>
</p>
<p>
<label for='password'>Password:</label>
<input type='password' class='text_' name='password' id='password'/>
</p>
<p>
<label for='passwordConfirmation'>Confirm:</label>
<input type='password' class='text_' name='passwordConfirm' id='passwordConfirmation'/>
</p>
<p>
<input type='submit' id="submit" value='REGISTER'/>
</p>
</form>
</div>
</div>
</body>
Here is the code for my controller. The method that recieves the POST is 'create'.
package genealogicaltree
import gentree.security.UserCommand
import grails.converters.JSON
import org.springframework.security.access.annotation.Secured
@Secured('permitAll')
class RegisterController {
static allowedMethods = [index:'GET', create:['POST']]
def springSecurityService
def index() {
render(view: 'register')
}
def create() {
def userCommand = new UserCommand(params)
if(userCommand.validate())
render "valid"
else
render "invalid"
}
}
Here is how my domain class looks like:
class UserCommand{
public String username
public String password
public String passwordConfirm
static constraints = {
username size: 6..15, blank: false
password size: 6..15, blank: false
passwordConfirm blank: false
}
}
Using debugging I can see that the data from POST is binded to the userCommand object :
However, I get such an error message:
Here is the console output:
Error |
2015-04-02 15:41:57,180 [http-bio-8080-exec-7] ERROR errors.GrailsExceptionResolver - NotReadablePropertyException occurred when processing request: [POST] /GenealogicalTree/register/create - parameters:
passwordConfirm: password
username: username
password: ***
Invalid property 'username' of bean class [gentree.security.UserCommand]: Bean property 'username' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?. Stacktrace follows:
Message: Invalid property 'username' of bean class [gentree.security.UserCommand]: Bean property 'username' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
Line | Method
->> 20 | create in genealogicaltree.RegisterController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 53 | doFilter in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
| 49 | doFilter in grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter
| 82 | doFilter in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . in java.lang.Thread
The exception is thrown when the code calls 'userCommand.validate()'. I don't understand what am I doing wrong here. Thanks in advance!
You should add getters and setters into your domain class to remove this.
The Grails compiler will generate these methods by default, so for example.
myObject.myValue = "hello";
is the same as
myObject.setMyValue("hello");
However, it is obviously not perfect and you get errors like this! If you're using Grails version < 2.3.2, then this is a known bug and there is a Jira Issue for it, so you can solve it by upgrading your version of Grails.