Spring Data MongoDB выполняет проверку * после * сохранения в хранилище - PullRequest
0 голосов
/ 21 января 2019

У меня есть простой @Document, который при сохранении в MongoDB с использованием spring-data-mongodb не применяет никаких проверочных аннотаций.

Документ:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

import javax.validation.constraints.NotNull;
import java.time.Instant;

@Accessors(chain = true)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "calls")
public class Call {

    @Id
    private UUID id;

    @NotBlank("Owner ID is required")
    @Indexed
    private String ownerId;

    @NotNull
    private Instant createdAt;

}

Конфигурация валидатора:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class MongoValidator {

    @Bean
    public ValidatingMongoEventListener validatingMongoEventListener() {
        return new ValidatingMongoEventListener(validator());
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

}

Когда я пытаюсь сохранить в MongoRepository<Call, UUID>, я получаю ожидаемое исключение:

javax.validation.ConstraintViolationException: null
    at org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener.onBeforeSave(ValidatingMongoEventListener.java:67)
    at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:88)
    at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:31)

Но только после документ сохраняется в хранилище, а не до.

Есть идеи, как выполнить валидатор перед сохранением?

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Понял это после пошагового выполнения кода в MongoTemplate.

Я бы переопределил @Bean для ApplicationEventMulticaster:

@Bean
ApplicationEventMulticaster applicationEventMulticaster() {
    SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
    eventMulticaster.setErrorHandler(TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER); // don't want to prevent further processing of event
    return eventMulticaster;
}

Как следствие, выброшено исключениев BeforeSaveEvent слушатель, вызванный в MongoTemplate, не останавливал метод MongoTemplate.doSave.

0 голосов
/ 21 января 2019

Вы можете переопределить RestAdapter of Spring следующим образом:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class RestValidationConfiguration extends RepositoryRestConfigurerAdapter {

@Bean
@Primary
/**
 * Create a validator to use in bean validation - primary to be able to autowire without qualifier
 */
Validator validator() {
    return new LocalValidatorFactoryBean();
}


@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
    Validator validator = validator();
    //bean validation always before save and create
    validatingListener.addValidator("beforeCreate", validator);
    validatingListener.addValidator("beforeSave", validator);
}
}
...