Валидатор Spring-Data-Rest

Я пытался добавить весенние валидаторы в проект spring-data-rest.

Я последовал за мной и настроил приложение для начала работы по этой ссылке: http://spring.io/guides/gs/accessing-data-rest/.

... и теперь я пытаюсь добавить пользовательский PeopleValidator, следуя приведенным здесь документам: http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html

Мой пользовательский PeopleValidator выглядит так

package hello;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class PeopleValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public void validate(Object target, Errors errors) {
        errors.reject("DIE");
    }
}

... и мой класс Application.java теперь выглядит так

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public PeopleValidator beforeCreatePeopleValidator() {
        return new PeopleValidator();
    }
}

Я ожидал, что POSTing по URL-адресу http://localhost:8080/people приведет к какой-то ошибке, поскольку PeopleValidator все отклоняет. Однако ошибки не возникает, и валидатор никогда не вызывается.

Я также попытался вручную настроить валидатор, как показано в разделе 5.1 документации spring-data-rest.

Что мне не хватает?


person Robert Greathouse    schedule 20.06.2014    source источник


Ответы (4)


Таким образом, кажется, что события «до / после сохранения» срабатывают только при PUT и PATCH. При POSTing срабатывают события "до / после создания".

Я снова попробовал это вручную, используя переопределение configureValidatingRepositoryEventListener, и это сработало. Я не уверен, что я делаю на работе иначе, чем здесь, дома. Я завтра посмотрю.

Я бы очень хотел услышать, есть ли у других предложения о том, почему это не сработает.

Для записи вот как выглядит новый класс Application.java.

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application extends RepositoryRestMvcConfiguration {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
        validatingListener.addValidator("beforeCreate", new PeopleValidator());
    }
}
person Robert Greathouse    schedule 20.06.2014
comment
Очевидно, событие beforeSave не срабатывает, но событие beforeCreate срабатывает. Мне все равно пришлось подключить его вручную, вместо использования bean-компонента с именем beforeCreatePeopleValidator. - person Robert Greathouse; 22.06.2014
comment
Я нахожу такую ​​же ситуацию, автоматическое обнаружение не работает. - person JBCP; 06.12.2014
comment
У меня также проблема с подобной проблемой - ручное подключение событий работает нормально, автоматическое обнаружение не работает. - person Mikk; 19.12.2014
comment
Я столкнулся с той же проблемой, когда он не был обнаружен автоматически. Я создал на нем JIRA: jira.spring.io/browse/DATAREST-524 - person Daniel Moses; 22.04.2015
comment
Теперь вам нужно расширить RepositoryRestConfigurerAdapter, поскольку версия RepositoryRestMvcConfiguration устарела. - person Arun Karunagath; 14.01.2017

Похоже, что эта функция в настоящее время не реализована (2.3.0), к сожалению, нет констант для имен событий, иначе приведенное ниже решение не было бы таким хрупким.

Configuration добавляет все правильно названные Validator beans к ValidatingRepositoryEventListener, используя правильное событие.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.validation.Validator;

@Configuration
public class ValidatorRegistrar implements InitializingBean {

    private static final List<String> EVENTS;
    static {
        List<String> events = new ArrayList<String>();
        events.add("beforeCreate");
        events.add("afterCreate");
        events.add("beforeSave");
        events.add("afterSave");
        events.add("beforeLinkSave");
        events.add("afterLinkSave");
        events.add("beforeDelete");
        events.add("afterDelete");
        EVENTS = Collections.unmodifiableList(events);
    }

    @Autowired
    ListableBeanFactory beanFactory;

    @Autowired
    ValidatingRepositoryEventListener validatingRepositoryEventListener;

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, Validator> validators = beanFactory.getBeansOfType(Validator.class);
        for (Map.Entry<String, Validator> entry : validators.entrySet()) {
            EVENTS.stream().filter(p -> entry.getKey().startsWith(p)).findFirst()
                    .ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
        }
    }
}
person Andreas    schedule 19.05.2015

Немного укол в темноте - я не использовал spring-data-rest. Однако, прочитав руководство, которому вы следуете, я думаю, проблема в том, что вам нужен PersonValidator, а не PeopleValidator. Переименуйте все соответственно:

PersonValidator

package hello;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class PersonValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public void validate(Object target, Errors errors) {
        errors.reject("DIE");
    }
}

Приложение

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public PersonValidator beforeCreatePersonValidator() {
        return new PersonValidator();
    }
}
person Muel    schedule 20.06.2014
comment
Спасибо за предложение. Но, похоже, это не имело значения. Я повторил это вручную, и это сработало. Мне придется снова попробовать это в моем проекте, когда я приступлю к работе. - person Robert Greathouse; 20.06.2014
comment
@Muel - как ты это тестировал? - person Suleman khan; 03.09.2015

Другой способ сделать это - использовать обработчики с аннотациями, указанные здесь http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/events-chapter.html#d5e443

Вот пример использования аннотированных обработчиков:

import gr.bytecode.restapp.model.Agent;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.HandleBeforeSave;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.springframework.stereotype.Component;

@Component
@RepositoryEventHandler(Agent.class)
public class AgentEventHandler {

    public static final String NEW_NAME = "**modified**";

    @HandleBeforeCreate
    public void handleBeforeCreates(Agent agent) {
            agent.setName(NEW_NAME);
    }

    @HandleBeforeSave
    public void handleBeforeSave(Agent agent) {
        agent.setName(NEW_NAME + "..update");
    }
}

Пример взят из github отредактировано для краткости.

person Amit    schedule 06.08.2015
comment
Лучше использовать валидаторы, чем обработчики. - person Ignacio; 15.06.2019