javaspringspring-bootspring-data-jpaspring-validation

Cannot use repository inside custom request class for request validations in spring boot


So I am trying to validate email and name in UserCreateRequest class but @Wired doesn't work and userRepository is null

UserCreateRequest.java:

@Getter
@Setter
@Component
public class UserCreateRequest {

    private UserRepository userRepository;

    public UserCreateRequest() {
    }

    @Autowired
    public UserCreateRequest(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @NotBlank(message = "Name is mandatory")
    @Size(min = 2, max = 20, message = "Name should be between 2 and 20 characters")
    private String name;


    @NotBlank(message = "Email is mandatory")
    @Email(message = "Email should be valid")
    private String email;

    @NotNull(message = "Date of birth is mandatory")
    @DateFormatRule(message = "Date of birth should be in yyyy-MM-dd format")
    private String dob;

    public User validated() {
        if (userRepository.findUserByEmail(email).isPresent()) {
            throw new RuntimeException("Email already exists");
        }
        if (userRepository.findUserByName(name).isPresent()) {
            throw new RuntimeException("Name already exists");
        }


        User user = new User();
        user.setName(name);
        user.setEmail(email);
        user.setDob(LocalDate.parse(dob));

        return user;
    }
}

UserController.java:

@PostMapping
public ResponseEntity<User> addUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {

    User validatedData = userCreateRequest.validated();

    User createdUser = this.userService.addUser(validatedData);

    return ResponseEntity.ok(createdUser);
}

Error I am getting when sending request:

(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.base/java.lang.Thread.run(Thread.java:1623)\n",
    "message": "Cannot invoke \"com.test.restapi.repository.UserRepository.findUserByEmail(String)\" because \"this.userRepository\" is null",
    "path": "/api/students"

I want to check database if user name or email already exists from the request class, without checking that from controller.

is there any way to use userRepository in UserCreateRequest class like that?

I could not find the exact solution I was looking for


Solution

  • UserCreateRequest is not a spring-managed component, it's created by mapping request payload to the class. You can:

    1. Autowire repository manually by injecting the context in the controller - just don't do that, you are already mixing responsibilities by adding business logic (validation and mapping) to the dto.
    2. Create validation annotations to apply on the fields - @UniqueName, @UniqueEmail. Their validators can be easily made into spring-managed components.