2017-02-02 6 views
6

В моем приложении Spring Boot 1.5.1 я пытаюсь настроить поддержку проверки JSR-303/JSR-349.Конфигурация Spring Boot JSR-303/349

я добавил следующие аннотации @NotNull @Size(min = 1) моему методу:

@Service 
@Transactional 
public class DecisionDaoImpl extends BaseDao implements DecisionDao { 

    @Override 
    public Decision create(@NotNull @Size(min = 1) String name, String description, String url, String imageUrl, Decision parentDecision, Tenant tenant, User user) { 
     ... 
    } 

} 

Я пытаюсь вызвать этот метод из моего теста, но это не обязательно от ограничений проверки.

Это мой тест и конфиги:

@SpringBootTest(classes = { TestConfig.class, Neo4jTestConfig.class }) 
@RunWith(SpringRunner.class) 
@Transactional 
public class TenantTest { 

    @Test 
    public void testCreateDecision() { 
     User user1 = userService.createUser("test1", "test1", "[email protected]", null, null); 
     Tenant tenant1 = tenantDao.create("Tenant 1", "Tenant 1 description", false, user1); 

     // the following line should fail on the validation constraint because name parameter is null but it doesn't 
     final Decision rootDecision = decisionDao.create(null, "Root decision 1 description", null, tenant1, user1); 

... 


@Configuration 
@ComponentScan("com.example") 
@SpringBootApplication(exclude={Neo4jDataAutoConfiguration.class}) 
public class TestConfig { 
} 

Что я делаю неправильно и как настроить JSR-303 есть?

ОБНОВЛЕНО

Я добавил

public Decision create(@Valid @NotNull @Size(min = 1) String name, String description, Decision parentDecision, Tenant tenant, User author) { 

, но он по-прежнему не работает

Я добавил к моему @ValidatedDecisionDaoImpl, но он не в настоящее время со следующим исключением:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'decisionDaoImpl': Bean with name 'decisionDaoImpl' has been injected into other beans [criterionGroupDaoImpl,characteristicGroupDaoImpl,tenantDaoImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example. 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:585) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) 
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) 
    ... 43 common frames omitted 

Я также добавил @Lazy аннотации через место, где я мой DecisionDao автоматическое связывание, но сейчас мое испытание терпит неудачу с исключением следующим:

javax.validation.ConstraintDeclarationException: HV000151: A method overriding another method must not alter the parameter constraint configuration, but method public com.example.domain.model.entity.decision.Decision com.example.domain.dao.decision.DecisionDaoImpl.create(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.Long,java.lang.Long,com.example.domain.model.entity.user.User) changes the configuration of public abstract com.example.domain.model.entity.decision.Decision com.example.domain.dao.decision.DecisionDao.create(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.Long,java.lang.Long,com.example.domain.model.entity.user.User). 
    at org.hibernate.validator.internal.metadata.aggregated.rule.OverridingMethodMustNotAlterParameterConstraints.apply(OverridingMethodMustNotAlterParameterConstraints.java:24) 
    at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.assertCorrectnessOfConfiguration(ExecutableMetaData.java:456) 
+0

Относительно этого последнего исключения с OverridingMethodMustNotAlterParameterConstraints, задаваясь вопросом, применяете ли эти же аннотации JSR 303 к базовому интерфейсу DecisionDao, решите это. Возможно, вы можете попробовать применить их только на уровне интерфейса. –

+0

Я переместил ограничения проверки на базовый интерфейс, но затем проверка перестала работать, как и раньше, без каких-либо исключений. – alexanoid

+0

И если вы применяете те же аннотации точно как в интерфейсе, так и в impl? –

ответ

2

Перемещайте проверку интерфейс следующим образом:

import javax.validation.Valid; 
import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 

public interface DecisionDao { 

    Decision create(@Valid @NotNull @Size(min = 1) String name, 
      String description, String url, String imageUrl); 
} 

аннотировать DecisionDaoImpl с @Validated, следующим образом:

import org.springframework.stereotype.Service; 
import org.springframework.validation.annotation.Validated; 

@Service 
@Validated 
public class DecisionDaoImpl extends BaseDao implements DecisionDao { 

    @Override 
    public Decision create(String name, 
      String description, String url, String imageUrl) { 
     System.out.println(name); 
     return new Decision(); 
    } 

} 

Измените тест, чтобы проверить для javax.validation.ConstraintViolationException с помощью assertj или ExpectedException как следует:

import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 

import javax.validation.ConstraintViolationException; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringRunner; 
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; 

@ContextConfiguration(classes = { TenantTest.Config.class }) 
@RunWith(SpringRunner.class) 
public class TenantTest { 

    @Autowired 
    private DecisionDao decisionDao; 

    @Rule 
    public ExpectedException expectedException = ExpectedException.none(); 

    @Test 
    public void testCreateDecisionUsingAssertj() { 
     assertThatExceptionOfType(ConstraintViolationException.class) 
       .isThrownBy(
         () -> decisionDao.create(null, 
           "Root decision 1 description", null, null)); 
    } 

    @Test 
    public void testCreateDecision() { 
     expectedException.expect(ConstraintViolationException.class); 
     decisionDao.create(null, "Root decision 1 description", null, null); 
    } 

    @Configuration 
    public static class Config { 
     @Bean 
     public MethodValidationPostProcessor methodValidationPostProcessor() { 
      return new MethodValidationPostProcessor(); 
     } 

     @Bean 
     public DecisionDao decisionDao() { 
      return new DecisionDaoImpl(); 
     } 
    } 
} 

Убедитесь, что вы гибернации-валидатор в вашем пути к классам наряду с @StanislavL ответ:

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-validator</artifactId> 
</dependency> 

и опциональный зависимость для org.assertj.core.api.Assertions.assertThatExceptionOfType, как:

<dependency> 
    <groupId>org.assertj</groupId> 
    <artifactId>assertj-core</artifactId> 
    <version>3.3.0</version> 
    <scope>test</scope> 
</dependency> 

Для образца Например, вам может ссылаться arpitaggarwal/jsr-303

+0

Да, у меня есть - hibernate-validator 5.2.4.Final. Не работает – alexanoid

+0

@alexanoid проверить мой обновленный ответ. – Arpit

+0

спасибо за ваш ответ.Я добавил '@ Validated' в мой' DecisionDaoImpl', но теперь он терпит неудачу в следующем исключении: 'Bean с именем 'solutionDaoImpl' был добавлен в другие beans [criterionGroupDaoImpl, characterGroupDaoImpl, tenantDaoImpl] в своей исходной версии как часть кругового ссылка, но в конечном итоге была завернута. Это означает, что другие бобы не используют финальную версию компонента. Это часто является результатом чрезмерно нетерпеливого соответствия типов - рассмотрим, например, использование 'getBeanNamesOfType' с выключенным флагом 'allowEagerInit'. ' – alexanoid

1

Вам необходимо @Valid аннотацию

Отмечает свойство, параметр методы или метод return для каскадирования проверки. Ограничения, определенные на объекте и его свойствах, проверяются, когда свойство свойства, параметра метода или метода проверяется.

+0

Я добавил @Valid аннотацию к моему параметру метода, но он все еще не работает. Я обновил свой вопрос. – alexanoid

+0

Не могли бы вы добавить параметр результата BindingResult в конце метода и проверить result.hasErrors() в методе? Похоже, вы ожидаете исключения, но не генерируете исключение, но допускаете некоторые ошибки. – StanislavL

+0

Какая реализация BindingResult должна предоставляться во время вызова метода? Например, я не вызываю метод из Spring MVC. – alexanoid

0

Аннотации ограничений предназначены для применения к JavaBeans. См. http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition

У вас есть аннотация для ограничения @NotNull, @Size и т. Д., Применяемые в DAO. Вы должны создать Java Bean, например. «Лицо», которое обертывает эти атрибуты (имя, описание и т. Д.), Затем передает «Человек» в качестве параметра в метод контроллера. Если вам нужно использовать DAO вместо контроллера, для его проверки необходимо будет выполнить проверку. Вы можете быть по своему усмотрению в этой связи в отношении АОП и т.д., если что-то не изменилось с тех пор этот пост: http://forum.spring.io/forum/spring-projects/container/82643-annotation-driven-jsr-303-validation-on-service-and-dao-tier

Update: Ну, похоже, что это (проверка уровня метод JSR-349) поддерживается в настоящее время см. пример http://blog.codeleak.pl/2012/03/how-to-method-level-validation-in.html, аналогичный ответу Арпита. Обновлено название вопроса, чтобы отразить это последнее JSR.

Смежные вопросы