2

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

Diego Borba
  • 1,282
  • 8
  • 22

1 Answers1

2

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.
Chaosfire
  • 4,818
  • 4
  • 8
  • 23
  • Thanks. I have just started learning Spring Boot. Do you have any suggestions for resources where I can see how that kind of stuff is managed in a clean way and what are the best practices, without writing everything in one place so the code can be easily readable? – b. tsutskiridze Aug 18 '23 at 16:26
  • @b.tsutskiridze Try to adhere to the single responsibility principle. In the current context, use custom validation annotations - [just one possible guide](https://www.baeldung.com/spring-mvc-custom-validator), use a mapper to transform dto to entity - [this guide](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application) is about model mapper, but there are other libraries (or you can write your own mapper, if you don't need all the functionalities provided by those libraries). – Chaosfire Aug 18 '23 at 18:46
  • And I would also add, stop using Lombok, it's fine for a school project but debugging under the hood generated code is a pain and I don't wish that on anyone who will maintain your code when working in a team for a project in a company. [Here is a bigger read on the subject](https://medium.com/@vgonzalo/dont-use-lombok-672418daa819). – Radu Sebastian LAZIN Aug 18 '23 at 20:19