web-dev-qa-db-ja.com

Spring Boot JSR-303 / 349構成

_Spring Boot 1.5.1_アプリケーションで、JSR-303/JSR-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) {
_

しかし、それでも機能しません

DecisionDaoImplに_@Validated_を追加しましたが、次の例外を除いて失敗します。

_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
_

また、DecisionDaoを自動配線している場所に_@Lazy_アノテーションを追加しましたが、現在、次の例外を除いてテストが失敗します。

_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)
_
7
alexanoid

次のように、検証をインターフェースに移動します。

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();
    }

}

次のように、 assertj または ExpectedException を使用して、テストケースを変更してjavax.validation.ConstraintViolationExceptionを確認します。

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の回答とともに、クラスパスにhibernate-validatorがあることを確認してください。

<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-3 を参照できます。

2
Arpit Aggarwal

制約アノテーションは、JavaBeansに適用されることを目的としています。 http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition を参照してください

制約アノテーションがあります@NotNull@SizeなどがDAO内で適用されます。これらの属性(名前、説明など)をラップするJava Bean、たとえば「Person」)を作成してから、「Person」をパラメーターとしてControllerメソッドに渡す必要があります。必要な場合コントローラの代わりにDAOを使用するには、検証を実行するためにインストルメント化する必要があります。この投稿以降に何か変更がない限り、AOPなどに関しては自分で行うことができます。 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 例として、Arpitの回答に似ています。この最新のJSRを反映するように、質問のタイトルを更新しました。

1
user2066936

@Validアノテーションが必要です

検証カスケード用のプロパティ、メソッドパラメータ、またはメソッドの戻り値の型をマークします。オブジェクトとそのプロパティに定義された制約は、プロパティ、メソッドパラメータ、またはメソッドの戻り値の型が検証されるときに検証されます。

1
StanislavL