web-dev-qa-db-de.com

Spring Boot JSR-303/349 Konfiguration

In meiner Spring Boot 1.5.1-Anwendung versuche ich, die Unterstützung der JSR-303/JSR-349-Validierung zu konfigurieren.

Ich habe meiner Methode die folgenden Anmerkungen @NotNull @Size(min = 1) hinzugefügt:

@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) {
        ...
    }

}

Ich versuche, diese Methode von meinem Test aus aufzurufen, aber die Gültigkeitsbeschränkungen schlagen nicht fehl.

Dies ist mein Test und Configs:

@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 {
}

Was mache ich falsch und wie konfiguriere ich JSR-303 dort?

AKTUALISIERTE

Ich habe hinzugefügt

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

aber es funktioniert immer noch nicht

Ich habe @Validated zu meiner DecisionDaoImpl hinzugefügt, aber es schlägt jetzt mit folgender Ausnahme fehl:

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

Ich habe auch eine @Lazy-Annotation an Stellen hinzugefügt, an denen ich meine DecisionDao automatisch verdrahte. Derzeit schlägt mein Test jedoch mit der folgenden Ausnahme fehl:

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

Verschieben Sie Ihre Validierung wie folgt in die Benutzeroberfläche:

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

Kommentieren Sie Ihre DecisionDaoImpl mit @Validated wie folgt:

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

}

Ändern Sie Ihren Testfall so, dass er mit assertj oder ExpectedException auf javax.validation.ConstraintViolationException überprüft wird:

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

Stellen Sie sicher, dass Sie in Ihrem Klassenpfad hibernate-validator zusammen mit @StanislavL answer haben:

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

Und eine optionale Abhängigkeit für org.assertj.core.api.Assertions.assertThatExceptionOfType als:

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

Zum Beispiel können Sie arpitaggarwal/jsr-303 verweisen.

2
Arpit

Die Einschränkungsannotationen sollen auf JavaBeans angewendet werden. Siehe http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition

Sie haben die Einschränkungsannotation @NotNull, @Size usw. innerhalb des DAO angewendet. Sie müssen eine Java Bean erstellen, z. "Person" umschließt diese Attribute (Name, Beschreibung usw.) und übergibt dann "Person" als Parameter an die Controller-Methode. Wenn Sie ein DAO anstelle eines Controllers verwenden möchten, muss dieses instrumentiert werden, um die Validierung durchzuführen. Sie können diesbezüglich in Bezug auf AOP usw. auf sich allein gestellt sein, sofern sich seit diesem Beitrag nichts geändert hat: http://forum.spring.io/forum/spring-projects/container/82643-annotation-driven -jsr-303-validation-on-service-and-dao-tier

Update : Nun, es sieht so aus, als ob es (Validierung auf Methodenebene JSR-349) jetzt unterstützt wird. Siehe http://blog.codeleak.pl/2012/03/how-to-method-level-validation -in.html Ein Beispiel, ähnlich der Antwort von Arpit. Der Titel der Frage wurde aktualisiert, um diese neueste JSR wiederzugeben.

1
user2066936

Sie benötigen eine @Valid Annotation

Markiert eine Eigenschaft, einen Methodenparameter oder einen Methodenrückgabetyp für die Validierungskaskadierung. Für das Objekt und seine Eigenschaften definierte Einschränkungen werden überprüft, wenn die Eigenschaft, der Methodenparameter oder der Methodenrückgabetyp überprüft werden.

1
StanislavL