How to @Validate unique username in spring?
Asked Answered
C

4

19

Let's assume that I have a form where I might submit username(@NaturalId) and password for a new user.

I would like to add the user with a unique username. How can I use @Valid annotations to validate this constraint? And if username is not unique how can I display this information in jsp via <form:error/>?

Chic answered 13/6, 2013 at 16:43 Comment(0)
G
30

AFAIK there isn't an annotation to do this. You have two options

One, create a custom validator annotation. Here is a very good example. Make a call to your DAO class and check the availability in the validator implementation

    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {

    return userDAO.userNameAvailable(object); //some method to check username availability
    }

OR

Set unique = true on your property in your entity class.

    @Column(unique = true)
    private String userName;

But this will not work with @valid, instead throw an exception on persistence. You have to use an appropriate logic to handle that.

The first solution isn't fool proof. Check this answer on SO.

The second will will never fail.

UPDATE

As NimChimpsky commented, using both together will be a concrete solution.

Gawain answered 14/6, 2013 at 9:13 Comment(6)
I'd recommend using both methodsYarkand
Well, after digging a bit I feel that the second one is better :) It will never fail unlike the first one.Gawain
um, well that relies on exception handling for when a user inputs a pre existing username, I woul dvalidate user input before trying to persistYarkand
what if there is a concurrent transaction with the same username??Gawain
thats is very unlikely, but it is why I said both methods should used. The column shoul dbe unique, but that does not stop you vaidating input.Yarkand
How solve the problem of the update of object? The userDAO.userNameAvailable(object) would return false. I didn't find so far a smart solution if the validation annotation is on the String field username. In fact in this way I cannot get the id of the object and check if it's an update (ok) or a new insert (ko). thanksLivialivid
V
4

JSR-303 does not support what you want (something like a @Unique constraint). You have to write you own validator. How can this be done is explained here: https://community.jboss.org/wiki/AccessingtheHibernateSessionwithinaConstraintValidator

But before doing that make sure you read this answer: https://mcmap.net/q/384161/-unique-constraint-with-jpa-and-bean-validation

And this sentence from the previous article:

The reason @Unique is not part of the built-in constraints is the fact that accessing the Session/EntityManager during a valiation is opening yourself up for potenital phantom reads.

Vibratile answered 14/6, 2013 at 9:10 Comment(0)
U
1

You can use UserDetailsService prepared spring class, extend and customize it :

@Service
public class LoginDetailsServiceImpl implements UserDetailsService, Serializable {

    @Autowired
    LoginService loginService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (username == "" || username.isEmpty()) {
            throw new UsernameNotFoundException(String.format("User %s is invalid!", username));
        }
        Login login = loginService.find(username);
        if (login == null) {
            throw new UsernameNotFoundException(String.format("User %s does not exist!", username));
        }
        if (!loginService.scheduleChecking(login.getScheduled())) {
            throw new UsernameNotFoundException(String.format("User %s is not authorized this time!", username));
        }
      //....
Unworldly answered 3/12, 2016 at 6:40 Comment(0)
C
0

I think there is a way to find a Unique User name. You Have to use Native Query to perform the Particular Task.

You have to perform this query on your repository interface

@Query(value = "SELECT * FROM customers_details WHERE username = :username , nativeQuery = true)
public List findEmaiList(@Param("username ") String username , @Param("id") Long id);

You can get similar data from the query and pass validation whatever you want. you can also create a separate Unique API for your convenience. You can also find different Unique parameters like Email or Mobile using this query

Calpe answered 4/3, 2022 at 14:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.