0

I'm trying to create a registration form that uses fields from my DTO and my User class. I'm not exactly sure to go about it and could use some help.

I have a User class that looks like this:

@Entity
public class User extends AbstractEntity {

    @NotNull
    private String username;

    @NotNull
    private String pwHash;

    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;
    @Column(name = "phone_number")
    private String phoneNumber;



    public User() {}

    public User(String username, String password) {
        this.username = username;
        this.pwHash = encoder.encode(password);
    }

    public String getUsername() {
        return username;
    }

    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    public boolean isMatchingPassword(String password) {
        return encoder.matches(password, pwHash);
    }

// ---> Removed Getters and setters removed for brevity. 

The registration form originally was set up to ask for a username/password pair, and then ask the user to confirm the password by typing it in again. So the associated DTO extended the LoginFormDTO and added an additional field for password verification. When I only asked for a username and password I was able to complete the registration and update those columns in my database. However now I'd like to add additional user information during registration.

My data transfer object has been updated to look like this... (I've tried this with and without the @Column annotations.

public class RegisterFormDTO extends LoginFormDTO{

    private String verifyPassword;

    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;
    @Column(name = "phone_number")
    private String phoneNumber;



    public String getVerifyPassword() {
        return verifyPassword;
    }

    public void setVerifyPassword(String verifyPassword) {
        this.verifyPassword = verifyPassword;
    }

    public String getFirstName() {
        return firstName;
    }
// additional pojo getters and setters

My LoginFormDTO looks like this...

public class LoginFormDTO {

    @NotNull
    @NotBlank
    @Size(min = 3, max = 20, message = "Invalid username. Must be between 3 and 30 characters.")
    private String username;

    @NotNull
    @NotBlank
    @Size(min = 5, max = 20, message = "Invalid password. Must be between 5 and 30 characters.")
    private String password;



    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


}

My AuthenticationController's registration method looks like this

    @PostMapping("/register")
    public String processRegistrationForm(@ModelAttribute @Valid RegisterFormDTO registerFormDTO,
                                          Errors errors, HttpServletRequest request,
                                          Model model) {

        if (errors.hasErrors()) {
            model.addAttribute("title", "Register");
            return "register";
        }

        User existingUser = userRepository.findByUsername(registerFormDTO.getUsername());

        if (existingUser != null) {
            errors.rejectValue("username", "username.alreadyexists", "A user with that username already exists");
            model.addAttribute("title", "Register");
            return "register";
        }

        String password = registerFormDTO.getPassword();
        String verifyPassword = registerFormDTO.getVerifyPassword();
        if (!password.equals(verifyPassword)) {
            errors.rejectValue("password", "passwords.mismatch", "Passwords do not match");
            model.addAttribute("title", "Register");
            return "register";
        }

        User newUser = new User(registerFormDTO.getUsername(), registerFormDTO.getPassword(), registerFormDTO.getFirstName(), registerFormDTO.getLastName(), registerFormDTO.getPhoneNumber(), registerFormDTO.getEmail());
        userRepository.save(newUser);
        setUserInSession(request.getSession(), newUser);

        return "redirect:";
    }

I'm not sure how to create a new user from the dto and the user class. I'm able to set the username and password but can't seem to add user info like firstName, lastName, phoneNumber or email. The database adds the id, pw_hash and username. What is the best way to go adding these fields so that they show up in the database? Thank you in advance. I'm learning so much from this helpful community!

Abby Howe
  • 86
  • 1
  • 12
  • Your DTO should have all fields that you later on need in the *User* class. – mentallurg May 21 '20 at 23:07
  • Show us your class *LoginFormDTO*. Doesn't it have fields *firstName*, *lastName*, etc.? – mentallurg May 21 '20 at 23:09
  • @mentallurg I wondered if that would do the trick. I’ll give that a shot. I did not include those fields in LoginFormDTO but it makes sense to include them in the RegistrationDTO. Should I just use this format: private String firstName and do I need getters and setters? It really seems redundant since they are already in the User class. – Abby Howe May 21 '20 at 23:13
  • The class *RegisterFormDTO* extends class *LoginFormDTO*. This means that your object *registerFormDTO* has also *all* the fields inherited from the class *LoginFormDTO*. – mentallurg May 21 '20 at 23:16
  • @mentallurg I added the LoginFormDTO above. I tried adding in `firstName`, `lastName` etc.. and the login worked but would not update the database with the additional information. I'm still a little unsure about if I should extend my LoginFormDTo or just add fields? – Abby Howe May 22 '20 at 01:59
  • Each class should have its own purpose, otherwise it will be messy. What is login? Normally this is only user name and password. First name, last name have nothing to do with login. Right? Means, it is not a good idea to add such fields into that class. Then, we should add it to the *RegisterFormDTO*: *firstName*, *lastName*, *phoneNumber*. – mentallurg May 22 '20 at 02:27

1 Answers1

1

How about extending RegisterFormDTO class with fields: firstName, lastName, phoneNumber, email?

Then, your User class should have another constructor that supports more than username and password. In this case to limit the number of arguments in the constructor you can use a builder design pattern.

You can read more here: Managing constructors with many parameters in Java


And one more thing about naming convention, if your name contains uppercase shortcut that is longer than two characters you should proceed with PascalCase: RegisterDTO -> RegisterDto.

See: Java Naming Convention with Acronyms

mslowiak
  • 1,688
  • 12
  • 25
  • Formally you are right. In a team of 10 developers working on a project 1-2 years such things are obvious. But she is *a beginner* and as I understand she is doing that probably *alone*. If you are a beginner, it is hard to understand the value of strictly following some coding style :) – mentallurg May 21 '20 at 23:20
  • @mentallurg This is why I left some links to read more. There is always place for improvement but you need to be somehow guided :) – mslowiak May 21 '20 at 23:21
  • @mslowiak thanks for the tips! my RegisterFormDto is extended by LoginFormDto. Should I extend that by the User class? – Abby Howe May 22 '20 at 02:03
  • @AbigailHowe It would be better to define explicit those 4 fields in RegisterFormDto rather than extending from User class. You need to treat dtos classes like something different than entities – mslowiak May 22 '20 at 07:37
  • I've defined those fields but am not able to get that data to show up in the MySQL database. There must be something that I'm missing. @mslowiak – Abby Howe May 22 '20 at 13:32
  • @mslowiakTo be clear, the id, the pw_hash and username are showing up in the database, just not the firstname, lastname, email etc... – Abby Howe May 22 '20 at 13:36
  • @AbigailHowe would you mind updating the code in question? :) Then we can check what is wrong with that – mslowiak May 22 '20 at 16:10
  • @mslowiak I updated the code above. Thank you so much for helping me! – Abby Howe May 22 '20 at 16:54
  • @AbbyHowe Looks like there is no actual version for User class because there is no constructor for 4 additional fields. Have you still a problem with that code or you are done? – mslowiak May 23 '20 at 08:38
  • @mslowiak I updated my code and question here. https://stackoverflow.com/q/61965394/9679359 – Abby Howe May 23 '20 at 13:42