DEV Community

Janel
Janel

Posted on

3 2

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

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.

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay