Home > Mobile >  Network calls inside custom validations in spring boot
Network calls inside custom validations in spring boot

Time:09-21

I need to validate a number of fields in my REST Api. Is there a specific pattern to do this ? My api is cluttered with these validation calls.

  1. Check auth token in the http request against another service to verify access permissions.

  2. Validate a number of fields in request body such as category, type etc by making calls to another service.

  3. Generic null & empty checks. Currently I'm using spring validation to do this.

CodePudding user response:

Check auth token in the http request against another service to verify access permissions

I would suggest validating the token in a filter before the request reaches the controller.

Something like this

  1. Create a new token validation filter
    @Component
    public class TokenValidationFilter extends OncePerRequestFilter {
        private TokenValidationService tokenValidationService;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
                throws ServletException, IOException {
    
            final String authorizationHeader = request.getHeader("Authorization");
            
          boolean isValid = tokenValidationService.validate(authorizationHeader);
            //do authentication here 
            chain.doFilter(request, response);
        }
    }

Add the filter to http filters

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // this just an example you might needed to added before a different filter 
    }
}

Validate a number of fields in request body such as category, type etc by making calls to another service.

Spring allows creating custom constraints. See spring doc.

Example: UniqueUsername interface

@Documented
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD,ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueUsername {
    String message() default "username is not unique";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, UserDto> {
    private final UserService usersService;

    @Override
    public void initialize(UniqueUsername constraintAnnotation) {

    }

    @Override
    public boolean isValid(UserDto value, ConstraintValidatorContext context) {
       return usersService.isUnique(value.getUsername());
    }

}

user dto:


@UniqueUsername(message = "Username is used")
public class UserDto {
    @DecimalMin(value = "0")
    private long id;
    @NotBlank(message = "Username can not be blank")
    private String username;
}

Note that the constraints could be class level like UniqueUsername or filed level like NotBlank.

Generic null & empty checks. Currently I'm using spring validation to do this.

spring validation/constraints is correct.

  • Related