In my Spring Boot 1.5.1
application I'm trying to configure support of JSR-303 / JSR-349 validation.
I have added a following annotations @NotNull @Size(min = 1)
to my method:
@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) {
...
}
}
I'm trying to invoke this method from my test, but it does not fail on the validation constraints.
This is my test and configs:
@SpringBootTest(classes = { TestConfig.class, Neo4jTestConfig.class })
@RunWith(SpringRunner.class)
@Transactional
public class TenantTest {
@Test
public void testCreateDecision() {
User user1 = userService.createUser("test1", "test1", "test1@test.com", 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 {
}
What am I doing wrong and how to configure JSR-303 there ?
UPDATED
I have added
public Decision create(@Valid @NotNull @Size(min = 1) String name, String description, Decision parentDecision, Tenant tenant, User author) {
but it still doesn't work
I have added @Validated
to my DecisionDaoImpl
but it fails now with a following exception:
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
I have also added @Lazy
annotation in a places where I'm autowiring my DecisionDao
but right now my test fails with a following exception:
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)
The constraint annotations are meant to applied to JavaBeans. See http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition
You have the constraint annotation
@NotNull
,@Size
, etc. applied within the DAO. You must create a Java Bean, e.g. "Person", that wraps those attributes (name, description, etc.), then pass "Person" as a parameter to the Controller method. If you need to use a DAO instead of a controller, it will need to be instrumented to perform the validation. You may be on your own in that regard with regard to AOP, etc., unless something has changed since this post: http://forum.spring.io/forum/spring-projects/container/82643-annotation-driven-jsr-303-validation-on-service-and-dao-tierUpdate: Well, looks like it (method level validation JSR-349) is supported now see http://blog.codeleak.pl/2012/03/how-to-method-level-validation-in.html for an example, similar to Arpit's answer. Updated title of question to reflect this latest JSR.
Move your validation to interface, as follows:
Annotate your
DecisionDaoImpl
with@Validated
, as follows:Modify your test case to verify for
javax.validation.ConstraintViolationException
using assertj or ExpectedException, as follows:Make sure you have hibernate-validator in your classpath along with @StanislavL answer:
And an optional dependency for
org.assertj.core.api.Assertions.assertThatExceptionOfType
, as:For sample example, you can refer arpitaggarwal/jsr-303
You need
@Valid
annotationMarks a property, method parameter or method return type for validation cascading. Constraints defined on the object and its properties are be validated when the property, method parameter or method return type is validated.