DEV Community

loading...

Step by step procedure on how to implement custom-like javax.validator using Jersey and Jax-rs in Springboot Application

logronj profile image Janel ・2 min read

Today I'm trying to implement a validator using jaxrs, I'm only familiar with springmvc using spring-starter-validator and hibernate-validator wherein the errors are bind in the BindingResult using @restController. So as I was working around I made this solution works.

  1. create a custom global mapper for constraintViolationException.
public class ConstraintValidatorExceptionMapper implements ExceptionMapper<ConstraintViolationException>{

    @Override
    public Response toResponse(ConstraintViolationException exception) {
        final Map<String, String> errorResponse =
                exception.getConstraintViolations()
                  .stream()
                  .collect(Collectors.toMap(o -> o.getPropertyPath().toString(), o -> o.getMessage()));

        return Response
                 .status(Response.Status.BAD_REQUEST)
                 .entity(errorResponse)
                 .build();
    }

}
Enter fullscreen mode Exit fullscreen mode
  1. Next create a payload request for your API.
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@CompareDates
public class ViewTransactionHistoryRequest {

    @JsonProperty
    private String customerId;
    @JsonProperty
    private String cardSerNo;
    @JsonProperty 
    @NotBlank(message="contact id must not be null or empty")
    private String contactId;
    @JsonProperty
    private String dateFrom;
    @JsonProperty
    private String dateTo;
    @JsonProperty 
    private Double amountFrom;
    @JsonProperty
    private Double amountTo;
    @JsonProperty
    private int page;
}
Enter fullscreen mode Exit fullscreen mode
  1. Notice the @CompareDates I created a sample annotation validator for validating dates.
@Constraint(validatedBy = DateValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CompareDates {

    String message() default "dateTo should not be less than dateFrom!";

    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

}
Enter fullscreen mode Exit fullscreen mode
  1. Next for our endpoint we need to add @Valid to trigger the validation.
    @POST
    @Path("/view-transaction")
    @Consumes("application/json")
    @ApiOperation(value = "Get transaction history")
    public Object fiterBy(@RequestBody @Valid ViewTransactionHistoryRequest request) {
        LOGGER.info("Get account contact transaction history"); 
        return accountContactService.viewTransactionHistory(request);
    }
Enter fullscreen mode Exit fullscreen mode
  1. Then register your custom validator in your jersey configuration file.
@Component
public class JerseyConfig extends ResourceConfig {

  @Value("${spring.jersey.application-path}")
  private String basePath;

  public JerseyConfig() {
    register(ConstraintValidatorExceptionMapper.class);
  }
}
Enter fullscreen mode Exit fullscreen mode

That's it! Sample response in postman should be something like this: Alt Text

In this way we can provide to the client which fields have errors instead of just relying the 400 bad request exception response.

Discussion (0)

pic
Editor guide