Reputation: 2377
In Spring boot. I want to do field validation and return an error if the input does not exist in the database. I am trying to write the custom annotation for multiple input fields. The controller is as below
@RestController
@Api(description = "The Mailer controller which provides send email functionality")
@Validated
public class SendMailController {
@Autowired
public SendMailService sendemailService;
org.slf4j.Logger logger = LoggerFactory.getLogger(SendMailService.class);
@RequestMapping(method = RequestMethod.POST, value = "/sendMail", consumes = {MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = {"text/xml", "application/json"})
@ResponseBody
@Async(value = "threadPoolTaskExecutor")
@ApiOperation("The main service operation which sends one mail to one or may recipient as per the configurations in the request body")
public Future<SendMailResult> sendMail(@ApiParam("Contains the mail content and configurations to be used for sending mail") @Valid @RequestBody MailMessage message) throws InterruptedException {
SendMailResult results = new SendMailResult();
try {
sendemailService.sendMessages(message);
long txnid = sendemailService.createAudit (message);
results.setTxnid (txnid);
results.setStatus("SUCCESS");
} catch(MessagingException | EmailServiceException e) {
logger.error("Exception while processing sendMail " + e);
results.setStatus("FAILED");
// TODO Handle error create results
e.printStackTrace();
} catch(Exception e) {
logger.error("Something went wrong " + e);
results.setStatus("FAILED");
// TODO Handle error create results
e.printStackTrace();
}
return new AsyncResult<SendMailResult>(results);
}
}
one DTO that is mapped with request
public class MailContext {
@NotNull
private String clientId;
@NotNull
private String consumer;
public int getClientId() {
return Integer.parseInt(clientId);
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String toJson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String writeValueAsString = mapper.writeValueAsString(this);
return writeValueAsString;
}
}
Request xml
<mailMessage>
<mailContext>
<clientId>10018</clientId>
<consumer>1</consumer>
</mailContext>
</mailMessage>
if these not present in database send error message else call service method.
Please suggest how to write such custom annotation with the error.
Upvotes: 0
Views: 5361
Reputation: 785
I know another way to validate this. Inside your controller, you can register a validator.
@InitBinder
public void setup(WebDataBinder webDataBinder) {
webDataBinder.addValidators(dtoValidator);
}
Where dtoValidator is an instance of Spring Bean, for example, which must implements org.springframework.validation.Validator.
So, you just have to implement two methods: supports() and validate(Object target, Errors errors);
Inside supports() method you can do whatever you want to decide whether the object should be validated by this validator or not. (for example, you can create an interface WithClientIdDto and if the tested object isAssignableFrom() this interface you can do this validation. Or you can check your custom annotation is presented on any field using reflection)
For example: (AuthDtoValidator.class)
@Override
public boolean supports(Class<?> clazz) {
return AuthDto.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
final AuthDto dto = (AuthDto) target;
final String phone = dto.getPhone();
if (StringUtils.isEmpty(phone) && StringUtils.isEmpty(dto.getEmail())) {
errors.rejectValue("email", "", "The phone or the email should be defined!");
errors.rejectValue("phone", "", "The phone or the email should be defined!");
}
if (!StringUtils.isEmpty(phone)) {
validatePhone(errors, phone);
}
}
UPDATE: You can do that.
Create an annotation for example:
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = ClientIdValidator.class)
@Documented
public @interface ClientId {
String message() default "{some msg}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
and implement this validator:
class ClientIdValidator implements ConstraintValidator<ClientId, Long> {
@Override
public boolean isValid(Long value, ConstraintValidatorContext context) {
//validation logc
}
}
More details you can find here: https://reflectoring.io/bean-validation-with-spring-boot/
Upvotes: 1