1

I have an administration panel where i can add users. In insert form i have USERNAME, PASSWORD (no confirm-password), and some ordinary fields like name, surname,....

When i insert a new user, i want that hibernate will validate it:

  • username not null
  • unique username in db (with an unique index on table)
  • password not null (for now, no length controls)

until here, everything is working fine.

As in future i will store encrypted passwords, in Edit form, i have normal editable fields like username, name, but i didn't put password. instead i put new password field just in case i want to change it (not mandatory).

my edit form:

<!-- 
- username 
-->                                                                 
<div class="form-group">
   <label class="col-sm-4 control-label">Username*:</label>
   <div class="col-sm-8" ><input class="form-control" type="text" data-th-field="*{username}" placeholder="Username" th:errorclass="'has-error-input'"></input></div>
</div>  


<!-- 
- password 
- fingo password
-->                                                                 
<div class="form-group">
   <label class="col-sm-4 control-label">Password:</label>
   <div class="col-sm-8" >******</div>
</div>  


<!-- 
- new password
- (if i want to change it) 
-->                                                                 
<div class="form-group">
   <label class="col-sm-4 control-label">New Password:</label>
   <div class="col-sm-8" ><input class="form-control" type="password" id="password_new" name="password_new" placeholder="New Password"></input></div>
</div>  

As you can see the password_new field is a normal tag, without using spring notation. I will retrieve this as parameter in controller and i will check if new password was written or no.

Now the problem: when i submit the form, i get validation error, as password is null. I'm asking you this:

  1. am i on a good way to do this?

  2. is it possible skip a validation (password) in hibernate on update, but set as mandatory on insert? and then update all fields except password (you will see that i commented the line userToUpdate.setPassword(user.getPassword());)?

  3. could be better remove new password field from edit form, and change password in a page where i update only the password?

  4. is it a stupid / unsafe idea to set an hidden field called 'password' in edit form containing the encrypted password, so it will not give me validation errors? thinking for a second, i think it's really not a good idea, as someone can see encrypted password just looking the source code of the page. having a encrypted password "in clear" can be dangerous / unsafe?

User.java (model)

@NotNull(message = "PASSWORD cannot be null")
@NotEmpty(message = "PASSWORD cannot be null")
@Size(max = 50, message = "Max 50 char")
@Column(name = "password", length = 50)
private String password;

UserDao.java

@Override
public void updateUser(User user) throws UserNotFoundException {
    User userToUpdate = getUser(user.getId());
    userToUpdate.setUsername(user.getUsername());
    //userToUpdate.setPassword(user.getPassword());
    userToUpdate.setNome(user.getNome());
    userToUpdate.setCognome(user.getCognome());
    userToUpdate.setEmail(user.getEmail());
    userToUpdate.setEnabled(user.getEnabled());
    userToUpdate.setRole(user.getRole());
    getCurrentSession().update(userToUpdate);
}

UserController.java

@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String editingUser(@Valid @ModelAttribute User user,
        BindingResult result, RedirectAttributes redirectAttrs,
        @RequestParam(value = "action", required = true) String action,
        @RequestParam(value = "password_new") String password_new
        ){

    logger.info("IN: User/edit-POST: " + action);

    List<Role> user_roles = RoleService.getRoles();


    if (action.equals("abort")) 
    {   
        /**
         * message
         */           
        String message = "Edit not saved";          
        redirectAttrs.addFlashAttribute("message", message);
        redirectAttrs.addFlashAttribute("message_class", "alert-warning");

        redirectAttrs.addFlashAttribute("user_roles", user_roles);
    } 
    else if (result.hasErrors()) 
    {
        logger.info("User-edit error: " + result.toString());
        redirectAttrs.addFlashAttribute("org.springframework.validation.BindingResult.user", result);

        redirectAttrs.addFlashAttribute("user", user);

                    /** 
                    * as in my list page i have also the insert form, 
                    * i need to populate the select
                    */
        redirectAttrs.addFlashAttribute("user_roles", user_roles);

        return "redirect:/users/edit?id=" + user.getId();
    } 
    else if (action.equals("save")) 
    {

        try 
        {
            logger.info("User/edit-POST:  " + user.toString());


            /**
             * i see if i changed the password
             */
            logger.info("new password:  " + password_new);

            if (!password_new.equals(""))
                    {
                        user.setPassword(password_new);
                    }
                    else
                    {
                        //nothing, or what?
                    }

                    /**
                    * now i can update the user in DB
                    */
            UserService.updateUser(user);

            /**
             * message
             */            
            String message = "User edited with success";            
            redirectAttrs.addFlashAttribute("message", message);
            redirectAttrs.addFlashAttribute("message_class", "alert-success");


                    /** 
                    * as in my list page i have also the insert form, 
                    * i need to populate the select
                    */
            redirectAttrs.addFlashAttribute("user_roles", user_roles);
        }
        catch (UserNotFoundException e)
        {
            logger.info("User/edit-POST:  id [" + user.getId() + "] not found");

            String message = "User id [" + user.getId() + "] not found!";           
            redirectAttrs.addFlashAttribute("message", message);       
            redirectAttrs.addFlashAttribute("message_class", "alert-danger");                       
        } 
    }

    return "redirect:/users/list";
}

thank you very much

PS. As it's my first application in spring / hibernate / java word, for now i'm storing plain passwords, in future i will encrypt them.

2 Answers 2

1
  1. Sure!

  2. Only if you remove the @Valid annotation. What you could do is to remove the annotation, then set all properties in the controller and before calling the DAO function validate the entity manually:

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    validator = factory.getValidator();
    Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);
    
  3. It's up to you.

  4. Yes, don't do that :)

Sign up to request clarification or add additional context in comments.

3 Comments

You mean say to create custom validator?
your answer is perfect, i still have only one problem: when validation fails on a field (like empty username) i can't pass errors appear to edit form... i always used redirectAttrs.addFlashAttribute("org.springframework.validation.BindingResult.user", result); but here i see errors are in constraintViolations
resolved with import org.springframework.validation.Validator; validator.validate(user, result); . thank you for your support!
1

•username not null

You can use @NotNull in model.

•unique username in db (with an unique index on table)

instead of doing at the time of inserting you can make an AJAX call when username field on form get out of focus to check entered user is exit or not.

While updating you want to update fields without updating password (if its blank)

First of all I would like to tell you that NotEmpty and NotNull annotation from domain model. I don't use the @NotNull and @NotEmpty validations in practice you can refer this article

You can use hibernates dynamic-update to update only those properties which is changed. Go Through this

You can use password field on the edit form and as per your idea you can validate if user enters something in password field then update is required other wise first fetch the object from DB set to updating object then call for hibernate to update the object.

Better Way

To change your models As you said you want to take users FirstName,LastName,other personal details that should be in Person model and all the login account related part in LoginAccount model

So your model becomes like :

Person

  • PersonId
  • FirstName
  • LastName
  • etc.

LoginAccount

  • LoginAccountId
  • UserName
  • Password
  • FK_PersonID

And you make viewmodel for new registration form and change password and edit profile functionalities to update details.

2 Comments

Defining different models is nice idea!! I having the same.
Thank you for your very detailed and clear answer. Unluckily, for this project, Person details aren't very important

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.