I have created Custom ContrainValidator and added the code below. I am passing a bean where I have all my Validation logic. However, it is not working. The Validator is not being invoked.
I have also added my controller class. Somehow code is not flowing in the validator.
ValidCustomClass class
<code>package com.validation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Constraint(validatedBy = MyValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface ValidCustomClass {
String message() default "Invalid request.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
</code>
<code>package com.validation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Constraint(validatedBy = MyValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface ValidCustomClass {
String message() default "Invalid request.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
</code>
package com.validation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Constraint(validatedBy = MyValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface ValidCustomClass {
String message() default "Invalid request.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator class
<code>package com.validation;
import com.model.request.CreateRequest;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyValidator implements ConstraintValidator<ValidCustomClass, CreateRequest> {
private static final String MY_REGEX = "^(.+)@(.+)$";
private final MyService myService;
public MyValidator(MyService myService) {
this.myService = myService;
}
@Override
public void initialize(ValidCustomClass constraintAnnotation) {
// DO nothing here
}
@Override
public boolean isValid(final CreateRequest value, final ConstraintValidatorContext context) {
if (dosSomething(value)) return false;
return true;
}
}
</code>
<code>package com.validation;
import com.model.request.CreateRequest;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyValidator implements ConstraintValidator<ValidCustomClass, CreateRequest> {
private static final String MY_REGEX = "^(.+)@(.+)$";
private final MyService myService;
public MyValidator(MyService myService) {
this.myService = myService;
}
@Override
public void initialize(ValidCustomClass constraintAnnotation) {
// DO nothing here
}
@Override
public boolean isValid(final CreateRequest value, final ConstraintValidatorContext context) {
if (dosSomething(value)) return false;
return true;
}
}
</code>
package com.validation;
import com.model.request.CreateRequest;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyValidator implements ConstraintValidator<ValidCustomClass, CreateRequest> {
private static final String MY_REGEX = "^(.+)@(.+)$";
private final MyService myService;
public MyValidator(MyService myService) {
this.myService = myService;
}
@Override
public void initialize(ValidCustomClass constraintAnnotation) {
// DO nothing here
}
@Override
public boolean isValid(final CreateRequest value, final ConstraintValidatorContext context) {
if (dosSomething(value)) return false;
return true;
}
}
Controller class
<code>package com.controller;
import com.model.request.CreateRequest;
import com.model.response.MyResponse;
import com.service.MyService;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Validated
@RequestMapping("/endpoint")
public class MyController {
private final MyService myService;
MyController(MyService myService) {
this. myService = myService;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public MyResponse create(@RequestBody @Valid CreateRequest request) throws Exception {
return myService.create(request);
}
}
</code>
<code>package com.controller;
import com.model.request.CreateRequest;
import com.model.response.MyResponse;
import com.service.MyService;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Validated
@RequestMapping("/endpoint")
public class MyController {
private final MyService myService;
MyController(MyService myService) {
this. myService = myService;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public MyResponse create(@RequestBody @Valid CreateRequest request) throws Exception {
return myService.create(request);
}
}
</code>
package com.controller;
import com.model.request.CreateRequest;
import com.model.response.MyResponse;
import com.service.MyService;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Validated
@RequestMapping("/endpoint")
public class MyController {
private final MyService myService;
MyController(MyService myService) {
this. myService = myService;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public MyResponse create(@RequestBody @Valid CreateRequest request) throws Exception {
return myService.create(request);
}
}
finally I have added @ValidCustomClass
on CreateRequest
.
Am I missing something here? There are no errors but the validator in not invoked.
What have I tried?
- I tried creating default constructor and assigning null to myService in it as suggested in many of the stackoverflow question but I observed that the default constructor is invoked after the parameterised assigning myService null leading to
NullPointerException
- I tried using @Autowired but somehow it did not work either. I thought I need to make
MyValidator
a bean as well but that also did not work.
2