Issue
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.
Check auth token in the http request against another service to verify access permissions.
Validate a number of fields in request body such as category, type etc by making calls to another service.
Generic null & empty checks. Currently I'm using spring validation to do this.
Solution
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
- 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.
Answered By - MD9
Answer Checked By - Timothy Miller (JavaFixing Admin)