I am trying to learn about Spring Data Validation and in that am trying to create my own Custom Validation Annotation which in this case is @UniqueUser which will validate that my username is unique while creating it. I know I can do in the DB level using unique constraint but am just playing around now.
This is my Annotation interface:
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueUserValidator.class)
@Documented
public @interface UniqueUser {
String message() default "Username already exists";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
And the below is my validator implementation:
@Component
public class UniqueUserValidator implements ConstraintValidator<UniqueUser, String> {
@Autowired
private UserRepo userRepo;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return !userRepo.findByUserName(value).isPresent();
}
}
JPA Repo & User Entity are simple only.
JPA Repo:
@Repository
public interface UserRepo extends JpaRepository<User, Integer> {
public Optional<User> findByUserName(String userName);
}
Entity:
@Entity
@Table(name = "user")
@Getter
@Setter
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "email")
private String email;
@Column(name = "user_name")
@NotEmpty(message = "Username cannot be Empty")
@UniqueUser
private String userName;
@Column(name = "age")
@Min(value = 13, message = "User must be atleast 13 or above to sign in to the platform")
private Integer age;
public User(String email, String userName, Integer age) {
this.email = email;
this.userName = userName;
this.age = age;
}
}
So as you can see I have made use of @Component & @Autowire annotation to make this class as a Bean & Inject the Repo Bean. But still I get this error when I make a request:
2025-03-22T22:18:45.368+05:30 ERROR 33823 --- [data-validation] [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: jakarta.validation.ValidationException: HV000028: Unexpected exception during isValid call.] with root cause
java.lang.NullPointerException: Cannot invoke "com.example.data_validation.repo.UserRepo.findByUserName(String)" because "this.userRepo" is null
Not sure why.