Bean-Validation

Configuration

Achilles allows you to apply Bean Validation (JSR-303) to entities before save, update and load actions.

To activate bean validation, all you need to do is:

A special pre-mutate (INSERT/UPDATE) Interceptor is built when bean validation is enabled.
This interceptor will be the last interceptor to be triggered if more interceptors are registered for an entity.
This way, you can perform functional logic on the entity before invoking bean validation.
The interceptor is bound to the PRE_INSERT and PRE_UPDATE events of the entity lifecycle.

Achilles will apply validation on entity having constraints on field, property or class (custom validation).
Right now Achilles does not validate method arguments or return values.

On validation error, an AchillesBeanValidationException will be thrown. You can setup a try-catch block around this exception for validation error handling.


POST_LOAD Validation

By default, Achilles does not invoke bean validator for the POST_LOAD event. To enable POST_LOAD bean valdation
you must set the POST_LOAD_BEAN_VALIDATION_ENABLE parameter to true. In this case Achilles will register a special
POST_LOAD interceptor to perform bean validation. Please notice that this interceptor will be the first to be invoked.

Please note that the POST_LOAD_BEAN_VALIDATION_ENABLE parameter requires the BEAN_VALIDATION_ENABLE parameter
to be true otherwise it has no effect


Validation group

The default bean validation interceptor will not be invoked for grouped constraints. If you want to use them, you can provide a custom bean validation interceptor.
Below is an example of such interceptor:


    public class Entity {
        @PartitionKey
        private Long id;
    
        @Column
        @NotNull(groups = CustomValidationGroup.class)
        private String name;
    }
    
    public static class CustomValidationInterceptor implements Interceptor<Entity> {
    
        private final Validator validator;
    
        public CustomValidationInterceptor(Validator validator) {
            this.validator = validator;
        }
    
        @Override
        public boolean accepEntity(Class<?> entityClass) {
            if(entityClass != null) return Entity.class.equals(entityClass);
            return false;
        }
        
        @Override
        public void onEvent(Entity entity) {
            Set<ConstraintViolation<Entity>> violations = validator.validate(entity,CustomValidationGroup.class);
            ...
        }
    
        @Override
        public List<Event> events() {
            return asList(PRE_INSERT, PRE_UPDATE);
        }
    }


Extending validation to others lifecycle events

It is possible to extend bean validation to other lifecycle events than PRE_INSERT and PRE_UPDATE. You just need to provide custom bean validation interceptors. Follow the same approach as above