0

It's keep giving me that error and I don't know how to focus on the problem or where to search it's keep asking me about the constructor but I'm using lombok so why should I do the constructor, I really don't know what is the problem with the code.

this is the user model code bellow :

package com.muskiltak.v1.model;

import lombok.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "users")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@Column(name = "username")
private String username;

@Column(name = "email")
private String email;

@Column(name = "phone")
private Integer phone;

@Column(name = "password")
private String password;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable( name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
}

,this is the Role model code bellow:

package com.muskiltak.v1.model;

import com.muskiltak.v1.utility.enums.Roles;
import lombok.*;

import javax.persistence.*;

@Entity
@Table(name = "roles")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@Enumerated(EnumType.STRING)
@Column(name = "name")
private Roles name;
}

and this is the AuthController code:

package com.muskiltak.v1.controller;

import com.muskiltak.v1.utility.enums.Roles;
import com.muskiltak.v1.model.Role;
import com.muskiltak.v1.model.User;
import com.muskiltak.v1.repository.RoleRepo;
import com.muskiltak.v1.repository.UserRepo;
import com.muskiltak.v1.service.UserDetailsImpl;
import com.muskiltak.v1.utility.JWT.JwtUtils;
import com.muskiltak.v1.utility.payload.request.LoginRequest;
import com.muskiltak.v1.utility.payload.request.RegisterRequest;
import com.muskiltak.v1.utility.payload.response.JwtResponse;
import com.muskiltak.v1.utility.payload.response.MessageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/v1")
public class AuthController {

@Autowired
AuthenticationManager authenticationManager;

@Autowired
UserRepo userRepository;

@Autowired
RoleRepo roleRepository;

@Autowired
PasswordEncoder encoder;

@Autowired
JwtUtils jwtUtils;


@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {

    Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

    SecurityContextHolder.getContext().setAuthentication(authentication);
    String jwt = jwtUtils.generateJwtToken(authentication);

    UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
    List<String> roles = userDetails.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toList());

    return ResponseEntity.ok(new JwtResponse(jwt,
            userDetails.getId(),
            userDetails.getUsername(),
            userDetails.getEmail(),
            userDetails.getPhone(),
            roles));
}

@PostMapping("/register")
public ResponseEntity<?> registerUser(@Valid @RequestBody RegisterRequest registerRequest) {
    if (userRepository.existsByUsername(registerRequest.getUsername())) {
        return ResponseEntity
                .badRequest()
                .body(new MessageResponse("Error: Username is already taken!"));
    }

    if (userRepository.existsByEmail(registerRequest.getEmail())) {
        return ResponseEntity
                .badRequest()
                .body(new MessageResponse("Error: Email is already in use!"));
    }

    if (userRepository.existsByPhone(registerRequest.getPhone())) {
        return ResponseEntity
                .badRequest()
                .body(new MessageResponse("Error: Phone Number is already in use!"));
    }

    // Create new user's account
    User user = new User(
            registerRequest.getUsername(),
            registerRequest.getEmail(),
            registerRequest.getPhone(),
            encoder.encode(
                    registerRequest.getPassword()
            )
    );

    Set<String> strRoles = registerRequest.getRole();
    Set<Role> roles = new HashSet<>();

    if (strRoles == null) {
        Role userRole = roleRepository.findByName(Roles.USER)
                .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
        roles.add(userRole);
    } else {
        strRoles.forEach(role -> {
            switch (role) {
                case "admin":
                    Role adminRole = roleRepository.findByName(Roles.ADMIN)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(adminRole);

                    break;
                case "moderator":
                    Role moderatorRole = roleRepository.findByName(Roles.MODERATOR)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(moderatorRole);

                    break;
                case "corp":
                    Role corpRole = roleRepository.findByName(Roles.CORP)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(corpRole);

                    break;
                default:
                    Role userRole = roleRepository.findByName(Roles.USER)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(userRole);
            }
        });
    }

    user.setRoles(roles);
    userRepository.save(user);

    return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
}
}

all the time keeping giving me the same error as you can see in the image below even when I run it with the debug mode it keeps asking me to make the constructor and I'm using the lombok as you can see

enter image description here

  • Please [edit] the question and include the error as text, not as image. --- A remark on the code: [Field injection should be avoided](https://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it) – Turing85 Dec 27 '20 at 00:15

3 Answers3

4

As per lombok, the constructor that will be created will have all property types in same sequence as defined. Hence, your @AllArgsConstructor annotation will create a constructor like below:

public User(long id, String username, Integer phone, String password, HashSet<Role> roles);

In your line 94, you are trying to provide four values to a constructor requiring 6. You can solve your problem with below possible ways:

  1. Pass some default value for id and null for roles in line 94 in your AuthController.
  2. Write the constructor required yourself with only four arguments.
  3. Remove @AllArgsConstructor annotation and create required constructors only instead of providing an all argument constructor.
Dharman
  • 30,962
  • 25
  • 85
  • 135
Avinash Sagar
  • 527
  • 4
  • 10
1

You're generating two constructors using Lombok: one that takes no arguments and one that takes all fields as arguments. You're calling a non-existent constructor that takes only a subset of the fields of User.

Replacing this:

// Create new user's account
User user = new User(
        registerRequest.getUsername(),
        registerRequest.getEmail(),
        registerRequest.getPhone(),
        encoder.encode(
            registerRequest.getPassword()
        )
);

with the code below should work.

// Create new user's account
User user = new User();
user.setUsername(registerRequest.getUsername());
user.setEmail(registerRequest.getEmail());
user.setPhone(registerRequest.getPhone());
user.setPassword(encoder.encode(registerRequest.getPassword()));

Alternatively, you could manually add a constructor with these 4 parameters to the User class.

myeongkil kim
  • 2,465
  • 4
  • 16
  • 22
timsmelik
  • 732
  • 3
  • 11
1

You are using a constructor that is neither the no-arguments constructor, nor a constructor that receives all arguments. You pass to your constructor the username, email, phone and password. This is four fields of your User class, but that class has more fields, so that constructor does not match any of the constructors generated by Lombok. You must either write that constructor explicitly or pass the appropriate parameters so it will match one of the Lombok-generated constructors.

JustAnotherDeveloper
  • 2,061
  • 2
  • 10
  • 24