简体   繁体   中英

Multithreading in Service layer in Java

I am designing web app with Spring MVC.

I have some problem in implementing safely updating e-mail and registering new user. E-mail is unique for every user.

It is my method, which is invoked by controller for registering user:

@Override
    public void registerUser(Client newUser) throws DuplicateEmailException {

        if(!isEmailUnique(newUser.getEmail())){
            throw new DuplicateEmailException("User with the same email is registered"
                    + " in system already");
        }

        newUser.setPassword(encodePassword(newUser.getPassword()));
        newUser.setRole(UserRole.ROLE_CLIENT);
        newUser.setStatus(UserStatus.ACTIVE);
        newUser.setEmailStatus(EmailStatus.NOTCONFIRMED);
        newUser.setRegistrationTime(LocalDateTime.now());

        clientDao.save(newUser);


    }

It is method for updating email:

@Override
    public void updateUserEmail(String email, String newEmail, String password)
            throws InvalidPasswordException, DuplicateEmailException {
        Client client = getClientByEmail(email);
        if(!isPasswordRight(password, client.getPassword())){
            throw new InvalidPasswordException("Password doesn't match to real");
        }

        if(email.equals(newEmail)){
            return;
        }

        if(!isEmailUnique(newEmail)){
            throw new DuplicateEmailException(
                    "Such email is registered in system already");
        }

        client.setEmail(newEmail);
        client.setEmailStatus(EmailStatus.NOTCONFIRMED);
    }

There is can be situation, when some user clicks button for registering, registerUser(Client newUser) method checks email for uniqueness, at the same moment second user want to update email, and before clientDao.save(newUser) is invoked, updateUserEmail(String email, String newEmail, String password) checks email for uniqueness, and if emails of both users are equals, I will get two the same emails in db - it is unacceptable.

My Service layer is marked with @Translactional annotation, session is automatically flushed before closing transaction, and user is saved in db only after finishing registerUser(..) method

So, tell me please, which instruments in Java multithreading can I use for solving this problem?

You can do this programmatically by rolling the isEmailUnique method into the save functionality and making the save method synchronized.

BUT the better solution is to make the email column have a unique constraint in the db, to make sure that no duplicates can ever make it into your dataset no matter where in the app, or even which app, they come from.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM