views:

146

answers:

1

Hello

I am new to grails and trying to create a form which allows a user to change the email address associated with his/her account for a site I am creating.

It asks for the user for their current password and also for the new email address they want to use. If the user enters the wrong password or an invalid email address then it should reject them with an appropriate error message.

Now the email validation can be done through constraints in grails, but the password change has to match their current password. I have implemented this check as a method on a service class.

See code below:

def saveEmail =
{
    def client = ClientUser.get(session.clientUserID)
    client.email = params.email
    if(clientUserService.checkPassword(session.clientUserID , params.password) ==false)
    {
        flash.message = "Incorrect Password"
        client.discard()
        redirect(action:'changeEmail')
    }    
    else if(!client.validate())
    {
         flash.message = "Invalid Email Address"
         redirect(action:'changeEmail')
    }
    else
    {
        client.save();
        session.clientUserID = null;
        flash.message = "Your email address has been changed, please login again"
        redirect(controller: 'clientLogin' , action:'index')
    }
}

Now what I noticed that was odd was that if I entered an invalid email then it would not save the changes (as expected) BUT if I entered the wrong password and a valid email then it would save the changes and even write them back into the database even though it would give the correct "invalid password" error message.

I was puzzled so set break points in all the if/else if/else blocks and found that it was hitting the first if statement as expected and not hitting the others , so it would never come accross a call to the save() method, yet it was saved anyway.

After a little research I came accross documentation for the discard() method which you can see used in the code above. So I added this but still no avail. I even tried using discard then reloading the client object from the DB again but still no dice.

This is very frustrating and I would be grateful for any help, since I think that this should surely not be a complicated requirement!

+1  A: 

Grails closes your Hibernate session at the end of the web request, which will flush out the changed object. The object's connected to your Hibernate session because you got hold of it via Hibernate (get()). If you want to avoid having the change flushed, you need to use discard().

This is done automatically by a failing validator, which is why you're not having to do it for a validation fail.

You'd simplify the code, however, by either moving this logic to a custom validator on one of your ClientUser fields, which would automatically discard the object on failure, or by using a Grails command object, which could also encapsulate the verification logic. Then you'd just check for errors on the command object.

John Stoneham
yes, but that is what is puzzeling me , I am using discard and this is working on the integration test but not on the web
Remember, integration tests roll back your transaction at the end. At the web, your transaction will eventually commit.
John Stoneham