Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity validation before the "beforeSave" RepositoryEventHandler fired

The Spring Data REST docs describe the way to validate entities after the RepositoryEventHandler has fired:

you simply need to register an instance of your validator with the bean whose job it is to invoke validators after the correct event

Is there a way to apply [declarative] JSR-303 validation of entities before they get passed to the "beforeSave" RepositoryEventHandlers?

From what I can see so far debugging, that is not the case and the "beforeSave" RepositoryEventHandlers get fired before any validation takes place.

I can write validating calls in the handlers directly, but that would be different from how the "after" validation is handled.

Btw. the sequence of event handler calls seems to have changed between Spring Boot 1.3.8 and 1.5.1. In the past, the validation occurred before the @HandleBeforeSave handler. In the 1.5.1 ValidatingRepositoryEventListener fires after the @HandleBeforeSave handlers.

Update:

As mentioned in the comments, there seems to be a ticket in Spring Data REST Jira is open about this.

like image 773
Sergey Shcherbakov Avatar asked Oct 24 '25 14:10

Sergey Shcherbakov


1 Answers

As a workaround:

  1. Create PreflightValidatingRepositoryEventListener which extends ValidatingRepositoryEventListener and annotate it with @Order(Ordered.HIGHEST_PRECEDENCE).

    @Component
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class PreflightValidatingRepositoryEventListener extends ValidatingRepositoryEventListener {
        public PreflightValidatingRepositoryEventListener(ObjectFactory<PersistentEntities> persistentEntitiesFactory) {
            super(persistentEntitiesFactory);
        }
    }
    
  2. Add same validators as for ValidatingRepositoryEventListener

    @Configuration
    @Import(RepositoryRestMvcConfiguration.class)
    public class Config extends RepositoryRestConfigurerAdapter {
    
        @Bean
        @Primary
        public Validator validator() {
            return new LocalValidatorFactoryBean();
        }
    
        @Autowired
        private PreflightValidatingRepositoryEventListener preflightValidatingRepositoryEventListener;
    
        @Override
        public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
            Validator validator = validator();
    
            validatingListener.addValidator("beforeCreate", validator);
            validatingListener.addValidator("beforeSave", validator);
    
            preflightValidatingRepositoryEventListener.addValidator("beforeCreate", validator);
            preflightValidatingRepositoryEventListener.addValidator("beforeSave", validator);
        }
    }
    

NOTE: Validation will be ran twice

like image 194
Ahmed Al Hafoudh Avatar answered Oct 26 '25 06:10

Ahmed Al Hafoudh